« Link: Intercepting UITableView Touches | Main | Encrypted iPhone Applications »
Sunday
Feb142010

Building Static Libraries to Share Code on iPhone AND Mac OS X Projects


There are numerous good resources out there, like Clint Harris’ excellent tutorial, that describe how one can share common code across iPhone projects by keeping the shared code in a separate project, and including it in your various projects using the cross-project reference technique. The technique is further complicated due to the need to use static libraries for iPhone projects, as dynamic libraries are not allowed by Apple in iPhone apps.

Despite the nuisance, the technique works pretty well, and we’ve been using it as detailed here on Mobile Orchard for building OpenSSL and SQLCipher for iPhone projects. However, recently we started sharing a lot of our SQLCipher-specific code (like our custom data model, etc) with our upcoming Mac OS X application, Strip Sync. Therefore, numerous libraries we were sharing were linked against our openssl-xcode build, which is necessarily a little customized. Using the shared library there worked great for development (“Debug”) builds, but came to a screeching halt once it came time to do a “Release” build.

The Release build process sets up a universal binary. Thus, using the common technique described above, the linker ends up trying to link a PPC build of your binary against our static openssl library, which was only building either i386, or ARMv6. If you are using the code and instructions we described in our SQLCipher tutorial to use SQLCipher in your iPhone project, and you decide to use that technique for a Mac OS X project, this problem will affect you (if you are building the standard universal binary on release builds).

Happily, we’ve got a fix! Once we realized what was going on, I mentioned it to Stephen, who put together our handy openssl-xcode project, that provides you a drop-in way of setting up the static library for iPhone development. In a few minutes he hooked up a new version of the Run Script build phase that sets up the static library to do the usual for iPhone builds, but to detect a universal binary build and do the right thing:


set

if [ "$SDKROOT" != "" ]; then
ISYSROOT="-isysroot $SDKROOT"
fi

## this is a universal build
if [ "$ARCHS_STANDARD_32_BIT" = "i386 ppc" ]; then

mkdir -p temp-universal

BUILDARCH="ppc"
echo "***** BUILDING UNIVERSAL ARCH $BUILDARCH ******"
make clean
./config -openssldir="$BUILD_DIR"
make CC=$PLATFORM_DEVELOPER_BIN_DIR/gcc-4.0 CFLAG="-D_DARWIN_C_SOURCE -arch $BUILDARCH $ISYSROOT" SHARED_LDFLAGS="-arch $BUILDARCH -dynamiclib"
cp libcrypto.a temp-universal/$BUILDARCH-libcrypto.a
cp libssl.a temp-universal/$BUILDARCH-libssl.a

BUILDARCH="i386"
echo "***** BUILDING UNIVERSAL ARCH $BUILDARCH ******"
make clean
./config -openssldir="$BUILD_DIR"
make CC=$PLATFORM_DEVELOPER_BIN_DIR/gcc-4.0 CFLAG="-D_DARWIN_C_SOURCE -arch $BUILDARCH $ISYSROOT" SHARED_LDFLAGS="-arch $BUILDARCH -dynamiclib"
cp libcrypto.a temp-universal/$BUILDARCH-libcrypto.a
cp libssl.a temp-universal/$BUILDARCH-libssl.a

lipo -create temp-universal/*-libcrypto.a -output libcrypto.a
lipo -create temp-universal/*-libssl.a -output libssl.a
else
BUILDARCH=$ARCHS
echo "***** BUILDING ARCH $BUILDARCH ******"
make clean
./config -openssldir="$BUILD_DIR"
make CC=$PLATFORM_DEVELOPER_BIN_DIR/gcc-4.0 CFLAG="-D_DARWIN_C_SOURCE -arch $BUILDARCH $ISYSROOT" SHARED_LDFLAGS="-arch $BUILDARCH -dynamiclib"
fi

ranlib libcrypto.a
ranlib libssl.a
cp libcrypto.a libssl.a "$BUILT_PRODUCTS_DIR"
exit 0

We’ve updated the Github project with this change, so if you are using this technique and openssl-xcode, you can simply download the latest (or pull from github master), and drag and drop the new project file into your XCode build directory and be off and running.

Again, the previous technique worked just fine for sharing code across iPhone projects, but doing a universal build of the static library is absolutely necessary if you use the same shared code in your Mac OS X project and you try to link it against a universally-built binary.

Zetetic is the creator of the encrypted iPhone data vault and password manager Strip and the open source encryption-enhanced database engine SQLCipher.

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>