0

我目前正在做一个更大的项目,其中包含很多库,我对为什么 linux 下的 gcc 会表现得这样有一些疑问。

首先,我想您可能知道,您可以使用 gcc/g++ 的“-lxyz”链接器标志在某些系统路径中搜索 libxyz.so 并链接到它。但是,这在静态库的情况下不起作用,即如果我想链接 libxyz.a,我必须明确添加 /usr/lib/libxyz.a 作为目标文件。

我的问题如下:如果我想在我的项目中包含一个 pkg-config 样式的 .pc 文件,如果用户选择构建一个静态库,我应该在其中放入什么?

此外,我发现 gcc/g++ 没有按照我期望的方式处理库依赖关系,这很烦人:

如果我将我的程序链接到 libabc.so,并且如果 ldd 告诉我 libabc.so 依赖于 libxyz.so,那么我认为 gcc/g++ 应该足够聪明,也可以链接到 libxyz.so。可悲的是,情况似乎并非如此。有什么好的理由为什么这不起作用或者是否有可能强制 gcc/g++ 考虑这些依赖关系?

4

1 回答 1

1

如果您不想指定静态库的完整路径,则无需指定完整路径,但您需要通知链接器您要链接静态库而不是动态库。

这可以通过 to 的-Bstatic参数来完成ld,您可以通过 gcc 或 g++ 传递该参数-Wl,-Bstatic(有变体,请参阅 参考资料man ld)。

例如:

gcc -o main main.c -Wl,-Bstatic -lfoo -Wl,-Bdynamic -lbar

main与 alibfoo.a但 a链接libbar.so。动态是支持 if(对于 GNU ld)的平台上的默认设置。如果你把类似的东西放在一个pkg-config设置或类似的地方,在你的静态库之后重置为默认值是礼貌的。

至于您问题的第二部分,这有点令人费解,因为至少在 Linux 上这不是必需的(或实际上是好的做法)。您的可执行文件应该只包含NEEDED它直接依赖的库的条目。运行时链接器将在必要时负责加载这些依赖项。(为什么这是一个好的做法?因为您不想导入间接依赖项 - 如果您依赖的库更改了自己的依赖项(例如在更新之后),您的可执行文件仍会加载有问题的旧依赖项并且可能引入错误。)

例如,假设我main调用了 in 中的一个函数libfoo.so,而该函数恰好调用了 in 中的一个函数libbar.so。要在可执行文件中注册的“正确”依赖项:

$ readelf -d libbar.so | grep Shared
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
$ readelf -d libfoo.so | grep Shared
 0x0000000000000001 (NEEDED)             Shared library: [libbar.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
$ readelf -d a.out | grep Shared
 0x0000000000000001 (NEEDED)             Shared library: [libfoo.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

ldd(它调用运行时链接器来完成它的工作)可以解决所有问题:

$ ldd a.out 
linux-vdso.so.1 (0x00007fff813ff000)
libfoo.so => ./libfoo.so (0x00007f48ee99d000)
libc.so.6 => /lib64/libc.so.6 (0x00007f48ee5c8000)
libbar.so => ./libbar.so (0x00007f48ee3c6000)
/lib64/ld-linux-x86-64.so.2 (0x00007f48eeb9f000)
于 2013-01-01T16:34:14.923 回答