之前曾有人问过这个问题,但是深入研究各种开发工具的文档似乎是有可能的,只是不那么明显。
动机:
制作一个静态库供其他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
,它是“私有(private)”的fn1
,它调用common
。 fn2
,它调用common
。 other
。 在动态库中,链接器将所有内容 bundle 为一大段代码。该库导出
other
,fn1
和fn2
。您必须加载整个库或不加载整个库,但是两个程序都可以加载它,而无需将多个副本放入内存中。符号表中只是缺少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/