我正在使用g++
和ld
编译c ++程序。我想要在链接期间使用.so
库。但是,/usr/local/lib
中存在同名的库,而ld
正在选择我直接指定的库。我该如何解决这个问题?
对于以下示例,我的库文件为/my/dir/libfoo.so.0
。我尝试过的东西不起作用:
g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
/my/dir
添加到$PATH
en`变量的开头或结尾/my/dir/libfoo.so.0
作为参数添加到g ++ 答案 0 :(得分:79)
将新库的路径添加到LD_LIBRARY_PATH
(在Mac上的名称略有不同......)
您的解决方案应该使用-L/my/dir -lfoo
选项,在运行时使用LD_LIBRARY_PATH指向库的位置。
Careful with using LD_LIBRARY_PATH - 简而言之(来自链接):
.. ..含义:
安全性:请记住LD_LIBRARY_PATH中指定的目录在(!)标准位置之前被搜索?在那里面 一个讨厌的人可以让你的应用程序加载一个版本的 包含恶意代码的共享库!这就是原因之一 setuid / setgid可执行文件确实忽略了那个变量! 性能:链接加载器必须搜索指定的所有目录,直到找到共享库的目录 驻留 - 对于所有共享库,应用程序链接! 这意味着很多系统调用open(),这将失败 “ENOENT(没有这样的文件或目录)”!如果路径包含很多 目录,失败的呼叫数量将线性增加,并且 你可以从应用程序的启动时间告诉你。如果有的话 (或所有)目录都在NFS环境中启动 您的应用程序的时间可能真的很长 - 它可能会变慢 整个系统!
不一致:这是最常见的问题。 LD_LIBRARY_PATH强制应用程序加载未链接的共享库 反对,这很可能与原版不兼容 版。这可能非常明显,即应用程序 崩溃,或者它可能导致错误的结果,如果拾取的库不 完全是原始版本会做的。特别是 后者有时难以调试。
OR
通过gcc使用rpath选项到链接器 - 将使用运行时库搜索路径 而不是寻找标准目录(gcc选项):
-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)
这对临时解决方案很有用。在查看标准目录之前,链接器首先在LD_LIBRARY_PATH中搜索库。
如果您不想永久更新LD_LIBRARY_PATH,可以在命令行上执行此操作:
LD_LIBRARY_PATH=/some/custom/dir ./fooo
您可以查看链接器使用(示例):
了解的库/sbin/ldconfig -p | grep libpthread
libpthread.so.0 (libc6, OS ABI: Linux 2.6.4) => /lib/libpthread.so.0
您可以查看您的应用程序使用的库:
ldd foo
linux-gate.so.1 => (0xffffe000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb7f9e000)
libxml2.so.2 => /usr/lib/libxml2.so.2 (0xb7e6e000)
librt.so.1 => /lib/librt.so.1 (0xb7e65000)
libm.so.6 => /lib/libm.so.6 (0xb7d5b000)
libc.so.6 => /lib/libc.so.6 (0xb7c2e000)
/lib/ld-linux.so.2 (0xb7fc7000)
libdl.so.2 => /lib/libdl.so.2 (0xb7c2a000)
libz.so.1 => /lib/libz.so.1 (0xb7c18000)
答案 1 :(得分:20)
指定库的绝对路径应该可以正常工作:
g++ /my/dir/libfoo.so.0 ...
您是否记得在添加绝对路径后删除-lfoo
?
答案 2 :(得分:16)
这是一个老问题,但似乎没有人提到这一点。
你很幸运,事情就是联系在一起。
您需要更改
g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
到此:
g++ -g -Wall -o my_binary -L/my/dir bar.cpp -lfoo
您的链接器会跟踪需要解析的符号。如果它首先读取库, 它没有任何所需的符号,所以它忽略了它中的符号。在需要的东西之后指定库 链接到它们,以便您的链接器具有要在其中查找的符号。
此外,-lfoo
可以根据需要专门搜索名为libfoo.a
或libfoo.so
的文件。不是libfoo.so.0
。因此要么ln
要么命名,要么将库重命名为appopriate。
引用gcc手册页:
-l library
...
It makes a difference where in the command you
write this option; the linker searches and processes
libraries and object files in the order they are
specified. Thus, foo.o -lz bar.o searches library z
after file foo.o but before bar.o. If bar.o refers
to functions in z, those functions may not be loaded.
直接将文件添加到g++
的命令行应该有效,
当然,除非你把它放在bar.cpp
之前,导致链接器
忽略它缺少任何需要的符号,因为还没有符号。
答案 3 :(得分:11)
作为替代方案,您可以使用环境变量LIBRARY_PATH
和CPLUS_INCLUDE_PATH
,它们分别指示在哪里查找库以及在哪里查找标题(CPATH
也可以完成工作),而不指定-L和-I选项。
编辑:
CPATH
包含-I
标题和CPLUS_INCLUDE_PATH
-isystem
标题。
答案 4 :(得分:0)
如果一个用于在Windows中使用DLL并希望在linux / QT中跳过.so版本号,则添加CONFIG += plugin
将取出版本号。要使用.so的绝对路径,将其提供给链接器的工作正常,正如Klatchko先生所提到的那样。