a.so
定义函数A()
,b.so
定义函数B()
并调用A()
在 a.so
中定义。 b.so
链接到 a.so
如下
gcc -fPIC -shared B.c -o libb.so -la
现在我创建了一个二进制文件,它调用在 b.so
中定义的 B()
gcc mybin.c -o mybin -lb
gcc 正在检查 b.so 中的每个符号并抛出错误,指出 A()
未定义。
gcc mybin.c -o mybin -lb -la
上面的方法有效,但我必须将 mybin 与 a.so
链接,即使它与 a.so
没有直接关系。我的要求是,如果 b.so
与 a.so
正确链接,则仅将 mybin 与 b.so
链接> 应该可以。
这可能吗?
最佳答案
链接可执行文件时,链接器想知道 libb.so
所需的库存在,以便它可以检查它们解析 libb.so
中任何 undefined reference
链接器在通常的位置查找所需的库,因此如果找不到 liba.so
那么你可以使用 LD_LIBRARY_PATH
告诉链接器去哪里查找如另一个答案所示,或者通过使用专门为此目的而存在的链接器选项, -rpath-link
gcc mybin.c -o mybin -lb -Wl,-rpath-link=.
(-Wl,
前缀是告诉 GCC 将选项传递给链接器的方式,这是 GCC 不直接了解的链接器选项所需要的。)
或者,您可以告诉链接器允许libb.so
中 undefined symbol 。在这种情况下,它不会尝试查找 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
这会产生 DT_RPATH
标签 libb.so
链接器将使用它来查找其依赖项:
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 在运行时查找它。或者您可以使用特殊字符串 $ORIGIN
在 RPATH 中,动态链接器将其扩展为包含 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]
关于c - 将一个 .so 与另一个 .so 链接时 undefined symbol ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27422303/