3rd party libraries used by iPhone applications are required to be linked statically. In order to build such a library for the device and simulator you need to set up your environment such that it will cross compile for the two different environments. This is as simple as using the following set of ‘exports’ as defined below.

# Defines to set up environment
export DEVROOT=${ROOTDIR}/Platforms/${PLATFORM}.platform/Developer
export SDKROOT=${DEVROOT}/SDKs/${PLATFORM}${MAX_VERSION}.sdk
export CC=$DEVROOT/usr/bin/gcc
export LD=$DEVROOT/usr/bin/ld
export CPP=$DEVROOT/usr/bin/cpp
export CXX=$DEVROOT/usr/bin/g++
export AR=$DEVROOT/usr/bin/ar
export LIBTOOL=$DEVROOT/usr/bin/libtool
export AS=$DEVROOT/usr/bin/as
export NM=$DEVROOT/usr/bin/nm
export CXXCPP=$DEVROOT/usr/bin/cpp
export RANLIB=$DEVROOT/usr/bin/ranlib
export OPTFLAG="-O${OPT}"
export COMMONFLAGS="${ARCH} -pipe $OPTFLAG -gdwarf-2 -no-cpp-precomp -mthumb -isysroot ${SDKROOT} -miphoneos-version-min=${MIN_VERSION}"
export LDFLAGS="${COMMONFLAGS} -L${HOME}${SDKROOT}/usr/lib"
export CFLAGS="${COMMONFLAGS} -fvisibility=hidden"
export CXXFLAGS="${COMMONFLAGS} -fvisibility=hidden -fvisibility-inlines-hidden"

This uses a few defines which need to be different for the device vs. simulator. Below are what you might want to use for each one. Note that MIN_VERSION, MAX_VERSION and OPT can all be set to control what SDK versions and the level of optimisation is used.

Device:

# Variables
export ROOTDIR="/Developer"
export PLATFORM="iPhoneOS"
export ARCH="-arch armv6 -arch armv7"
export MIN_VERSION="3.1"
export MAX_VERSION="4.0"
export OPT="3"

Simulator:

# Variables
export ROOTDIR="/Developer"
export PLATFORM="iPhoneSimulator"
export ARCH="-arch i386"
export MIN_VERSION="3.1"
export MAX_VERSION="4.0"
export OPT="3"

Once you have set the environment, you just need to use ‘make’ to build the library. If the library is using autoconf, then you will need to use the following ‘./configure’ options:

Device:

./configure --host=arm-apple-darwin9 --prefix=~$SDKROOT --enable-shared=no --disable-dependency-tracking

[Note: --disable-dependency-tracking is required because gcc can't use dependency tracking when building for 2 architectures at the same time (i.e. armv6 and armv7).]

Simulator:

./configure --host=i386-apple-darwin --prefix=~$SDKROOT --enable-shared=no

Then just use ‘make’ and ‘make install’ to build the library! It really is as easy as that :-D .

[Other libraries may require other configure options, but I can't cover them all here as they are often different]

EDIT: I’ve edited the defines above to be a bit clearer and factor out the common bits from the device/simulator.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • Twitter

4 Responses to “Compiling Static Libraries for iPhone / Simulator”

  1. Why the “~” before $SDKROOT? Also wondering why the -no-cpp-precomp. Don’t you usually also want to pass in the references to the SDK frameworks via “-F”? Also some headers are not in the simulator SDK (e.g. in_systm.h) I guess that needs another “-I”.

    Currently fighting myself with this stuff :)

  2. Hi Torsten,

    The ~ is to put it into your home directory. Sometimes that works, sometimes you need to specify it directly with /Users/ etc.

    The -no-cpp-precomp came from somewhere else to be honest. I’m a little vague on what it *actually* does, but it seems that for most libraries it’s required / works.

    You don’t want to pass in references to the SDK frameworks usually. That would only be required if the library you are compiling for is specially coded for the iPhone and in which case you probably wouldn’t be reading this anyway because they would have created the Makefile specially for the iPhone.

    Do you need any specific help with the package you are trying to compile?

  3. Evan Stachowiak says:

    Hi Matt,

    I’m trying to statically compile libical. Your directions work great for the Simulator, but I’m getting an error for Device. Here is my error:
    cc1: error: unrecognized command line option “-arch”

    Wondering if you had any ideas about this?

    Also may want to consider making into Universal Binary:
    http://developer.apple.com/mac/library/technotes/tn2005/tn2137.html

    If only I had two binaries that compiled I could test lipo out as well…

  4. @Evan – Yes I use lipo quite a lot to make a universal (fat) library. It’s useful to be able to just have 1 file that can be used for armv6, armv7 or i386.

    As for your unknown -arch problem – could you provide more on the error, such as the command line that gcc was doing at the time please?

Leave a Reply