如何打印ld(链接器)搜索路径

203

如何以搜索顺序打印被ld查找的搜索路径。

6个回答

159
您可以通过执行以下命令来实现此目的:
ld --verbose | grep SEARCH_DIR | tr -s ' ;' \\012

gcc会向链接器传递一些额外的-L路径,您可以使用以下命令列出这些路径:

gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,;  ,g' | tr \; \\012

建议使用ld.so.conf和ldconfig的答案是不正确的,因为它们是在运行时动态链接器搜索的路径(即每次执行程序时),这与由ld搜索的路径不同(即每次链接程序时)。

2
你说得对。我遇到了一个链接问题,在链接过程中,链接器在 /usr/local/.. 中找到了手动安装的库,导致缺少库错误,链接失败。我必须每次重命名 /usr/local 以排除该搜索路径。有没有一种简单的方法来排除或覆盖 /usr/local 路径? - kenn
1
你可以尝试使用GCC的-L选项手动指定库路径,我认为(不确定)这将覆盖系统库路径。在编译之前,你还可以尝试设置LIBRARY_PATH环境变量:$ LIBRARY_PATH=/somedir/ gcc ... - faken
1
我知道在命令行编译中如何进行链接。但我想找到一种全局的方法来覆盖ld的搜索路径。例如,有时我需要从makefile编译源代码,或者从configure脚本或CMakeLists.txt生成makefile,甚至更复杂的情况,如valasrt。在这些情况下修改ld搜索路径很困难。 - kenn
使用CMake时,您可以在配置阶段选择要使用的确切库(其中一些条目仅在高级模式下显示)。至于来自Autotools的配置脚本,请参见此答案:https://dev59.com/0Wsz5IYBdhLWcg3w8Mcb。这并没有直接回答您的问题,但可能会帮助您实现所需的功能。 - faken
2
啊,现在这就解释了为什么在Centos中使用本地库构建是如此不稳定。包含路径搜索顺序为/usr/local/include然后是/usr/include,而链接器搜索顺序为/usr/lib64然后是/usr/local/lib64 - coladict
为什么如果我在gcc中添加选项-Lpath,我看不到gcc -print-search-dirs输出中的更改? - Филя Усков

92
在Linux系统中,您可以使用ldconfig命令来维护ld.so的配置和缓存,并打印出被ld.so搜索的目录。
ldconfig -v 2>/dev/null | grep -v ^$'\t'

ldconfig -v 命令输出链接器搜索的目录(无前导制表符),以及在这些目录中找到的共享库(带前导制表符);grep 获取这些目录。在我的机器上,这行命令会输出:

/usr/lib64/atlas:
/usr/lib/llvm:
/usr/lib64/llvm:
/usr/lib64/mysql:
/usr/lib64/nvidia:
/usr/lib64/tracker-0.12:
/usr/lib/wine:
/usr/lib64/wine:
/usr/lib64/xulrunner-2:
/lib:
/lib64:
/usr/lib:
/usr/lib64:
/usr/lib64/nvidia/tls: (hwcap: 0x8000000000000000)
/lib/i686: (hwcap: 0x0008000000000000)
/lib64/tls: (hwcap: 0x8000000000000000)
/usr/lib/sse2: (hwcap: 0x0000000004000000)
/usr/lib64/tls: (hwcap: 0x8000000000000000)
/usr/lib64/sse2: (hwcap: 0x0000000004000000)

首先的路径,没有hwcap在行中,要么是内置的,要么是从/etc/ld.so.conf读取的。 然后链接器可以在基本库搜索路径下搜索名称为sse2的具有额外CPU功能的其他目录。 这些带有hwcap的路径可以包含针对这些CPU功能量身定制的附加库。

最后一点说明:使用-p而不是上面的-v会搜索ld.so缓存。


62
他在询问链接器(ld),而不是装载器(ld.so)! - fons
3
如果我设置 export LD_LIBRARY_PATH=/some/other/dir,为什么这个命令的输出不会受到影响?!看起来它没有完全生效? - Tomas
4
有趣的是我在寻找这个答案时来到了这里。:) 链接时间或运行时间路径?我想这就是问题所在。LIBRARY_PATH(链接时间)与LD_LIBRARY_PATH。 - Daniel Santos
2
我在一些平台上发现(例如使用Linaro工具链的arm),ldconfig实际上并没有搜索与运行时链接器相同的目录。您可以通过启用调试来获得其搜索路径,并包括来自LD_LIBRARY_PATH的路径。例如。 LD_DEBUG = libs / lib / ld-linux.so --list cat(您可以使用任何可执行文件,我选择了cat作为我能想到的第一件事)。值得注意的是,如果您有一个与所有所需库匹配的/etc/ld.so.cache,则无法看到内置系统搜索路径,因为它不会走那么远。 - John O'M.
gcc 的搜索路径和这些路径一样吗? - nn0p
1
在FreeBSD上使用ldconfig -v时要小心,它会永久删除所有配置的目录。在FreeBSD上请改用ldconfig -r - rustyx

