LLVM gold 插件¶
简介¶
使用链接时优化构建需要系统链接器的配合。Linux 系统上的 LTO 支持通过 gold 链接器 提供,它通过插件支持 LTO。这与 GCC LTO 项目使用的机制相同。
LLVM gold 插件在 libLTO 之上实现了 gold 插件接口。相同的插件也可以被其他工具使用,例如 ar
和 nm
。请注意,来自 binutils 版本 2.21.51.0.2 及更高版本的 ld.bfd 也通过插件支持 LTO。但是,LLVM gold 插件与 ld.bfd 的使用未经测试,因此未获得官方支持或推荐。
从 LLVM 15 开始,gold 插件将忽略来自 ELF 目标文件内部 .llvmbc
区段的位代码。但是,仍然支持使用位代码文件的 LTO。
如何构建它¶
你需要拥有带有插件支持的 gold 并构建 LLVMgold 插件。gold 链接器安装为 ld.gold。要查看 gold 是否是系统上的默认链接器,请运行 /usr/bin/ld -v
。如果不是,它将报告 “GNU gold”,否则报告 “GNU ld”。如果 gold 已经安装在 /usr/bin/ld.gold
,一种选择是简单地将其设为默认链接器,方法是备份你现有的 /usr/bin/ld
并使用 ln -s /usr/bin/ld.gold /usr/bin/ld
创建一个符号链接。或者,你可以使用 clang 的 -fuse-ld=gold
构建,或将 -fuse-ld=gold
添加到 LDFLAGS,这将导致 clang 驱动程序直接调用 /usr/bin/ld.gold
。
如果你已安装 gold,请通过运行 /usr/bin/ld.gold -plugin
检查插件支持。如果它提示 “missing argument”(缺少参数),则你具有插件支持。如果不是,并且你收到诸如 “unknown option”(未知选项)之类的错误,那么你需要构建 gold 或安装具有插件支持的版本。
下载、配置和构建带有插件支持的 gold
$ git clone --depth 1 git://sourceware.org/git/binutils-gdb.git binutils $ mkdir build $ cd build $ ../binutils/configure --enable-gold --enable-plugins --disable-werror $ make all-gold
这应该会给你留下
build/gold/ld-new
,它支持-plugin
选项。运行make
还会额外构建支持插件的build/binutils/ar
和nm-new
二进制文件。一旦你准备好切换到使用 gold,备份你现有的
/usr/bin/ld
,然后用ld-new
替换它。或者,安装在/usr/bin/ld.gold
中,并使用-fuse-ld=gold
,如前所述。可选地,将
--enable-gold=default
添加到上面的配置调用中,以使用make install
自动安装新构建的 gold 作为默认链接器。构建 LLVMgold 插件。运行带有
-DLLVM_BINUTILS_INCDIR=/path/to/binutils/include
的 CMake。正确的包含路径将包含文件plugin-api.h
。
用法¶
你应该使用选项 -flto
从 clang
生成位代码文件。此标志还将导致 clang
在其前缀下的 lib
目录中查找 gold 插件,并将 -plugin
选项传递给 ld
。如果没有 -fuse-ld=gold
,它将不会查找备用链接器,这就是为什么你还需要 gold 成为路径中已安装的系统链接器的原因。
ar
和 nm
也接受 -plugin
选项,并且可以将 LLVMgold.so
安装到 /usr/lib/bfd-plugins
以实现无缝设置。如果你构建了自己的 gold,请务必将你构建的 ar
和 nm-new
安装到 /usr/bin
。
链接时优化示例¶
以下示例显示了 gold 插件混合 LLVM 位代码和本机代码的工作示例。
--- a.c ---
#include <stdio.h>
extern void foo1(void);
extern void foo4(void);
void foo2(void) {
printf("Foo2\n");
}
void foo3(void) {
foo4();
}
int main(void) {
foo1();
}
--- b.c ---
#include <stdio.h>
extern void foo2(void);
void foo1(void) {
foo2();
}
void foo4(void) {
printf("Foo4");
}
--- command lines ---
$ clang -flto a.c -c -o a.o # <-- a.o is LLVM bitcode file
$ ar q a.a a.o # <-- a.a is an archive with LLVM bitcode
$ clang b.c -c -o b.o # <-- b.o is native object file
$ clang -flto a.a b.o -o main # <-- link with LLVMgold plugin
Gold 通知插件 foo3 从未在 IR 外部引用,从而导致 LLVM 删除该函数。但是,与 libLTO 示例 不同,gold 目前不会消除 foo4。
快速入门:将 LTO 用于 autotooled 项目¶
一旦你的系统 ld
、ar
和 nm
都支持 LLVM 位代码,一切都已就绪,可以轻松构建 autotooled 项目的 LTO
按照 关于如何构建 LLVMgold.so 的说明进行操作。
将新构建的 binutils 安装到
$PREFIX
将
Release/lib/LLVMgold.so
复制到$PREFIX/lib/bfd-plugins/
设置环境变量(
$PREFIX
是你安装 clang 和 binutils 的位置)export CC="$PREFIX/bin/clang -flto" export CXX="$PREFIX/bin/clang++ -flto" export AR="$PREFIX/bin/ar" export NM="$PREFIX/bin/nm" export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a
或者你可以直接设置你的路径
export PATH="$PREFIX/bin:$PATH" export CC="clang -flto" export CXX="clang++ -flto" export RANLIB=/bin/true
像往常一样配置和构建项目
% ./configure && make && make check
环境变量设置也可能适用于非 autotooled 项目,但你可能还需要设置 LD
环境变量。
许可¶
Gold 在 GPLv3 许可下获得许可。LLVMgold 使用来自 gold 的接口文件 plugin-api.h
,这意味着生成的 LLVMgold.so
二进制文件也受 GPLv3 约束。这仍然可以像 gold 在没有插件的情况下一样,用于链接非 GPLv3 程序。