与“cc”链接时如何指定备用链接器命令

新手上路,请多包涵

当您使用 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 许可协议

阅读 741
2 个回答

-B 选项允许您为编译器将使用的可执行文件、库、包含文件和数据文件指定备用搜索路径。这适用于某些版本的 gcc [1] 和 clang(目前未记录 - 在至少 clang 3.7 和 3.8 的手册页中):

 cc -B/usr/local/bin foo.c -o foo

请注意,这将导致 cc 在 -B 指定的路径中搜索其他工具(例如,汇编程序)。因此,假设您在 /usr/local/bin 中安装了不同版本的 binutils,如果您 只想 使用该链接器(而不是 /usr/local/bin/as 等),您可以执行以下操作:

 mkdir /tmp/usemyld
ln -s /usr/local/bin/ld /tmp/usemyld
cc -B/tmp/usemyld foo.c -o foo

-B 有自己的一套规则,允许您覆盖 gcc 编译器尝试使用的不同文件(程序、库、包含文件、数据文件)。这至少可以追溯到 gcc 2.95 - 阅读 gcc 手册/信息页面。我不知道 -B 的行为与 clang 的兼容性如何。如前所述,它目前没有记录在 clang 手册页中。但它工作得很好,可以让我选择一个备用链接器,如上所示。

gcc 还支持调用由 -wrapper 指定的脚本/程序。 clang (目前)没有。您也可以使用它并指向一个包装脚本,该脚本会改变编译器正在调用的程序。 I don’t know if collect2 the -wrapper option (and for gcc , 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 选项将无法帮助您指定您选择的备用链接器。

原文由 Juan 发布,翻译遵循 CC BY-SA 3.0 许可协议

GCC 使用内部 规范文件(决定 gcc 程序的行为方式,特别是它如何链接以及使用什么链接器)。您可以 使用 -specs= 配置或更改它,因此拥有自己的规范文件并使用它。或使用 -T 选项(属于 gcc 明确 将其传递给 ld )来提供链接描述文件。

默认规格通过 gcc -dumpspecs 获得

此外,通过 strace(1) -ing 一些 gcc 命令,您会发现它尝试访问例如 /usr/lib/gcc/x86_64-linux-gnu/specs ;所以把你自己的规范文件放在那里。

这些规范文件是文本的,因此您应该能够编写自己的文件。

但我不确定这是个好主意。

BTW, /usr/bin/cc is on Linux distribution a symlink (on Debian: /usr/bin/cc -> /etc/alternatives/cc -> /usr/bin/gcc ), either to some gcc or to some clang . AFAIK, cc (和 c99 )在 POSIX 中指定(但当然,没有任何关于它与 ld 的关系的说明)2

原文由 Basile Starynkevitch 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题