我有一个共享库,并使用它来创建可执行二进制文件。我只能控制库和可执行二进制文件的构建过程,而不能控制所涉及的源文件。不出所料,可执行二进制文件中的源文件引用了库中的许多功能。
当前,共享库是直接使用objectfiles(.o)构建的。
g++ -shared ${OBJECT_FILES} -o ${SHARED_LIBRARY}
我也想通过将对象文件分组到静态库(.a文件或achive)中来发布对象文件。
为了节省空间,我在创建存档文件时删除了所有.o文件。所以现在,build命令是
g++ -shared ${ACRCHIVE_FILE} -o ${SHARED_LIBRARY}
该库构建良好。
但是,当我尝试通过链接到此共享库来构建可执行二进制文件时,二进制文件所引用的符号未定义,并且无法链接。(对的未定义引用Context::Get()
)
根据我的理解,我们直接使用.o文件还是由所有.o文件组成的档案库创建共享库都没有关系,但是显然这是不可能的,或者我可能会丢失一些东西。
共享库libfoo.so
应包含PIC代码,而静态库应libfoo.a
包含普通的非PIC代码。因此,您不能从静态库创建共享库。
共享库需要位置无关代码,因为它们的段是mmap(2)-在几乎任意且可变的地址处编入的,而没有MAP_FIXED
...请参见ASLR。
原则上,您可以从PIC对象文件构建静态库,但实际上没有人这样做。
您可能(如果真的坚持的话)可以使ELF共享对象由非PIC代码构成,但是结果将导致非常糟糕的性能。动态链接器将有很多重定位,因此大多数段将是不共享的,并且动态链接将非常慢。
要将foo.cc
共享库编译为PIC目标文件,请执行以下操作foo.pic.o
:
g++ -Wall -c -O foo.cc -fPIC -o foo.pic.o
要将其编译为普通的非PIC对象文件中的静态库,请执行以下操作foo.o
:
g++ -Wall -c -O foo.cc -o foo.o
为了使共享库foo.pic.o
,并bar.pic.o
为libfoobar.so
一些链接libdep.so
共享库:
g++ -shared foo.pic.o bar.pic.o -ldep -o libfoobar.so
像上面那样创建共享库时,例如-Wl,-rpath,
...或-Wl,-soname,
... ,您通常想添加更多的链接选项。
顺便说一句,不可能将归档文件libfoobar.a
(即使它是由PIC文件组成)链接到中,libfoobar.so
因为没有名称是未定义的,并且需要从中链接某些目标文件libfoobar.a
(也许您可以尝试用来取消定义一些符号symb
,-u symb
但我不建议这样做)这样做)。
为了使静态库foo.o
和bar.o
成libfoobar.a
:
ar cv libfoobar.a foo.o bar.o
请注意,由于GNU会执行ranlib,因此不再需要ranlib(创建档案的索引)ar
。
另请参阅ld.so(8),ldd(1),ld(1),ar(1),objdump(1),readelf(1),dlopen(3)(通常,您需要将主程序与-rdynamic
if它会dlopen
在运行时加载-ed插件,以使插件能够在主程序中找到一些符号。
注意:我只是建立一个共享库,根本不关心静态链接。请注意,在某些系统上,PIC成本较低(代码较大和/或较慢)。AFAIK,x86-64上的PIC开销比32位Linux x86代码便宜。在某些体系结构和ABI上,PIC的开销可以忽略不计(甚至比非位置无关的代码更有效)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句