草庐IT

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

coder 2023-07-20 原文

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

我正在维护一个使用 SQLite 数据库的 iPhone 应用程序。现在我必须在启用 ICU 支持的情况下进行编译 (SQLITE_ENABLE_ICU)。我有最新的 ICU 资源。

我正在使用的 configure 标志:

./configure --target=arm-apple-darwin --enable-static --disable-shared

之后,运行 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)

知道我做错了什么吗?

编辑添加:

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

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)

这就是为什么我认为我构建的库不正确。就好像在说:

  • 它无法判断 .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)

我可能会告诉 Xcode 错误的事情吗?我右键单击项目名称,然后选择“添加->现有文件”,然后从 /icu/iosbuild/lib 中选择六个或七个 .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. Loomis 建议我将 #define U_HAVE_GCC_ATOMICS1 更改为 0(在 platform.h) 没有区别,唉。我还意识到错误的最后一行 (not found for architecture arm6) 并不意味着它适用于 arm7,这只是一个 fyi,这是一个交叉编译。当我指定 arm7 构建时,它失败并显示相同的消息。唉。

编辑#4

成功!

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

我没有尝试为模拟器重复这个,但这不在我的问题范围内。

特别感谢 Steven R. Loomis 的参与,以及 Sergio Moura 的插入。

最佳答案

编辑:

我可以确认,如果您这样做,正如 Steven R. Loomis 所建议的那样:

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

  2. 清理干净

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

问题应该解决了。事实上,如果不这样做,构建的库就会包含令人讨厌的 undefined symbol :

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

按照上述建议,这是相同命令的结果:

sergio@sfogliatella$ nm -a ./lib/libicuuc.a | grep __sync_
nm: no name list
nm: no name list

因此,毫无疑问,二进制文件中不存在有问题的符号。

结束编辑。

为 iOS 交叉编译 libicu 需要两个独立的步骤:

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

  2. 通过指定交叉编译目录为 iOS 交叉编译 libicu。

之所以需要第 1 步,是因为 libicu 会 self 引导一些,即它会编译一些中间工具,然后在其余的构建过程中使用这些工具;这些工具需要在主机平台上运行,因此它们是可用的。

嗯,总而言之,你可以按照步骤(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 是一个 shell 脚本,类似于上面 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

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

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

编辑:

很高兴听到您可以编译!

现在,链接问题。

首先,请检查 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

如果没问题,那么下一个问题:您是为模拟器还是为设备构建?模拟器需要 i386 库、设备 arm 库...从您显示的错误消息中:

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

在我看来,您正在针对模拟器进行构建...为此您将需要“普通”macos x 库...

关于iphone - 如何构建 ICU 以便我可以在 iPhone 应用程序中使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8126233/

有关iphone - 如何构建 ICU 以便我可以在 iPhone 应用程序中使用它?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  8. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  9. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  10. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

随机推荐