如何指定库路径的首选项?

时间:2010-04-28 05:17:07

标签: c++ linker g++

我正在使用g++ld编译c ++程序。我想要在链接期间使用.so库。但是,/usr/local/lib中存在同名的库,而ld正在选择我直接指定的库。我该如何解决这个问题?

对于以下示例,我的库文件为/my/dir/libfoo.so.0。我尝试过的东西不起作用:

  • 我的g ++命令是g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
  • /my/dir添加到$PATH en`变量的开头或结尾
  • /my/dir/libfoo.so.0作为参数添加到g ++

5 个答案:

答案 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.alibfoo.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_PATHCPLUS_INCLUDE_PATH,它们分别指示在哪里查找库以及在哪里查找标题(CPATH也可以完成工作),而不指定-L和-I选项。

编辑: CPATH包含-I标题和CPLUS_INCLUDE_PATH -isystem标题。

答案 4 :(得分:0)

如果一个用于在Windows中使用DLL并希望在linux / QT中跳过.so版本号,则添加CONFIG += plugin将取出版本号。要使用.so的绝对路径,将其提供给链接器的工作正常,正如Klatchko先生所提到的那样。