Dad*_*Dad 12 cocoa objective-c static-libraries ios
之前已经提出过这个问题,但是对各种开发工具的文档进行深入研究似乎是可能的,这一点并不明显.
动机:制作一个供其他iOS开发人员使用的静态库.如果导出库中的某些符号会导致问题,所以我希望将它们作为仅内部符号.使用动态库这很简单,只需使用use -exported_symbols_list libtool(ld)参数并列出您想要公开的参数. libtool文档不允许这个参数用于静态库.
Library有几个ObjectiveC .m文件,它们使用彼此的代码.只需要将组中的一个类公开给最终的.a静态库文件的用户.
尝试libtool -exported_symbols_list publicsymbols.exp但静态库libtool不支持该参数-static.
不能使符号与属性私有(如果它甚至可以工作),因为组中的其他.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
Run Code Online (Sandbox Code Playgroud)
其中{path}类型的东西有很长的路径到那里的适当位置.
但我得到如下错误:
/ usr/bin/ld_classic:/Users/Dad/ABCsdk/iphone-ABClib/build/ABCLib.build/Distribution-iphoneos/ABCLib-device.build/Objects-normal/armv6/ABCmain.o不兼容,文件包含不受支持的类型加载命令0中的第3节(_ TEXT, _picsymbolstub4)(必须指定要使用的"-dynamic")
那里似乎有些不对劲......
谁知道一个聪明的方法来使这项工作?谢谢.
Die*_*Epp 15
这真的不可能,我很遗憾地说.它与静态库的工作方式有关.静态库只是*.o捆绑在一起的一堆目标文件,但动态库是可加载的二进制映像,就像可执行文件一样.
假设你有四个文件,
common,这是"私有"fn1哪些调用common.fn2哪些调用common.other.在动态库中,链接器将所有内容捆绑到一大块代码中.库出口other,fn1和fn2.您必须加载整个库或不加载它,但是两个程序都可以加载它而无需在内存中放置多个副本.common符号表中缺少入口点- 您无法从库外部调用它,因为链接器无法找到它.
请注意,应用程序和共享库具有基本相同的格式:应用程序基本上是一个只导出一个符号的共享库main.(这不完全正确,但接近.)
在静态库中,链接器永远不会运行.这些文件都被编译成*.o文件并放入*.a库归档文件中.内部参考将无法解决.
假设您的应用程序调用fn1.链接器看到一个未解析的调用fn1,然后查看库.它fn1在fn1.o中找到了一个定义.然后链接器注意到一个未解析的调用common,所以它在common.o中查找它.该程序不会从fn2.c或other.c获取代码,因为它不使用这些文件中的定义.
静态库非常古老,它们没有动态库的任何功能.您可以将静态库视为一个充满已编译源代码的zip文件,而不像链接在一起的动态库.没有人愿意扩展存档格式以添加符号可见性.当您与静态库链接时,您获得的结果与将库的源代码添加到程序中的结果相同.
简短版本:动态库具有所有导出符号的一个符号表,但没有私有符号.以同样的方式,目标文件具有其所有extern符号的列表,但没有一个符号static.但是静态库没有符号表,它只是一个存档.因此,没有任何机制可以使代码专用于静态库(除了定义对象static,但这对Objective-C类不起作用).
如果我们知道你为什么要这样做,也许我们可以给你一个建议.(这是为了安全吗?姓名冲突?所有这些问题都有解决方案.)
这个有可能!正如 Dietrich 所说,.o静态库中文件中的所有导出符号都是公共的,如果一个文件需要引用另一个.o文件中的符号,则需要从该文件中导出(因此是公共的)。但有一种简单的解决方法 - 将所有.o文件预先链接到一个文件中。那么你只需要导出公共符号即可。
这显然被称为“单个对象预链接”,并且在treert提到的XCode中可以选择执行此操作。但您可以仅使用标准命令行工具来完成此操作(此处为示例存储库):
看看(这是在 Mac 上)。
首先让我们创建一些测试文件
$ cat private.c
int internal_private_function() {
return 5;
}
$ cat public.c
extern int internal_private_function();
int public_function() {
return internal_private_function();
}
Run Code Online (Sandbox Code Playgroud)
编译它们
$ clang -c private.c -o private.o
$ clang -c public.c -o public.o
Run Code Online (Sandbox Code Playgroud)
将它们添加到静态库(它基本上是一个 zip 文件,但采用了几十年前的格式)。
$ ar -r libeverything_public.a public.o private.o
Run Code Online (Sandbox Code Playgroud)
检查里面有什么符号。
$ objdump -t libeverything_public.a
libeverything_public.a(private.o): file format Mach-O 64-bit x86-64
SYMBOL TABLE:
0000000000000000 g F __TEXT,__text _internal_private_function
libeverything_public.a(public.o): file format Mach-O 64-bit x86-64
SYMBOL TABLE:
0000000000000000 g F __TEXT,__text _public_function
0000000000000000 *UND* _internal_private_function
Run Code Online (Sandbox Code Playgroud)
好的,您可以看到这两个函数都是可见的,并且两个符号都是g全局的。
现在让我们预链接到一个文件中,然后将其单独放入静态库中。
$ ld -r -o prelinked.o private.o public.o
$ ar -r libeverything_public_prelinked.a prelinked.o
$ objdump -t libeverything_public_prelinked.a
libeverything_public_prelinked.a(prelinked.o): file format Mach-O 64-bit x86-64
SYMBOL TABLE:
0000000000000020 l O __TEXT,__eh_frame EH_Frame1
0000000000000038 l O __TEXT,__eh_frame func.eh
0000000000000060 l O __TEXT,__eh_frame EH_Frame1
0000000000000078 l O __TEXT,__eh_frame func.eh
0000000000000000 g F __TEXT,__text _internal_private_function
0000000000000010 g F __TEXT,__text _public_function
Run Code Online (Sandbox Code Playgroud)
类似的结果 - 它们位于一个文件中,但仍然存在且全局。最后让我们过滤掉它们(这是 Mac 特有的)。我们需要导出符号列表:
$ cat exported_symbols_osx.lds
_public_function
Run Code Online (Sandbox Code Playgroud)
然后使用该-exported_symbols_list选项。
$ ld -r -exported_symbols_list exported_symbols_osx.lds -o prelinked_filtered.o private.o public.o
$ ar -r libfiltered_prelinked.a prelinked_filtered.o
ar: creating archive libfiltered_prelinked.a
$ objdump -t libfiltered_prelinked.a
libfiltered_prelinked.a(prelinked_filtered.o): file format Mach-O 64-bit x86-64
SYMBOL TABLE:
0000000000000000 l F __TEXT,__text _internal_private_function
0000000000000020 l O __TEXT,__eh_frame EH_Frame1
0000000000000038 l O __TEXT,__eh_frame func.eh
0000000000000060 l O __TEXT,__eh_frame EH_Frame1
0000000000000078 l O __TEXT,__eh_frame func.eh
0000000000000010 g F __TEXT,__text _public_function
Run Code Online (Sandbox Code Playgroud)
田田!_internal_private_function现在已成为当地的象征。您可以添加-x选项(或者运行strip -x)将名称更改为随机的无意义值(此处l001)。
$ ld -r -x -exported_symbols_list exported_symbols_osx.lds -o prelinked_filtered.o private.o public.o
$ objdump -t prelinked_filtered.o
prelinked_filtered.o: file format Mach-O 64-bit x86-64
SYMBOL TABLE:
0000000000000000 l F __TEXT,__text l001
0000000000000020 l O __TEXT,__eh_frame EH_Frame1
0000000000000038 l O __TEXT,__eh_frame func.eh
0000000000000060 l O __TEXT,__eh_frame EH_Frame1
0000000000000078 l O __TEXT,__eh_frame func.eh
0000000000000010 g F __TEXT,__text _public_function
Run Code Online (Sandbox Code Playgroud)
以下是苹果链接器的说法-x:
不要将非全局符号放入输出文件的符号表中。非全局符号在调试和获取回溯中的符号名称时很有用,但在运行时不使用。如果 -x 与 -r 一起使用,则不会删除非全局符号名称,而是替换为唯一的虚拟名称,该名称在链接到最终链接图像时将自动删除。这允许死代码剥离(使用符号来分解代码和数据)正常工作,并提供删除源符号名称的安全性。
除了 之外,所有这些在 Linux 上都是相同的-exported_symbols_list。在 Linux 上,我认为你必须使用--version-script这样的文件:
V0 {
global:
_public_function;
local:
*;
};
Run Code Online (Sandbox Code Playgroud)
但我还没有测试过这个。该文件和其他exported_symbols_list文件都支持通配符。
| 归档时间: |
|
| 查看次数: |
6632 次 |
| 最近记录: |