egrunin
egrunin

Reputation: 25083

How to configure a library so it runs in the Xcode iOS Simulator?

I've got an iPhone app that runs on the device. Now I need to run it in the Simulator.

It uses an open source project (http://site.icu-project.org/), which I build from the command line to create arm-compatible .a files. I can link these with my iPhone project, and it runs on the device.

If I switch the target to Simulator, the build fails, as I expected:

ld: warning: in libicudata.a, file was built for unsupported file format which is not the architecture being linked (i386)

But if I use libs compiled for local use (x86_64), I get the same error, which has got be baffled. Do I have to specify a third architecture for the Simulator? Which one? How do I set the configuration?

For reference, this is how I configured the icu project for the two different targets: How to build ICU so I can use it in an iPhone app?

Edited to add:

As Guillaume suggested (and Connect iPhone App to PostgreSQL Using Libpq confirmed), I now see that the emulator needs a 32-bit build. So that's the last part: how do I set the configuration?

The library has a standard configure script, as far as I know, but I'm still pretty new at this.

Edited to add:

I've gotten this far, but the references to i686 are obviously wrong.

I don't know if i386 is considered a cross-compile, if it is I need "host" and "target" options, too.

ICU_PATH=/Users/eric.grunin/Documents/dev/icu2

DEVROOT=/Developer/Platforms/iPhoneSimulator.platform/Developer
SDKROOT=$DEVROOT/SDKs/iPhoneSimulator4.3.sdk
SYSROOT=$SDKROOT

ICU_FLAGS="-I$ICU_PATH/source/common/ -I$ICU_PATH/source/tools/tzcode/ "

export CXXPP=
export CXXPPFLAGS=
export CPPFLAGS="-I$SDKROOT/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I$SDKROOT/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I$SDKROOT/usr/include/ -I$SDKROOT/usr/include/c++/4.2.1/armv7-apple-darwin10/ -I./include/ -miphoneos-version-min=2.2 $ICU_FLAGS"

export CFLAGS="$CPPFLAGS -pipe -no-cpp-precomp -isysroot $SDKROOT"
export CPP="$DEVROOT/usr/bin/cpp $CPPFLAGS"
export CXXFLAGS="$CFLAGS" 

export CC="$DEVROOT/usr/llvm-gcc-4.2/bin/i686-apple-darwin10-llvm-gcc-4.2"
export CXX="$DEVROOT/usr/llvm-gcc-4.2/bin/i686-apple-darwin10-llvm-g++-4.2"
export LDFLAGS="-L$SDKROOT/usr/lib/ -isysroot $SDKROOT -Wl,-dead_strip -miphoneos-version-min=2.0"

cd $ICU_PATH
mkdir simbuild
cd simbuild

$ICU_PATH/source/configure --enable-static --disable-shared 
gnumake

Upvotes: 1

Views: 5811

Answers (3)

egrunin
egrunin

Reputation: 25083

This is how I got it to work. I'm putting it here so I can look it up later.

It's likely this is imperfect, feel free to correct it. Comments try to separate what's generic from what's specific to the ICU library I was building.

// This is is required by the ICU configure step

# must be ABSOLUTE PATH
ICU_PATH=/Users/eric.grunin/Documents/dev/icu2

// First crucial bit: specify the Simulator

DEVROOT=/Developer/Platforms/iPhoneSimulator.platform/Developer
SDKROOT=$DEVROOT/SDKs/iPhoneSimulator4.3.sdk
SYSROOT=$SDKROOT

// for convenience

ICU_FLAGS="-I$ICU_PATH/source/common/ -I$ICU_PATH/source/tools/tzcode/ "

export CXXPP=
export CXXPPFLAGS=

// current version of gcc is missing some #include files, we have to get them elsewhere

export CPPFLAGS="-I$SDKROOT/usr/include/c++/4.2.1/i686-apple-darwin10/ -I$SDKROOT/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I$SDKROOT/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I$SDKROOT/usr/include/ -I$SDKROOT/usr/include/c++/4.2.1/armv7-apple-darwin10/ -I./include/ -miphoneos-version-min=2.2 $ICU_FLAGS"

// MUST specify -arch i386

export CFLAGS="$CPPFLAGS -pipe -arch i386 -no-cpp-precomp -isysroot $SDKROOT"
export CPP="$DEVROOT/usr/bin/cpp $CPPFLAGS"
export CXXFLAGS="$CFLAGS" 

export CC="$DEVROOT/usr/bin/gcc"
export CXX="$DEVROOT/usr/bin/g++"

// MUST add -arch i386 here.
// Also: to avoid "undefined symbol: _Unwind_Resume", add -lgcc_eh

export LDFLAGS="-arch i386 -L$SDKROOT/usr/lib/ -lgcc_eh -isysroot $SDKROOT -Wl,-dead_strip -miphoneos-version-min=2.0"

cd $ICU_PATH
mkdir simbuild
cd simbuild

// Not sure if --host is really needed

$ICU_PATH/source/configure --enable-static --disable-shared --host=i686-apple-darwin10
gnumake

I'm probably not going to make a fat binary, because the ICU library is already very large and I need to keep the final app as small as possible.

Edited to add

I tried the fat library approach: it tripled the size of my app, alas.

Upvotes: 1

Steven R. Loomis
Steven R. Loomis

Reputation: 4350

That's just the data library. You don't need to build it several times. Use --with-data-packaging=archive when you build ICU, and then it will generate a file icudt*.dat .. when your app starts up, call u_setDataDirectory() to tell it which directory contains that .dat file. u_setDataDirectory()

Upvotes: 1

Guillaume
Guillaume

Reputation: 21736

You need to build a fat library: a fat library is a library that embed the code of many architectures in one file.
For the devices, you need to add the architectures armv6 and armv7. For the simulator, i386.

Look into this answer for details and a script on how to do this from Xcode: https://stackoverflow.com/a/3647187/272342

Upvotes: 4

Related Questions