我目前正在做一个更大的项目,里面包含了很多库,我对为什么在linux下的gcc会有这样的表现有一些疑问。
首先,我想您可能已经知道,您可以使用"-lxyz“链接器标志连接到gcc/g++,以便在一些系统路径中搜索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++考虑这些依赖关系?
发布于 2013-01-02 00:34:15
如果您不想为静态库指定完整路径,则无需为其指定完整路径,但您需要告知链接器您希望链接到静态库而不是动态库。
这可以通过将-Bstatic参数传递给ld来完成,您可以通过gcc或带有-Wl,-Bstatic的g++传递该参数(有一些变体,请参阅man ld)。
例如:
gcc -o main main.c -Wl,-Bstatic -lfoo -Wl,-Bdynamic -lbar会将main链接到一个libfoo.a,而不是一个libbar.so。在支持if (用于GNU ld)的平台上,动态是默认的。如果您将类似的内容放入pkg-config设置或类似设置中,那么在静态库之后将其重置为默认值是有礼貌的。
至于你问题的第二部分,它有点令人费解,因为至少在Linux上这不是必要的(或者实际上是好的实践)。对于它直接依赖的库,您的可执行文件应该只有NEEDED条目。运行时链接器将在必要时加载这些依赖项。(为什么这是一个好的实践?因为你不想导入间接依赖关系--如果你依赖的库改变了它自己的依赖关系(例如,在更新之后),你的可执行文件仍然会加载旧的依赖关系,这是有问题的,并且可能会引入bug。)
例如,假设我有一个main,它调用libfoo.so中的函数,而该函数恰好调用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)https://stackoverflow.com/questions/14111929
复制相似问题