【发布时间】:2016-11-07 17:22:29
【问题描述】:
当您使用cc(1) 链接程序时,它将调用默认链接器命令。例如,您的编译器版本可能已构建为在类 unix 平台上默认使用 /usr/bin/ld。
有没有办法指定cc(1)(或c++(1))应该使用的不同链接器命令(例如,/usr/local/bin/ld 而不是/usr/bin/ld)?我主要对 gcc 和 clang 感兴趣。
我不是在寻找涉及单独运行各种编译步骤(例如,预处理、编译、汇编、链接)的方法。
例如,我希望这样的事情可以完成这项工作:
env LD=/usr/local/bin/ld cc foo.c -o foo
但这不适用于 gcc 或 clang。当然,如果你有一个先构建目标文件的 makefile,然后调用 ${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)。文档说它看起来 first 是“硬编码的链接器文件名”。如果该文档是正确的,要强制它不使用该链接器(即欺骗它),您必须重命名默认链接器(例如,sudo mv /usr/bin/ld /usr/bin/ld.tmp-disable)。
更新 2:使用 -B 似乎可以很好地满足我的需求。请参阅下面我发布答案的地方。我不能接受自己的答案,但如果可以的话,我会接受——这似乎很好地解决了问题。
【问题讨论】:
-
cc只是gcc、clang或系统使用的任何默认 C 编译器的别名。 -
@BasileStarynkevitch:我问是因为我想测试与安装在 /usr/bin 中的链接器不同的链接器。这里没有XY问题。只是针对不同版本的链接器进行测试。
-
@Olaf:是的,我知道 cc 是什么。我特别提到我已经知道拆分编译器/链接器步骤的方法。这个问题专门关于如何告诉 cc(它可以通过一次调用 cc 来执行所有构建阶段)如何使用与构建 cc 时默认指定的链接器不同的链接器。也许您不知道 cc 可以调用链接器(尝试使用
cc -v helloworld.c构建一个简单的 C 程序)。 -
看起来像 XY 问题。 为什么您要使用与默认链接器不同的链接器?对于正常编译,这应该是您想要的,对于交叉编译,您应该使用适当的工具链,其中还包括正确的链接器。
-
评论不是问题的一部分。您应该编辑问题,查看How to Ask 并阅读常见问题解答。但是,是的,我监督巴兹尔已经怀疑过同样的事情。不过,我不明白你的问题是什么。
cc用于默认编译/构建。对于任何较大的程序,无论如何您都应该使用构建工具,它们总是允许单独指定编译器和链接器。