我目前正在开发一种不鼓励(即基本上禁止)动态库的系统。因此,一切都必须静态联系。
我正在使用的应用程序框架(无法更改)正在使用库libfoo.a
(版本r7)的旧的静态链接版本。我正在使用的库libbar
需要libfoo.a
版本r8(具体来说,一些新功能对于库的运行至关重要)。我可以编辑和重新编译libbar
以及libfoo
r8,但我希望尽可能避免更改它们,因为我对代码不太熟悉(并且必须向上游传递代码更改)
不幸的是,这两个libfoo
库共有大量符号。因此,链接器会发出大量“多符号定义”错误。
我听说可以使用objcopy
和朋友将静态库“内联”到另一个库中。但是,我不确定如何在实践中实现这一目标,也不是最好的选择。
那么,如何成功编译使用同一个库的两个不兼容版本的可执行文件?我已经考虑过要避免这种情况了,但这样做会更难。
答案 0 :(得分:2)
事实证明,实际上这可能会带来一些ld
和objcopy
魔法。
基本上,程序如下:
# Unpack libraries
ar x libbar.a
ar x libfoo.a
# Grab symbol table (symbols to export)
nm -Ag libbar.a | grep -v ' U ' | cut -d' ' -f 3 > libbar.sym
# Build a single object file with libfoo relocated in
ld -Er *.o -o libbar-merged.lo
# Localize all symbols except for libbar's symbols
objcopy --keep-global-symbols libbar.sym libbar-merged.lo libbar-merged.o
# Create an archive to hold the merged library
ar crs libbar-merged.a libbar-merged.o
这有效地创建了一个单独的超级库,它只导出原始libbar
中的符号,并重新定位了另一个库。
可能有另一种更清晰的方法来实现这个结果,但这种方法对我有用,并允许我将两个不兼容的库静态链接到同一个可执行文件中,没有明显的不良影响。