如何build立ICU,以便在iPhone应用程序中使用它?
我如何configuration和build立ICU,以便将其链接到我的iPhone应用程序?
我正在维护一个使用SQLite数据库的iPhone应用程序。 现在我必须编译启用ICU支持( SQLITE_ENABLE_ICU
)。 我有最新的ICU来源。
我正在使用的configure
标志:
./configure --target=arm-apple-darwin --enable-static --disable-shared
之后,运行gnumake
运行没有错误。
然后我将这些库添加到我的Xcode项目中。 但是当我build立时,我得到了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)
任何想法我做错了什么?
编辑添加:
当我添加库到项目(右键单击项目名称,然后添加现有…),我得到这个:
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)
这就是为什么我认为我错误地build立图书馆。 这就好像在说:
- 它不能告诉.a文件是为什么构build的
- libsqlite3-cerod.a是为i386构build的
我不明白这两种可能性,但我是iPhone新手。
编辑添加
我尝试了@Sergio Moura的解决scheme,并得到了我评论中提到的错误。
我尝试了@塞尔吉奥的解决scheme,它的build立。 但是我仍然得到相同的错误,从以下开始:
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)
我可能会告诉Xcode错误的东西? 右键单击项目名称,然后select“Add-> Existing File”,然后从/icu/iosbuild/lib
select六个或七个.a
文件。 这是正确的过程吗?
注意:
@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
这之前是一系列的警告:
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)
编辑#3
@Stephen R. Loomisbuild议我将#define U_HAVE_GCC_ATOMICS
从1
改为0
(在platform.h
)没有什么区别,唉。 我也意识到错误的最后一行( not found for architecture arm6
)并不意味着它会为arm7
工作,只是这是一个交叉编译。 当我指定一个arm7
版本,它失败了相同的消息。 唉。
编辑#4
成功!
总结:@塞尔吉奥的build造标志本质上是正确的。 我添加了-DU_HAVE_GCC_ATOMICS = 0到ios版本的CFLAGS。 我一直在做错的一件事是没有意识到我需要交叉编译库来创build设备构build。
我还没有试图重复这个模拟器,但这不在我的问题的范围。
特别感谢Steven R. Loomis的投入,并感谢Sergio Moura让事情滚滚而来。
编辑:
我可以证实,如果你这样做,就像史蒂文·R·罗米斯所说的那样:
-
在icu / source / common / unicode / platform.h中将U_HAVE_GCC_ATOMICS设置为0
-
使distclean
-
sh cross_configure.sh(使用我的脚本,即,如果你正在使用它)
这个问题应该解决。 事实上,如果不这样做,构build的库包含有问题的未定义符号:
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
遵循上述build议后,这是同一命令的结果:
sergio@sfogliatella$ nm -a ./lib/libicuuc.a | grep __sync_ nm: no name list nm: no name list
所以,当然,在二进制文件中不存在违规符号。
结束编辑。
为iOS交叉编译libicu需要两个独立的步骤:
-
在编译目录中编译主机(MacOS)的libicu;
-
通过指定交叉编译目录来交叉编译iOS的libicu。
步骤1的必要原因是libicu会引导自己,也就是说它会编译一些中间工具,然后在构build过程的其余部分使用这些中间工具。 这些工具需要在主机平台上运行,所以它们可以使用。
那么,总而言之,你可以按照下面的步骤(1.为主机编译):
$ cd $icu $ mkdir hostbuild $ cd hostbuild $ ../icu/source/configure <configure settings you need> $ gnumake
一旦完成,就可以交叉编译了(2.为iOS编译):
$ cd $icu (or cd ../ from the previous directory) $ mkdir iosbuild $ cd iosbuild $ sh ../cross_configure_icu.sh $ gnumake
其中cross_configure_icu.sh
是一个类似于上面的Sergio Moura提出的shell脚本,但为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
在上面的脚本( 源代码 )中, ICU_PATH
是一个绝对path,因为libicuconfiguration需要使用with-cross-build
选项。 再次检查你的SDK和编译器的值,但4.3应该可以。
最后,你应该考虑到苹果已经(至less)拒绝了至less一个链接到libicu的应用程序,因为它使用了保留的API。 看看这个SO主题 。
编辑:
听到你可以编译的快乐!
现在,到链接问题。
首先,请检查libicu库的格式是否正确:
sergio@sfogliatella$ lipo -info ./lib/libicuuc.a
输出应该是(对于任何一个库):
input file ./lib/libicuuc.a is not a fat file Non-fat file: ./lib/libicuuc.a is architecture: arm
如果这没问题,那么下一个问题:你在为模拟器或设备build造吗? 模拟器需要i386库,设备臂库…从您显示的错误消息:
ld:warning:…文件是为不支持的文件格式构build的,而不是被链接的架构(i386)
在我看来,你是build立在模拟器…因为你将需要“正常”的马科斯X库…
我使用iOS SDK版本6.1,与clang和build立对c + + 11标准库。 我发现设置环境variables如CXXFLAGS没有任何影响,并试图将它们传递给命令行上的'configure'似乎完全破坏它。 我结束了使clang,clang ++和ld脚本,这将允许我传递额外的参数。 例如,我的铛脚本:
#This script circumvents gnumake getting rid of our flags. Use the environment variable $MORE_CFLAGS /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang "$@" $MORE_CFLAGS
其他是相同的,但是在适当的情况下用clang ++和ld替代,分别使用MORE_CXXFLAGS和MORE_LDFLAGS。
最后,我做了这个脚本,主机构build,模拟器构build和iOS构build。 请注意,模拟器版本包含debugging信息,iOS版本是-O2优化版本。 然后,它使用libs(制作一个通用的二进制文件),并将它们和include文件夹一起复制到由INSTALL_PATH指定的目标。 第3-5行用于configuration脚本。 将所有这4个脚本放在同一个文件夹中,并从命令行执行最后一个:
#unpack the ICU source and point $ICU_PATH at it ICU_PATH="$HOME/Downloads/icu" ICU_FLAGS="-I$ICU_PATH/source/common/ -I$ICU_PATH/source/tools/tzcode/ " INSTALL_PATH="$HOME/Documents/git/gamelib/Graphics/Text/icu/51.1" SDKROOT=`xcrun --sdk iphoneos --show-sdk-path` SIMULATOR_SDKROOT=`xcrun --sdk iphonesimulator --show-sdk-path` SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" SAVEPATH=$PATH cd $ICU_PATH mkdir host_build cd host_build ../source/configure gnumake PATH=$SCRIPT_DIR:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:$SAVEPATH cd $ICU_PATH mkdir iPhoneSimulator_build cd iPhoneSimulator_build #PATH points to the folder that contains this script, which should also contain scripts titled clang, clang++, and ld #those scripts call the actual clang, clang++, and ld, appending MORE_CFLAGS, MORE_CXXFLAGS, and MORE_LDFLAGS respectively export MORE_CFLAGS="-arch i386 -pipe -std=c99 -fmessage-length=0 -fvisibility=hidden -miphoneos-version-min=5.0 -isysroot $SIMULATOR_SDKROOT $ICU_FLAGS" export MORE_CXXFLAGS="-arch i386 -pipe -std=c++11 -stdlib=libc++ -fmessage-length=0 -fvisibility=hidden -miphoneos-version-min=5.0 -isysroot $SIMULATOR_SDKROOT $ICU_FLAGS" export MORE_LDFLAGS="-arch i386 -isysroot $SIMULATOR_SDKROOT -miphoneos-version-min=5.0" $ICU_PATH/source/configure --enable-debug --disable-release --with-cross-build="$ICU_PATH/host_build" --prefix="$ICU_PATH/iPhoneSimulator_build/install" --enable-static=yes --enable-shared=no gnumake clean gnumake VERBOSE=1 install PATH=$SCRIPT_DIR:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:$SAVEPATH cd $ICU_PATH mkdir iPhoneOS_build cd iPhoneOS_build #PATH points to the folder that contains this script, which should also contain scripts titled clang, clang++, and ld #those scripts call the actual clang, clang++, and ld, appending MORE_CFLAGS, MORE_CXXFLAGS, and MORE_LDFLAGS respectively export MORE_CFLAGS="-arch armv7 -pipe -std=c99 -O2 -fmessage-length=0 -fvisibility=hidden -miphoneos-version-min=5.0 -isysroot $SDKROOT $ICU_FLAGS" export MORE_CXXFLAGS="-arch armv7 -pipe -std=c++11 -stdlib=libc++ -O2 -fmessage-length=0 -fvisibility=hidden -miphoneos-version-min=5.0 -isysroot $SDKROOT $ICU_FLAGS" export MORE_LDFLAGS="-arch armv7 -isysroot $SDKROOT -miphoneos-version-min=5.0" $ICU_PATH/source/configure --host=arm-apple-darwin --with-cross-build="$ICU_PATH/host_build" --prefix="$ICU_PATH/iPhoneOS_build/install" --enable-static=yes --enable-shared=no gnumake clean gnumake VERBOSE=1 install PATH=$SAVEPATH mkdir "$INSTALL_PATH/lib" for file in $ICU_PATH/iPhoneOS_build/install/lib/*.a; do BASENAME="${file##*/}" lipo "$ICU_PATH/iPhoneOS_build/install/lib/$BASENAME" "$ICU_PATH/iPhoneSimulator_build/install/lib/$BASENAME" -create -output "$INSTALL_PATH/lib/$BASENAME" done rm -r "$INSTALL_PATH/include" cp -r "$ICU_PATH/iPhoneOS_build/install/include" "$INSTALL_PATH/include"
如果你有来源,你真的需要链接图书馆? 只需将源代码添加到您的XCode项目中,您应该很好地去…
如果你真的想build立一个库,我build议你创build一个XCode项目作为你的目标,并将该库链接到你的代码,因为你的库是build立在MacOS电脑上运行的到您的错误日志)。
编辑
要从命令行构build它,并假设您没有使用iOS 5(由于您的XCode版本),我已经借用并修改了这套指令,以正确设置标志,以正确configuration和构build您的平台的二进制文件从这里 :
export IOS_BASE_SDK=4.2 export IOS_DEPLOY_TGT=4.2 export DEVROOT=/Developer/Platforms/iPhoneOS.platform/Developer export SDKROOT=$DEVROOT/SDKs/iPhoneOS$IOS_BASE_SDK.sdk export CFLAGS="-arch armv7 -pipe -no-cpp-precomp -isysroot $SDKROOT -miphoneos-version-min=$IOS_DEPLOY_TGT -I$SDKROOT/usr/include/" export CPP=$DEVROOT/usr/bin/cpp-4.2 export CXX=$DEVROOT/usr/bin/g++-4.2 export CXXCPP=$DEVROOT/usr/bin/cpp-4.2 export CC=$DEVROOT/usr/bin/gcc-4.2 export LD=$DEVROOT/usr/bin/ld export AR=$DEVROOT/usr/bin/ar export AS=$DEVROOT/usr/bin/as export NM=$DEVROOT/usr/bin/nm export RANLIB=$DEVROOT/usr/bin/ranlib export LDFLAGS="-L$SDKROOT/usr/lib/" export CPPFLAGS=$CFLAGS export CXXFLAGS=$CFLAGS ./configure --target=arm-apple-darwin --enable-static --disable-shared
请正确地将前两条指令的IOS版本设置为正确的环境值。
如果您要使用iOS 5 SDK,则需要更改编译器二进制文件的名称,因为它们已更改。
重新:同步同步:有人可能是在说谎的primefaces或有一些GCC库需要。 请尝试在icu / source / common / unicode / uconfig.h顶部的#define U_HAVE_GCC_ATOMICS 0
(注意:ARM似乎有一个弱内存模型,所以这个更改会导致更多的locking/解锁,否则将是必要的,但仍然安全)。