如何构建ICU以便我可以在iPhone应用程序中使用它?

egr*_*nin 14 sqlite iphone icu ios

如何配置和构建ICU,以便将其链接到我的iPhone应用程序?

我正在维护一个使用SQLite数据库的iPhone应用程序.现在我必须编译ICU支持enabled(SQLITE_ENABLE_ICU).我有最新的ICU来源.

configure我正在使用的标志:

./configure --target=arm-apple-darwin --enable-static --disable-shared
Run Code Online (Sandbox Code Playgroud)

之后,运行gnumake没有错误.

然后我将库添加到我的Xcode项目中.但是当我构建时,我得到50行:

Undefined symbols:
  "_uregex_close_48", referenced from:
      _icuRegexpDelete in libsqlite3-cerod.a(sqlite3_cerod.o)
  "_ubrk_current_48", referenced from:
      _icuNext in libsqlite3-cerod.a(sqlite3_cerod.o)
  "_ucol_strcoll_48", referenced from:
      _icuCollationColl in libsqlite3-cerod.a(sqlite3_cerod.o)
  "_u_isspace_48", referenced from:
      _icuRegexpFunc in libsqlite3-cerod.a(sqlite3_cerod.o)
  "_utf8_countTrailBytes_48", referenced from:
      _utf8_countTrailBytes_48$non_lazy_ptr in libsqlite3-cerod.a(sqlite3_cerod.o)
     (maybe you meant: _utf8_countTrailBytes_48$non_lazy_ptr)
  "_ubrk_next_48", referenced from:
      _icuNext in libsqlite3-cerod.a(sqlite3_cerod.o)
Run Code Online (Sandbox Code Playgroud)

知道我做错了什么吗?

编辑添加:

当我将库添加到项目中时(右键单击项目名称,然后添加现有...),我得到:

ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicudata.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicui18n.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicuio.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicule.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libiculx.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicutu.a, file was built for unsupported file format which is not the architecture being linked (i386)
ld: warning: in /Users/eric.grunin/dev/iOS/icu/source/lib/libicuuc.a, file was built for unsupported file format which is not the architecture being linked (i386)
Run Code Online (Sandbox Code Playgroud)

这就是为什么我认为我正在错误地构建库.好像它在说:

  • 它无法分辨.a文件的构建方式
  • libsqlite3-cerod.a是为i386构建的

我不明白这两种可能性,但我是iPhone开发的新手.

编辑添加

我尝试了@Sergio Moura的解决方案,并得到了我的评论中提到的错误.

我试过了@ sergio的解决方案.但我仍然得到相同的错误,从:

ld: warning: in /Users/eric.grunin/dev/iOS/icu/iosbuild/lib/libicudata.a, file was built for unsupported file format which is not the architecture being linked (i386)
Run Code Online (Sandbox Code Playgroud)

我可能会告诉Xcode错误的东西吗?我右键单击项目名称,然后选择"添加 - >现有文件",然后.a从中选择六个或七个文件/icu/iosbuild/lib.这是正确的过程吗?

注意:

@sergio推荐configure --host=arm-apple-darwin,@ Sergio Moura正在使用configure --target=arm-apple-darwin.唉,两者都没有区别.

编辑#2

定位设备(而不是模拟器)解决了除链接错误之外的所有错误!这是剩下的:

Undefined symbols for architecture armv6:
  "___sync_synchronize", referenced from:
      _ucol_initUCA_48 in libicui18n.a(ucol_res.ao)
      udata_getHashTable()      in libicuuc.a(udata.ao)
      _umtx_init_48 in libicuuc.a(umutex.ao)
      _initCache in libicuuc.a(uresbund.ao)
      icu_48::hasService()       in libicui18n.a(coll.ao)
      _ucol_initInverseUCA_48 in libicui18n.a(ucol_bld.ao)
      icu_48::locale_set_default_internal(char const*)in libicuuc.a(locid.ao)
      ...
ld: symbol(s) not found for architecture armv6
Run Code Online (Sandbox Code Playgroud)

之前是这些警告的级联:

ld: warning: CPU_SUBTYPE_ARM_ALL subtype is deprecated: /Users/eric.grunin/dev/iOS/icu/iosbuild/lib/libicuuc.a(resbund.ao)
ld: warning: CPU_SUBTYPE_ARM_ALL subtype is deprecated: /Users/eric.grunin/dev/iOS/icu/iosbuild/lib/libicuuc.a(ustrfmt.ao)
Run Code Online (Sandbox Code Playgroud)

编辑#3

@Stephen R. Loomis建议我#define U_HAVE_GCC_ATOMICS从改变10(in platform.h)没有任何区别,唉.我也意识到error(not found for architecture arm6)的最后一行并不意味着它会起作用arm7,这只是一个fyi,这是一个交叉编译.当我指定arm7构建时,它失败了相同的消息.唉.

编辑#4

成功!

