当您使用 cc(1)
链接程序时,它将调用默认链接器命令。例如,您的编译器版本可能已构建为在类 unix 平台上默认使用 /usr/bin/ld。
Is there a way to specify a different linker command that cc(1)
(or c++(1)
) should use (eg, /usr/local/bin/ld
instead of /usr/bin/ld
) ?我主要对 gcc 和 clang 感兴趣。
我不是在寻找涉及单独运行各种编译步骤(例如,预处理、编译、汇编、链接)的方法。
例如,我希望这样的事情可以完成这项工作:
env LD=/usr/local/bin/ld cc foo.c -o foo
但这不适用于 gcc 或 clang。当然,如果您有一个先构建目标文件的生成文件,然后调用 ${LD} 进行链接(例如, env LD=/usr/local/bin/ld make
),它会起作用
更新(有一个可能的动机):使用与默认链接器不同的链接器轻松测试。例如,如果能够做到这一点,那就太好了:
cc --linker=/usr/local/bin/ld foo.c -o foo
相反,您必须生成目标文件,运行 cc -v
找出 ld
的参数,手动运行 ld
你想要的参数
cc -c foo.c
cc -v foo.c -o /dev/null
现在查看链接器调用并手动复制/粘贴替换链接器和临时目标文件。像这样的东西(示例取自 Fedora 23 上的测试),您将 /usr/libexec/gcc/x86_64-redhat-linux/5.3.1/collect2
替换为 /usr/local/bin/ld
(尽管它与 collect2
不 _完全相同_):
/usr/local/bin/ld -plugin /usr/libexec/gcc/x86_64-redhat-linux/5.3.1/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/5.3.1/lto-wrapper -plugin-opt=-fresolution=/tmp/jhein/ccM2XKIg.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o c /usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/5.3.1/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/5.3.1 -L/usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../.. c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/5.3.1/crtend.o /usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../../../lib64/crtn.o
如您所见,这并不容易。请注意,gcc 信息页面中有关于 collect2 如何查找链接器程序的文档。但是根据那些文档,它首先看起来不是环境变量或您可以在命令行上指定的东西(例如,–linker)。文档说它 首先 查找“硬编码的链接器文件名”。如果该文档是正确的,要强制它不使用该链接器(即欺骗它),您必须重命名默认链接器(例如, sudo mv /usr/bin/ld /usr/bin/ld.tmp-disable
)。
更新 2 :使用 -B
似乎可以很好地满足我的需要。请参阅下面我发布答案的地方。我不能接受自己的答案,但如果可以的话,我会接受——这似乎很好地解决了这个问题。
原文由 Juan 发布,翻译遵循 CC BY-SA 4.0 许可协议
-B
选项允许您为编译器将使用的可执行文件、库、包含文件和数据文件指定备用搜索路径。这适用于某些版本的 gcc [1] 和 clang(目前未记录 - 在至少 clang 3.7 和 3.8 的手册页中):请注意,这将导致 cc 在
-B
指定的路径中搜索其他工具(例如,汇编程序)。因此,假设您在 /usr/local/bin 中安装了不同版本的 binutils,如果您 只想 使用该链接器(而不是/usr/local/bin/as
等),您可以执行以下操作:-B
有自己的一套规则,允许您覆盖 gcc 编译器尝试使用的不同文件(程序、库、包含文件、数据文件)。这至少可以追溯到 gcc 2.95 - 阅读 gcc 手册/信息页面。我不知道-B
的行为与 clang 的兼容性如何。如前所述,它目前没有记录在 clang 手册页中。但它工作得很好,可以让我选择一个备用链接器,如上所示。gcc
还支持调用由-wrapper
指定的脚本/程序。clang
(目前)没有。您也可以使用它并指向一个包装脚本,该脚本会改变编译器正在调用的程序。 I don’t know ifcollect2
the-wrapper
option (and forgcc
,collect2
is what calls the linker when compiling c/至少 c++ 程序)。[1] —
collect2
gcc
的信息页面中记录的链接器搜索顺序表示,如果 GCC 配置了 ‘– ,它将首先搜索“硬编码的链接器文件名”带有-ld’选项”)。所以如果你的 gcc 没有配置 ‘–with-ld’,那么它最终会在-B
指定的路径中搜索(如果它没有找到real-ld
首先)。如果您的 gcc 配置 为--with-ld
,那么-B
选项将无法帮助您指定您选择的备用链接器。