最近有个共享库libraw的编译,需要将一个额外的第三方库静态库编译进共享库。这个第三方库是gpr库,用来让libraw.so支持gpr格式的图片。
gpr默认编译出来是静态库,但是没有加-fPIC选项,导致不能链接到共享库
/usr/bin/ld: /work/nas/gpr-1.1/staging/lib/libdng_sdk.a(dng_host.cpp.o): relocation R_X86_64_PC32 against symbol `_ZTV8dng_host' can not be used when making a shared object; recompile with -fPIC
但是如果一个符号只是内部用的话,可以不加-fPIC选项
使用 -Lstaging/lib -lgrp_sdk
编译libraw.so没有报错报错,但是在编译使用libraw.so的可执行程序时,报错了。
ld: lib/.libs/libraw.so: undefined reference to `InitImage'
$ readelf -a build/lib/.libs/libraw.so | grep InitImage
00000022f3b8 00c900000402 R_AARCH64_JUMP_SL 0000000000000000 InitImage + 0
201: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND InitImage
6374: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND InitImage
发现这个符号是UND,应该是静态库没有链接到共享库里面。
经过搜索发现了--whole-archive选项,手动运行编译命令,在静态库前后加上:
-Wl,--whole-archive /work/gpr-1.1/lib/libdng_sdk.a /work/gpr-1.1/lib/libgpr_sdk.a -Wl,--no-whole-archive \
运行后
$ readelf -a libraw.so.23.0.0 | grep InitImage
00000024f350 0bb700000402 R_AARCH64_JUMP_SL 00000000001707b0 InitImage + 0
2999: 00000000001707b0 44 FUNC GLOBAL DEFAULT 12 InitImage
6753: 00000000001707b0 44 FUNC GLOBAL DEFAULT 12 InitImage
备注:
静态库,可以-Lpath -lcommon,也可以直接指定路径,/path/libcommon.a
LD手册说的很详细
whole-archive是把静态库的所有object包含进去,通常用来将一个archive链接到shared libary
--whole-archive
For each archive mentioned on the command line after the ‘--whole-archive’
option, include every object file in the archive in the link, rather than searching
the archive for the required object files. This is normally used to turn an archive
file into a shared library, forcing every object to be included in the resulting
shared library. This option may be used more than once.
Two notes when using this option from gcc: First, gcc doesn’t know about this
option, so you have to use ‘-Wl,-whole-archive’. Second, don’t forget to use
‘-Wl,-no-whole-archive’ after your list of archives, because gcc will add its
own list of archives to your link and you may not want this flag to affect those
as well.
参考:
https://stackoverflow.com/questions/17558881/how-to-use-whole-archive-with-libtool