C++ 如何指定库路径的偏好?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2726993/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:30:57  来源:igfitidea点击:

How to specify preference of library path?

c++linkerg++

提问by Heinrich Schmetterling

I'm compiling a c++ program using g++and ld. I have a .solibrary I want to be used during linking. However, a library of the same name exists in /usr/local/lib, and ldis choosing that library over the one I'm directly specifying. How can I fix this?

我正在使用g++和编译 C++ 程序ld。我有一个.so我想在链接期间使用的库。但是,在 中存在一个同名的库/usr/local/lib,并且ld正在选择该库而不是我直接指定的库。我怎样才能解决这个问题?

For the examples below, my library file is /my/dir/libfoo.so.0. Things I've tried that don't work:

对于下面的示例,我的库文件是/my/dir/libfoo.so.0. 我尝试过但不起作用的事情:

  • my g++ command is g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
  • adding /my/dirto the beginning or end of my $PATHen` variable
  • adding /my/dir/libfoo.so.0as an argument to g++
  • 我的 g++ 命令是 g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
  • 添加/my/dir到我的$PATHen` 变量的开头或结尾
  • /my/dir/libfoo.so.0作为参数添加到 g++

回答by stefanB

Add the path to where your new library is to LD_LIBRARY_PATH(it has slightly different name on Mac ...)

添加新库所在的路径LD_LIBRARY_PATH(它在 Mac 上的名称略有不同......)

Your solution should work with using the -L/my/dir -lfoooptions, at runtime use LD_LIBRARY_PATH to point to the location of your library.

您的解决方案应该使用这些-L/my/dir -lfoo选项,在运行时使用 LD_LIBRARY_PATH 指向您的库的位置。

Careful with using LD_LIBRARY_PATH- in short (from link):

小心使用 LD_LIBRARY_PATH- 简而言之(来自链接):

..implications..:
Security: Remember that the directories specified in LD_LIBRARY_PATH get searched before(!) the standard locations? In that way, a nasty person could get your application to load a version of a shared library that contains malicious code! That's one reason why setuid/setgid executables do neglect that variable!
Performance: The link loader has to search all the directories specified, until it finds the directory where the shared library resides – for ALL shared libraries the application is linked against! This means a lot of system calls to open(), that will fail with “ENOENT (No such file or directory)”! If the path contains many directories, the number of failed calls will increase linearly, and you can tell that from the start-up time of the application. If some (or all) of the directories are in an NFS environment, the start-up time of your applications can really get long – and it can slow down the whole system!
Inconsistency: This is the most common problem. LD_LIBRARY_PATH forces an application to load a shared library it wasn't linked against, and that is quite likely not compatible with the original version. This can either be very obvious, i.e. the application crashes, or it can lead to wrong results, if the picked up library not quite does what the original version would have done. Especially the latter is sometimes hard to debug.

..含义..:
安全性:还记得在 LD_LIBRARY_PATH 中指定的目录在(!)标准位置之前被搜索吗?这样,一个讨厌的人就可以让您的应用程序加载包含恶意代码的共享库版本!这就是 setuid/setgid 可执行文件忽略该变量的原因之一!
表现:链接加载器必须搜索所有指定的目录,直到找到共享库所在的目录 - 对于应用程序链接的所有共享库!这意味着对 open() 的大量系统调用将失败并显示“ENOENT(没有这样的文件或目录)”!如果路径包含很多目录,调用失败的次数会线性增加,这从应用程序的启动时间就可以看出。如果部分(或全部)目录位于 NFS 环境中,那么您的应用程序的启动时间可能会很长——并且会减慢整个系统的速度!
不一致: 这是最常见的问题。LD_LIBRARY_PATH 强制应用程序加载它没有链接的共享库,这很可能与原始版本不兼容。这可能是非常明显的,即应用程序崩溃,或者它可能导致错误的结果,如果选择的库与原始版本不完全相同。尤其是后者有时很难调试。

