LLVM gold 外掛程式¶
簡介¶
使用連結時間最佳化 (LTO) 進行建置需要系統連結器的協作。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
新增到上述 configure 調用中,以在使用make install
自動將新建置的 gold 安裝為預設連結器。建置 LLVMgold 外掛程式。使用
-DLLVM_BINUTILS_INCDIR=/path/to/binutils/include
執行 CMake。正確的 include 路徑將包含檔案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 位元碼,一切就緒,可以輕鬆使用 LTO 建置 autotooled 專案
將新建立的 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 授權。這仍然可以用於連結非 GPLv3 程式,就像 gold 在沒有外掛程式的情況下可以做到的那樣。