之前曾有人问过这个问题,但是深入研究各种开发工具的文档似乎是有可能的,只是不那么明显。

动机:
制作一个静态库供其他iOS开发人员使用。库中的某些符号如果导出会引起问题,所以我希望将其设置为仅供内部使用的符号。使用动态库,这很容易,只需使用-exported_symbols_list libtool(ld)参数并列出要公开的参数即可。 libtool文档不允许静态库使用此参数。

库中有几个使用彼此代码的ObjectiveC .m文件。该组中只有一个类需要对最终.a静态库文件的用户公开。

尝试过libtool -exported_symbols_list publicsymbols.exp,但是静态库的libtool不支持-static的参数。

无法将符号设置为具有属性的私有(private)属性(如果可以使用的话),因为组中的其他.m文件需要使用它们。

好像ld可以接收多个.o文件并将它们链接到一个新的.o文件中(通过-r参数),并且它没有-exported_symbols_list参数的“仅动态”免责声明(可能只是不清楚的文档。) )。

就像测试一样,我使用Xcode构建项目,因此我已经制作了所有.o文件,然后尝试在命令行上调用ld,如下所示:

ld -r -x -all_load -static -arch armv6 -syslibroot {path}
   -filelist /Users/Dad/ABCsdk/iphone-ABClib/build/ABCLib.build/Distribution-iphoneos/ABCLib-device.build/Objects-normal/armv6/ABCsdk.LinkFileList
   -exported_symbols_list {exp file path} -o outputfile.o

{path}类型的事物到那里的适当位置的路径很长。

但我收到如下错误:



所以那里似乎有问题...

任何人都知道使这项工作聪明的方法吗?谢谢。

最佳答案

很抱歉,这确实是不可能的。它与静态库的工作方式有关。静态库只不过是 bundle 在一起的一堆对象*.o文件,而动态库是可加载的二进制镜像,就像可执行文件一样。

假设您有四个文件,

  • common.c定义common,它是“私有(private)”的
  • fn1.c定义fn1,它调用common
  • fn2.c定义fn2,它调用common
  • other.c定义other

  • 在动态库中,链接器将所有内容 bundle 为一大段代码。该库导出otherfn1fn2。您必须加载整个库或不加载整个库,但是两个程序都可以加载它,而无需将多个副本放入内存中。符号表中只是缺少common的入口点-您无法从库外部调用它,因为链接器找不到它。

    请注意,应用程序和共享库具有基本相同的格式:应用程序基本上是仅导出一个符号main的共享库。 (这并不完全正确,但是很接近。)

    在静态库中,永远不会运行链接器。所有文件都被编译为* .o文件,并放入* .a库归档文件中。内部引用将无法解析。

    假设您的应用程序调用fn1。链接器看到对fn1的 Unresolved 调用,然后浏览库。它在fn1.o中找到fn1的定义。然后,链接器会注意到对common的 Unresolved 调用,因此它在common.o中进行查找。该程序不会从fn2.c或other.c获取代码,因为它不使用这些文件中的定义。

    静态库非常老,并且不具有动态库的任何功能。您可以将静态库视为基本上是一个已编译源代码的zip文件,与链接在一起的动态库不同。没人愿意扩展文件格式来增加符号可见性。与静态库链接时,所得到的结果与将库的源代码添加到程序中的结果相同。

    简短版本:动态库具有所有导出符号的一个符号表,但没有私有(private)符号。同样,目标文件包含所有extern符号的列表,但没有static符号的列表。但是静态库没有符号表,它只是一个存档。因此,没有机制可以将代码私有(private)化为静态库(除了定义对象static之外,但这不适用于Objective-C类)。

    如果我们知道您为什么要这样做,也许我们可以给您一个建议。 (是否出于安全性?名称冲突?所有这些问题都有解决方案。)

    关于objective-c - 如何在不公开所有符号的情况下为iOS创建静态库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6894214/

    10-13 05:30