OR

或者

Use the rpath option via gcc to linker - runtime library search path, will be used instead of looking in standard dir (gcc option):

通过 gcc 使用 rpath 选项到链接器 - 运行时库搜索路径,将用于代替在标准目录中查找(gcc 选项):

-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)

This is good for a temporary solution. Linker first searches the LD_LIBRARY_PATH for libraries before looking into standard directories.

这有利于临时解决方案。在查看标准目录之前,链接器首先在 LD_LIBRARY_PATH 中搜索库。

If you don't want to permanently update LD_LIBRARY_PATH you can do it on the fly on command line:

如果您不想永久更新 LD_LIBRARY_PATH,您可以在命令行上即时进行:

LD_LIBRARY_PATH=/some/custom/dir ./fooo

You can check what libraries linker knows about using (example):

您可以检查链接器知道使用哪些库(示例):

/sbin/ldconfig -p | grep libpthread
        libpthread.so.0 (libc6, OS ABI: Linux 2.6.4) => /lib/libpthread.so.0

And you can check which library your application is using:

您可以检查您的应用程序正在使用哪个库:

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)

回答by Michael Speer

This is an old question, but no one seems to have mentioned this.

这是一个老问题,但似乎没有人提到过这一点。

You were getting lucky that the thing was linking at all.

你很幸运,这件事完全链接起来了。

You needed to change

你需要改变

g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp

to this:

对此:

g++ -g -Wall -o my_binary -L/my/dir bar.cpp -lfoo

Your linker keeps track of symbols it needs to resolve. If it reads the library first, it doesn't have any needed symbols, so it ignores the symbols in it. Specify the libraries after the things that need to link to them so that your linker has symbols to find in them.

您的链接器会跟踪它需要解析的符号。如果它首先读取库,它没有任何需要的符号,因此它会忽略其中的符号。在需要链接到它们的东西之后指定库,以便您的链接器可以在其中找到符号。

Also, -lfoomakes it search specifically for a file named libfoo.aor libfoo.soas needed. Not libfoo.so.0. So either lnthe name or rename the library as appopriate.

此外,-lfoo使其专门搜索命名libfoo.alibfoo.so根据需要的文件。不是libfoo.so.0。因此ln,名称或将库重命名为适当的。

To quote the gcc man page:

引用 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.

Adding the file directly to g++'s command line should have worked, unless of course, you put it prior to bar.cpp, causing the linker to ignore it for lacking any needed symbols, because no symbols were needed yet.

将文件直接添加到g++的命令行应该会起作用,当然,除非您将它放在 之前bar.cpp,导致链接器因缺少任何所需符号而忽略它,因为还不需要任何符号。

回答by R Samuel Klatchko

Specifying the absolute path to the library should work fine:

指定库的绝对路径应该可以正常工作:

g++ /my/dir/libfoo.so.0  ...

Did you remember to remove the -lfooonce you added the absolute path?

您是否记得在-lfoo添加绝对路径后删除?

回答by Alexandre Hamez

As an alternative, you can use the environment variables LIBRARY_PATHand CPLUS_INCLUDE_PATH, which respectively indicate where to look for libraries and where to look for headers (CPATHwill also do the job), without specifying the -L and -I options.

作为替代方案,您可以使用环境变量LIBRARY_PATHand CPLUS_INCLUDE_PATH,它们分别指示在何处查找库和在何处查找标头(CPATH也将完成该工作),而无需指定 -L 和 -I 选项。

Edit: CPATHincludes header with -Iand CPLUS_INCLUDE_PATHwith -isystem.

编辑: CPATH包括与报头-ICPLUS_INCLUDE_PATH-isystem

回答by Pekka Lehtikoski

If one is used to work with DLL in Windows and would like to skip .so version numbers in linux/QT, adding CONFIG += pluginwill take version numbers out. To use absolute path to .so, giving it to linker works fine, as Mr. Klatchko mentioned.

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