如何为iOS链接静态库

5
我创建了一堆.o文件(通过gcc -c $file.c $someotherops -o $file.o)。现在我想把它们链接成一个静态库。 我不确定我是否应该使用ld或gcc来完成这个任务。在ld手册中,它说我不应该直接使用它。但是,我无法弄清楚gcc参数以创建静态库。 我尝试了ld *.o -static -o libfoo.a,但它抱怨缺少很多符号(我认为所有这些符号都来自于libc)。我不明白为什么它会抱怨,因为它应该是一个静态库。我认为它会在我将静态库链接到其他内容时检查这些符号。 还有一件事:我在这里使用/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ld(我的目标是iOS)。它会发出警告信息ld: warning: using ld_classic。这是什么意思?
然后我想,也许需要指定动态库。所以我添加了-lc来链接libc库。但是它报错:can't locate file for: -lc。我添加了-L/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/lib,并且有一个libc.dylib。 有什么想法吗?
关于-lc错误:我在指定-arch armv6后,错误消失了。然后它抱怨一个错误的libcache.dylib(我猜这必须链接自libc.dylib,因为它没有指定)。添加-L.../usr/lib/system有所帮助。
现在,对于每个单独的.o文件,我收到警告ld: warning: CPU_SUBTYPE_ARM_ALL subtype is deprecated。这是什么意思?
而且我仍然有一堆缺失的符号,尤其是:
Undefined symbols for architecture armv6:
  "start", referenced from:
     -u command line option
     (maybe you meant: _PyThread_start_new_thread)
  "___udivsi3", referenced from:
      _get_len_of_range in bltinmodule.o
      _quorem in dtoa.o
      _array_resize in arraymodule.o
      _newarrayobject in arraymodule.o
      _array_fromfile in arraymodule.o
      _get_len_of_range in rangeobject.o
      _inplace_divrem1 in longobject.o
      ...
  "___unorddf2", referenced from:
      _builtin_round in bltinmodule.o
  ...

我查看了一些符号,例如在get_len_of_range函数中的___udivsi3。该函数仅使用C算术,没有外部调用。因此,似乎要使用一些外部函数,例如___udivsi3。但是这是在哪些库中?

-lgcc_s.1修复了大部分___udivsi3和相关的缺失符号。但是start符号仍然缺失。-u命令行选项是什么意思?


我从这里得到的感觉是,也许ld不是合适的工具。在那里,只使用了一个简单的调用ar。这似乎更有意义。我将检查它是否有效,并将其转化为答案。


在进行更多尝试时,编译静态库时出现了一些警告,提示我使用libtool。现在我正在使用libtool -static -o libfoo.a *.o。同时,我将编译器切换到了/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang,但不确定是否有影响。
现在,在编译连接到这个静态库的某些测试应用程序时,我收到了以下警告:
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in __PyBuiltin_Init from /Users/az/Programmierung/python-embedded/libpython.a(bltinmodule.o). To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
ld: warning: 32-bit absolute address out of range (0x1001B70C4 max is 4GB): from _usedpools + 0x00000004 (0x001B70CC) to 0x1001B70C4
ld: warning: 32-bit absolute address out of range (0x1001B70C4 max is 4GB): from _usedpools + 0x00000000 (0x001B70CC) to 0x1001B70C4

他们是关于什么的?我不使用-mdynamic-no-pic。我也不太清楚在_PyBuiltin_Init中如何使用绝对寻址。
此外,这些超出范围的绝对地址是关于什么的?编辑:这些是一些非常大的分配。我现在只是暂时删除了这段代码(如果有人对这些特定的Python内部感兴趣,这是WITH_PYMALLOC)。
当我在iPhone上启动它时,我会得到中止: dyld: vm_protect(0x00001000, 0x00173000, false, 0x07) failed, result=2 for segment __TEXT in /var/mobile/Applications/C15D9525-E7DC-4463-B05B-D39C9CA24319/... 当我使用-no_pie进行链接时,甚至无法链接。它失败了:

在armv7架构下,/Users/az/Programmierung/python-embedded/libpython.a(marshal.o)中的_read_object向/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/libSystem.dylib的___stderrp进行了非法文本重定位


我解决了PIE禁用和绝对寻址错误。我的Clang命令行中有一个-static。一旦我删除了它,警告消失了,dyld/vm_protect错误也消失了。这是第一次实际运行了一些代码。
直到我遇到了另一个关于整数比较的奇怪错误。这似乎更像是他们的Clang构建中的一个错误。

@meccan:在这种情况下,我想要拥有自己的编译脚本,原因有很多(主要是因为对于这个特定的项目,现在这样做更简单)。无论如何,即使我使用Xcode来完成它,这个问题仍然是有效/开放的,因为我想要理解如何手动完成它。 - Albert
好的,你知道你可以从Shell构建Xcode项目吗? - CarlJ
1
你有没有查看过这个网站?http://mark.aufflick.com/blog/2010/11/18/making-a-fat-static-library-for-ios-device-and-simulator - CarlJ
@StevenFisher:我的问题并不一定是关于iPhone/iOS的。而且,我仍然想知道是否使用Xcode。但在这种情况下,Xcode不是一个选项。我猜我甚至会在Xcode中得到相同的错误。 - Albert
Xcode 没有做任何特殊的事情。它只是 GCC/Clang/libtool/ar/ld 和其他工具的包装器。最近的版本默认使用 Clang。实际上,我只是做与 Xcode 相同的事情。(我刚刚检查过了。我在 Xcode 中创建了一个静态库,并查看了 Xcode 执行的 clang/libtool 命令。)此外,如果您不了解这些内容,那么您将非常受限制。此外,Xcode 并不适用于跨平台开发。 - Albert
显示剩余5条评论
2个回答

14

现在一切都正常了。基本上,答案是:

  • 像往常一样编译每个*.c文件为*.o文件。唯一真正的区别是使用不同的GCC/Clang、-arch armv7、不同的SDK / include dirs。

  • 使用libtool -static -o libfoo.a *.o 来构建静态库。

就是这样。我问题中的其他问题只是错误的尝试。


1
如果有人通过搜索 dyld: vm_protect(...) 运行时错误而使用XCode,那么OP中提到的-static标志可能是问题所在。在LLVM编译器语言设置中将“启用与共享库链接”切换为“是”(默认值)来消除它。(这将从项目文件中删除GCC_LINK_WITH_DYNAMIC_LIBRARIES = NO)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接