总结:@ sergio的构建标志基本上是正确的.我在-os build的CFLAGS中添加了-DU_HAVE_GCC_ATOMICS = 0.我做错的一件事是没有意识到我需要交叉编译库来创建一个设备构建.

我没有尝试过为模拟器重复这个,但这超出了我的问题的范围.

特别感谢Steven R. Loomis投球,并感谢Sergio Moura让事情顺利进行.

ser*_*gio 5

编辑:

我可以证实,如果你这样做,正如Steven R. Loomis所说:

  1. 在icu/source/common/unicode/platform.h中将U_HAVE_GCC_ATOMICS设置为0

  2. 使distclean

  3. sh cross_configure.sh(使用我的脚本,即如果你正在使用它)

问题应该解决.实际上,如果不这样做,构建的库包含违规的未定义符号:

sergio@sfogliatella$ nm -a ./lib/libicuuc.a | grep __sync_
     U ___sync_synchronize
     U ___sync_val_compare_and_swap_4
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
     U ___sync_synchronize
Run Code Online (Sandbox Code Playgroud)

遵循上述建议后,这是同一命令的结果:

sergio@sfogliatella$ nm -a ./lib/libicuuc.a | grep __sync_
nm: no name list
nm: no name list
Run Code Online (Sandbox Code Playgroud)

所以,当然,二进制文件中不存在违规符号.

结束编辑.

针对iOS的交叉编译libicu需要两个单独的步骤:

  1. 在构建目录中为主机(MacOS)编译libicu;

  2. 通过指定交叉编译目录来交叉编译iOS的libicu.

第1步是必要的原因是libicu会自行引导一下,即它会编译一些中间工具,然后在构建过程的其余部分使用它们; 这些工具需要在主机平台上运行,因此它们是可用的.

好吧,总而言之,您可以按照以下步骤操作(1.为主机编译):

$ cd $icu
$ mkdir hostbuild
$ cd hostbuild
$ ../icu/source/configure <configure settings you need>
$ gnumake
Run Code Online (Sandbox Code Playgroud)

完成后,就可以进行交叉编译了(2.为iOS编译):

$ cd $icu  (or cd ../ from the previous directory)
$ mkdir iosbuild
$ cd iosbuild
$ sh ../cross_configure_icu.sh
$ gnumake
Run Code Online (Sandbox Code Playgroud)

cross_configure_icu.shshell脚本在哪里类似于Sergio Moura上面提出的那些,但是为libicu定制并使用更高级的llvm编译器:

DEVROOT=/Developer/Platforms/iPhoneOS.platform/Developer
SDKROOT=$DEVROOT/SDKs/iPhoneOS4.3.sdk
SYSROOT=$SDKROOT

ICU_PATH=<ABSOLUTE_PATH_TO_YOUR_ICU_DIR>
ICU_FLAGS="-I$ICU_PATH/source/common/ -I$ICU_MYSRC/source/tools/tzcode/ "

export CXXPP=
export CXXPPFLAGS=
export CPPFLAGS="-I$SDKROOT/usr/lib/gcc/arm-apple-darwin10/4.2.1/include/ -I$SDKROOT/usr/llvm-gcc-4.2/lib/gcc/arm-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/arm-apple-darwin10-llvm-gcc-4.2"
export CXX="$DEVROOT/usr/llvm-gcc-4.2/bin/arm-apple-darwin10-llvm-g++-4.2"
export LDFLAGS="-L$SDKROOT/usr/lib/ -isysroot $SDKROOT -Wl,-dead_strip -miphoneos-version-min=2.0"

sh $ICU_PATH/source/configure --host=arm-apple-darwin --enable-static --disable-shared -with-cross-build=$ICU_PATH/hostbuild
Run Code Online (Sandbox Code Playgroud)

在上面的脚本()中,ICU_PATH是一个绝对路径,因为libicu configure需要该with-cross-build选项.再次,检查SDK和编译器的值,但这应该适用于4.3.

最后,您应该考虑到Apple已经(一半)拒绝了至少一个与libicu链接的应用程序,因为它使用了保留的API.看看这个SO主题.

编辑:

听到你可以编译的快乐!

现在,到链接问题.

首先,请检查libicu库的格式是否正确:

sergio@sfogliatella$ lipo -info ./lib/libicuuc.a 
Run Code Online (Sandbox Code Playgroud)

输出应该是(对于任何libs):

input file ./lib/libicuuc.a is not a fat file
Non-fat file: ./lib/libicuuc.a is architecture: arm
Run Code Online (Sandbox Code Playgroud)

如果没问题,那么接下来的问题是:你是在为模拟器还是为设备构建?模拟器需要i386库,设备臂库...来自您显示的错误消息:

ld:warning:...文件是为不支持的文件格式构建的,而不是链接的体系结构(i386)

在我看来,你正在建立模拟器...因为你将需要"正常"的macos x libs ...