1

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
Community
  • 1
  • 1
egrunin
  • 24,650
  • 8
  • 50
  • 93

3 Answers3

4

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

Community
  • 1
  • 1
Guillaume
  • 21,685
  • 6
  • 63
  • 95
1

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.

egrunin
  • 24,650
  • 8
  • 50
  • 93
1

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()

Steven R. Loomis
  • 4,228
  • 28
  • 39
  • Not sure we're talking about the same thing--I have to build the code files for three different processors or it won't run. (I know that libicudata.a is just data, I've already got that down to 3.5M). But I see from the docs that static linking should be smart enough to prune the code I'm not using, so I guess I will try a smart binary after all. – egrunin Jan 12 '12 at 18:23
  • It looks like you're suggesting I (in effect) bundle three builds of ICU, only one of which will be used at runtime. If this were a desktop app I wouldn't care, but if the app goes over 20MB Apple won't allow "over the air" distribution, which is a requirement. – egrunin Jan 12 '12 at 21:15
  • No, I'm not suggesting bundling 3 builds. I was suggesting not building the data as a library, but using the 'stub' (nearly empty) data library that icu/source/stubdata builds. Then the .dat file can be shared among anything that has the same endianness. Although, re-reading the other answer, if you build a multi architecture static library, your final build should only be what's needed. – Steven R. Loomis Jan 13 '12 at 18:46