75

我不确定是否有简单打印完整有效搜索路径的选项。

但是:搜索路径由在命令行上使用 -L 选项指定的目录组成,后面跟着链接脚本中的 SEARCH_DIR("...") 指令添加到搜索路径中的目录。因此,如果你能看到这两个东西,你就可以计算出它了,具体操作如下:

如果你直接调用 ld

  • -L 选项是你所说的选项。
  • 要查看链接脚本,请添加 --verbose 选项。查找 SEARCH_DIR("...") 指令,通常在输出的顶部附近。(请注意,这些对于每次调用 ld 不一定相同-- 链接器具有许多不同的内置默认链接器脚本,并根据各种其他链接器选项进行选择。)

如果通过 gcc 进行链接:

  • 可以向 gcc 传递 -v 选项,以便显示它如何调用链接器。实际上,它通常不直接调用 ld,而是间接地通过一个名为 collect2 的工具(位于其内部目录之一)调用它,然后调用 ld。这将显示正在使用哪些 -L 选项。
  • 可以向 gcc 选项中添加 -Wl,--verbose,使其将 --verbose 传递到链接器,以查看上述描述的链接器脚本。

6
链接器的--verbose选项解决了问题。非常有用! - Ari
我一直在努力找出链接器的查找路径,但在输出中没有找到SEARCH_DIR。结果发现,由于我使用了“-T script”,我的脚本完全替换了ld的默认脚本,并且只查找了我指定的路径。 - thomasa88

35

在Linux上,我发现最兼容的gcc和clang命令是(感谢armando.sano):

$ gcc -m64 -Xlinker --verbose  2>/dev/null | grep SEARCH | sed 's/SEARCH_DIR("=\?\([^"]\+\)"); */\1\n/g'  | grep -vE '^$'

如果您提供-m32,它将输出正确的库目录。

在我的计算机上的示例:

对于g++ -m64

/usr/x86_64-linux-gnu/lib64
/usr/i686-linux-gnu/lib64
/usr/local/lib/x86_64-linux-gnu
/usr/local/lib64
/lib/x86_64-linux-gnu
/lib64
/usr/lib/x86_64-linux-gnu
/usr/lib64
/usr/local/lib
/lib
/usr/lib

对于 g++ -m32

/usr/i686-linux-gnu/lib32
/usr/local/lib32
/lib32
/usr/lib32
/usr/local/lib/i386-linux-gnu
/usr/local/lib
/lib/i386-linux-gnu
/lib
/usr/lib/i386-linux-gnu
/usr/lib

谢谢!微小的改进——去掉一两个grep:sed -n 's/SEARCH_DIR("=?([^"]+)"); */\1\n/gp' - Bruce K
5
为什么需要使用这样晦涩的方法? - bmacnaughton
这个运行得非常好!我们如何将目录添加到此列表中,链接器搜索路径? - pari

6
这个问题标记为Linux,但也许在Linux下同样有效吗?
gcc -Xlinker -v

在Mac OS X下,这将打印出:
@(#)PROGRAM:ld  PROJECT:ld64-224.1
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 armv6m armv7m armv7em
Library search paths:
    /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/lib
Framework search paths:
    /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/
[...]
gcc-Xlinker选项只是将-v传递给ld。然而:
ld -v

未打印搜索路径。


在Linux上,它也会打印目录,但是以“-Lpath”的形式。因此,@Raphaël Londeix的答案更好。 - pevik

3

Mac版本:$ ld -v 2,不知道如何获取详细路径。输出。

Library search paths:
    /usr/lib
    /usr/local/lib
Framework search paths:
    /Library/Frameworks/
    /System/Library/Frameworks/

6
我收到了“无法打开2: 没有那个文件或目录”的错误信息。运行ld -v 2 - Jacklynn
3
这个问题标记为Linux,而不是OS X。我不相信OS X使用GNU的ld。Binutil的开发者在构建脚本中禁用了它。已经被禁用多年了。 - jww

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接