链接可执行文件时,链接器想知道libb.so 所需的库是否存在,以便检查它们是否解析libb.so 中的任何未定义引用
链接器在通常的位置查找所需的库,因此如果找不到liba.so,那么您可以使用LD_LIBRARY_PATH 告诉链接器在哪里查找,如另一个答案所示,或者使用链接器专门为此目的而存在的选项,-rpath-link
gcc mybin.c -o mybin -lb -Wl,-rpath-link=.
(-Wl, 前缀是告诉 GCC 将选项传递给链接器的方式,这是 GCC 不直接知道的链接器选项所必需的。)
或者,您可以告诉链接器在 libb.so 中允许未定义的符号,在这种情况下,它不会尝试找到 liba.so 来解析对 A() 的引用,并相信您将正确链接并确保该库在运行时可用。这是通过--allow-shlib-undefined 选项完成的:
gcc mybin.c -o mybin -lb -Wl,--allow-shlib-undefined
但是,通常最好让链接器检查所有符号是否已定义,并告诉它如何找到所需的库,因为它会更快地发现真正的问题。
-rpath-link 选项only 告诉链接器在哪里寻找额外的共享库,它对链接的可执行文件没有可见的影响(即它不会在可在任何地方执行)。另一种选择是创建libb.so,以便它包含如何找到嵌入其中的liba.so 的知识。这是通过 -rpath 链接器选项完成的,例如如果liba.so 在/some/path 中,您可以这样做:
gcc -fPIC -shared B.c -o libb.so -la -Wl,-rpath=/some/path
这会在libb.so 中添加一个DT_RPATH 标记,链接器将使用它来查找其依赖项:
readelf -d libb.so | fgrep RPATH
0x000000000000000f (RPATH) Library rpath: [/some/path]
现在您无需了解liba.so 即可链接可执行文件,链接器将看到libb.so 需要liba.so 并使用RPATH 找到它:
gcc mybin.c -o mybin -lb
如果路径/some/path/liba.so 是固定的,这可以正常工作,但在开发期间和部署可执行文件之后在同一位置找到库可能不是真的。在这种情况下,您仍然可以对可执行文件使用-rpath-link 来告诉链接器在链接期间在哪里寻找它,并依靠 RPATH 在运行时找到它。或者您可以在 RPATH 中使用特殊字符串 $ORIGIN,动态链接器将其扩展到包含 RPATH 的对象的位置,例如如果liba.so 和libb.so 始终在同一个目录中,您可以像这样链接libb.so(注意引号以防止shell 扩展$ORIGIN):
gcc -fPIC -shared B.c -o libb.so -la '-Wl,-rpath=$ORIGIN'
readelf -d libb.so | fgrep RPATH
0x000000000000000f (RPATH) Library rpath: [$ORIGIN]