Building a static library that works on the iPhone and the simulator

Apple’s iPhone simulator runs really smooth and fast. This is because they aren’t emulating the ARM code on your Mac, they’re actually building x86 binaries that will run in the simulator.

Because of this, code written for the iPhone needs to be compiled twice, once for the simulator and once for the device. This makes working with static libraries a bit of a pain, because you need two of them, one for each architecture.

Luckily, it’s possible to build a “universal” binary that will work with both architectures. Apple did this during their switch from PowerPC to Intel.

I found the directions in this StackOverflow post.

  • All you need to do is create a new static library target.
  • Add a “Run Script” build phase.
  • Copy and paste this script in.
  • Your build output should be in a folder labeled Debug_universal or Release_universal

# Version 2.0 (updated for Xcode 4, with some fixes)

# Changes:

# - Works with xcode 4, even when running xcode 3 projects (Workarounds for apple bugs)

# - Faster / better: only runs lipo once, instead of once per recursion

# - Added some debugging statemetns that can be switched on/off by changing the DEBUG_THIS_SCRIPT variable to "true"

# - Fixed some typos

#

# Purpose:

# Create a static library for iPhone from within XCode

# Because Apple staff DELIBERATELY broke Xcode to make this impossible from the GUI (Xcode 3.2.3 specifically states this in the Release notes!)

# ...no, I don't understand why they did this!

#

# Author: Adam Martin - http://twitter.com/redglassesapps

# Based on: original script from Eonil (main changes: Eonil's script WILL NOT WORK in Xcode GUI - it WILL CRASH YOUR COMPUTER)

#

# More info: see this Stack Overflow question: http://stackoverflow.com/questions/3520977/build-fat-static-library-device-simulator-using-xcode-and-sdk-4

#################[ Tests: helps workaround any future bugs in Xcode ]########

#

DEBUG_THIS_SCRIPT="false"

if [ $DEBUG_THIS_SCRIPT = "true" ]

then

echo "########### TESTS #############"

echo "Use the following variables when debugging this script; note that they may change on recursions"

echo "BUILD_DIR = $BUILD_DIR"

echo "BUILD_ROOT = $BUILD_ROOT"

echo "CONFIGURATION_BUILD_DIR = $CONFIGURATION_BUILD_DIR"

echo "BUILT_PRODUCTS_DIR = $BUILT_PRODUCTS_DIR"

echo "CONFIGURATION_TEMP_DIR = $CONFIGURATION_TEMP_DIR"

echo "TARGET_BUILD_DIR = $TARGET_BUILD_DIR"

fi

#####################[ part 1 ]##################

# First, work out the BASESDK version number (NB: Apple ought to report this, but they hide it)

# (incidental: searching for substrings in sh is a nightmare! Sob)

SDK_VERSION=$(echo ${SDK_NAME} | grep -o '.\{3\}$')

# Next, work out if we're in SIM or DEVICE

if [ ${PLATFORM_NAME} = "iphonesimulator" ]

then

OTHER_SDK_TO_BUILD=iphoneos${SDK_VERSION}

else

OTHER_SDK_TO_BUILD=iphonesimulator${SDK_VERSION}

fi

echo "XCode has selected SDK: ${PLATFORM_NAME} with version: ${SDK_VERSION} (although back-targetting: ${IPHONEOS_DEPLOYMENT_TARGET})"

echo "...therefore, OTHER_SDK_TO_BUILD = ${OTHER_SDK_TO_BUILD}"

#

#####################[ end of part 1 ]##################

#####################[ part 2 ]##################

#

# IF this is the original invocation, invoke WHATEVER other builds are required

#

# Xcode is already building ONE target...

#

# ...but this is a LIBRARY, so Apple is wrong to set it to build just one.

# ...we need to build ALL targets

# ...we MUST NOT re-build the target that is ALREADY being built: Xcode WILL CRASH YOUR COMPUTER if you try this (infinite recursion!)

#

#

# So: build ONLY the missing platforms/configurations.

if [ "true" == ${ALREADYINVOKED:-false} ]

then

echo "RECURSION: I am NOT the root invocation, so I'm NOT going to recurse"

else

# CRITICAL:

# Prevent infinite recursion (Xcode sucks)

export ALREADYINVOKED="true"

echo "RECURSION: I am the root ... recursing all missing build targets NOW..."

Page 1 of 2 | Next page