【问题标题】:How to print the ld(linker) search path如何打印 ld(linker) 搜索路径
【发布时间】:2012-04-12 22:57:28
【问题描述】:

按照ld搜索的顺序打印搜索路径的方法是什么。

【问题讨论】:

    标签: linux gcc linker ld


    【解决方案1】:

    您可以通过执行以下命令来做到这一点:

    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(即每当链接程序时)。

    【讨论】:

    • 你说的对。我有一个链接问题,在链接过程中链接器在/usr/local/.. 中找到手动安装的库,这会导致缺少库错误,并且链接失败。我每次都必须重命名/usr/local 以排除该搜索路径。有没有简单的方法来排除或覆盖/usr/local 路径?
    • 您可以尝试使用 GCC 的 -L 选项手动指定库路径,我认为(不确定)会覆盖系统库路径。您也可以在编译前尝试设置 LIBRARY_PATH 环境变量: $ LIBRARY_PATH=/somedir/ gcc ...
    • 我知道命令行编译中的链接。我的意思是一种覆盖lds 搜索路径的全局方法。例如,有时我必须从makefile 编译源代码或从configure 脚本或CMakeLists.txt 甚至更复杂的诸如valasrt 生成makefile。在这种情况下我很难修改ld搜索路径
    • 使用 CMake 时,您可以选择在配置阶段使用的确切库(其中一些条目仅在高级模式下显示)。至于来自 Autotools 的配置脚本,请参阅此答案:stackoverflow.com/questions/7561509/…。这不会直接回答您的问题,但可能会帮助您做您想做的事。
    • 啊,现在这就解释了为什么在 Centos 中使用本地库构建如此糟糕。包括路径搜索是/usr/local/include 然后是/usr/include,而链接器搜索是/usr/lib64 然后是/usr/local/lib64
    【解决方案2】:

    在 Linux 上,您可以使用维护 ld.so 配置和缓存的ldconfig 打印出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 缓存。

    【讨论】:

    • 他问的是链接器(ld)而不是加载器(ld.so)!
    • 我设置export LD_LIBRARY_PATH=/some/other/dir怎么可能不影响这个命令的输出?!好像不是 100% 有效?
    • @fons 有趣的是我来这里是为了寻找这个答案。 :) 链接时或运行时路径?我想这就是问题所在。 LIBRAY_PATH(链接时间)与 LD_LIBRARY_PATH。
    • 我在某些平台(例如带有 Linaro 工具链的 arm)上发现 ldconfig 实际上并不搜索与运行时链接器相同的目录。您可以让它输出其搜索路径,并通过启用调试包含来自LD_LIBRARY_PATH 的路径。例如。 LD_DEBUG=libs /lib/ld-linux.so --list cat(你可以使用任何可执行文件,我首先想到的是cat)。 “search path”可能值得一试。请注意,如果您有一个匹配所有需要的库的/etc/ld.so.cache,您将看不到内置的系统搜索路径,因为它不会走那么远。
    • 在 FreeBSD 上小心ldconfig -v,它将永久删除所有配置的目录。在 FreeBSD 上使用 ldconfig -r
    【解决方案3】:

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

    但是:搜索路径由命令行中-L 选项指定的目录组成,然后是链接描述文件中SEARCH_DIR("...") 指令添加到搜索路径的目录。所以如果你能看到这两个,你就可以计算出来,你可以这样做:

    如果您直接调用ld

    • -L 选项就是您所说的。
    • 要查看链接描述文件,请添加--verbose 选项。查找SEARCH_DIR("...") 指令,通常位于输出顶部附近。 (请注意,ld 的每次调用不一定都相同——链接器有许多不同的内置默认链接器脚本,并根据各种其他链接器选项在它们之间进行选择。)

    如果您通过gcc 链接:

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

    【讨论】:

    • 链接器的 --verbose 选项起到了作用。很有帮助!
    • 我正在努力找出链接器正在寻找的位置,但没有在输出中找到 SEARCH_DIR。结果当我使用-T script 时,我的脚本完全替换了 ld 的默认脚本,并且只查看了我指向的位置。
    【解决方案4】:

    我在 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'
    • 为什么需要这么晦涩的方法?
    • 这就像一个魅力!我们如何在这个列表中添加目录,链接器搜索路径?
    【解决方案5】:

    问题被标记为 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 的答案更好。
    【解决方案6】:

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

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

    【讨论】:

    • 我得到“无法打开 2:没有这样的文件或目录”。运行ld -v 2
    • 问题标记为 Linux,而不是 OS X。我不相信 OS X 使用 GNU 的 ld。 Binutil 人在构建脚本中禁用了它。它已被禁用多年。
    猜你喜欢
    • 1970-01-01
    • 2017-01-15
    • 2011-10-30
    • 1970-01-01
    • 2012-04-27
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 2013-02-01
    相关资源
    最近更新 更多