a.so
定义函数A()
,b.so
定义函数B()
并调用A()
中定义的a.so
。 b.so
与a.so
相关联,如下所示
gcc -fPIC -shared B.c -o libb.so -la
现在我创建了一个调用B()
b.so
的二进制文件
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
相关联就可以了。
这可能吗?
答案 0 :(得分:3)
链接可执行文件时,链接器想要知道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
这会在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在运行时查找它。或者,您可以在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]
答案 1 :(得分:2)
缺失的位是LD_LIBRARY_PATH
:
export LD_LIBRARY_PATH=.
gcc -fPIC -shared a.c -o liba.so
gcc -fPIC -shared b.c -o libb.so -la
gcc mybin.c -o mybin -lb -L.
-L
不起作用的原因似乎是这个标志用于«将目录dir添加到要搜索的目录列表 for -l </ strong>»,请参阅{{3 }}。并且libba.so
中未指定-l
。
答案 2 :(得分:0)
以下是步骤:
gcc -fPIC -shared a.c -o liba.so
gcc -fPIC -shared b.c -o libb.so
gcc mybin.c -o mybin -lb -la -L. # -L to look for the directory to load .so files
Then make sure you do:
export LD_LIBRARY_PATH=<your_directory>
你需要在gcc mybin.c -o mybin -lb -la -L中提到liba.so和libb.so。因为函数A()需要在运行时加载。 b.so没有链接a.so.链接发生在共享库中的运行时。它们已编译,并且未解析对函数或外部变量的任何引用。
如果要包含b.so但不包含a.so,则将b编译为静态库,从而将a加载到其二进制文件中。然后当你编译mybin时,你只需要b.lib