英語

使用 Clang/LLVM 構建 Linux

本文件介紹如何使用 Clang 和 LLVM 工具構建 Linux 核心。

關於

傳統上,Linux 核心一直使用 GNU 工具鏈(例如 GCC 和 binutils)進行編譯。目前的工作已經允許使用 ClangLLVM 工具作為可行的替代方案。諸如 AndroidChromeOSOpenMandrivaChimera Linux 等發行版都使用 Clang 構建的核心。谷歌和 Meta 的資料中心叢集也執行使用 Clang 構建的核心。

LLVM 是一個工具鏈元件的集合,以 C++ 物件的形式實現。Clang 是 LLVM 的前端,支援 C 和核心所需的 GNU C 擴充套件,發音為“klang”,而不是“see-lang”。

使用 LLVM 構建

透過以下方式呼叫 make

make LLVM=1

以針對主機目標進行編譯。對於交叉編譯:

make LLVM=1 ARCH=arm64

LLVM= 引數

LLVM 具有 GNU binutils 工具的替代品。 它們可以單獨啟用。 支援的 make 變數的完整列表

make CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm STRIP=llvm-strip \
  OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump READELF=llvm-readelf \
  HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar HOSTLD=ld.lld

LLVM=1 擴充套件到以上內容。

如果您的 LLVM 工具在 PATH 中不可用,您可以使用帶有尾部斜槓的 LLVM 變數提供它們的位置

make LLVM=/path/to/llvm/

這將使用 /path/to/llvm/clang/path/to/llvm/ld.lld 等。 也可以使用以下方法

PATH=/path/to/llvm:$PATH make LLVM=1

如果您的 LLVM 工具具有版本字尾,並且您希望使用該顯式版本而不是像 LLVM=1 這樣不帶字尾的可執行檔案進行測試,則可以使用 LLVM 變數傳遞字尾

make LLVM=-14

這將使用 clang-14ld.lld-14 等。

為了支援樹外路徑與版本字尾的組合,我們建議

PATH=/path/to/llvm/:$PATH make LLVM=-14

LLVM=0 與完全省略 LLVM 不同,它的行為類似於 LLVM=1。 如果您只想使用某些 LLVM 工具,請使用它們各自的 make 變數。

如果透過不同的命令配置和構建,則每次呼叫 make 時,都應為 LLVM= 設定相同的值。 當執行最終將執行 make 的指令碼時,還應將 LLVM= 設定為環境變數。

交叉編譯

單個 Clang 編譯器二進位制檔案(和相應的 LLVM 工具)通常包含所有支援的後端,這可以幫助簡化交叉編譯,尤其是在使用 LLVM=1 時。 如果您僅使用 LLVM 工具,則 CROSS_COMPILE 或目標三元組字首變得不必要。 例子

make LLVM=1 ARCH=arm64

作為混合 LLVM 和 GNU 工具的示例,對於像 ARCH=s390 這樣的目標,它尚不具有 ld.lldllvm-objcopy 支援,您可以呼叫 make 透過

make LLVM=1 ARCH=s390 LD=s390x-linux-gnu-ld.bfd \
  OBJCOPY=s390x-linux-gnu-objcopy

此示例將呼叫 s390x-linux-gnu-ld.bfd 作為連結器和 s390x-linux-gnu-objcopy,因此請確保這些工具在您的 $PATH 中可訪問。

當未設定 LLVM=1 時,CROSS_COMPILE 不用於為 Clang 編譯器二進位制檔案(或相應的 LLVM 工具)新增字首,就像 GNU 工具的情況一樣。

LLVM_IAS= 引數

Clang 可以彙編彙編器程式碼。 您可以傳遞 LLVM_IAS=0 來停用此行為,並讓 Clang 呼叫相應的非整合彙編器。 例子

make LLVM=1 LLVM_IAS=0

當交叉編譯並且使用 LLVM_IAS=0 時,必須使用 CROSS_COMPILE,以便為編譯器設定 --prefix= 以找到相應的非整合彙編器(通常,您不想在針對另一個架構時使用系統彙編器)。 例子

make LLVM=1 ARCH=arm LLVM_IAS=0 CROSS_COMPILE=arm-linux-gnueabi-

Ccache

ccache 可以與 clang 一起使用以改進後續構建,(雖然為了避免 100% 快取未命中,應將 KBUILD_BUILD_TIMESTAMP 設定為構建之間的確定性值,有關更多資訊,請參見 Reproducible_builds

KBUILD_BUILD_TIMESTAMP='' make LLVM=1 CC="ccache clang"

支援的架構

LLVM 並非針對 Linux 支援的所有架構,並且僅僅因為 LLVM 中支援某個目標並不意味著核心可以構建或工作而沒有任何問題。 以下是當前與 CC=clangLLVM=1 一起使用的架構的一般摘要。 支援級別對應於 MAINTAINERS 檔案中的“S”值。 如果某個架構不存在,則表示 LLVM 不針對它,或者存在已知問題。 使用最新穩定版本的 LLVM 甚至開發樹通常會產生最佳結果。 通常,預計架構的 defconfig 能夠很好地工作,某些配置可能存在尚未發現的問題。 歡迎在下面的問題跟蹤器中提出錯誤報告!

架構

支援級別

make 命令

arm

支援

LLVM=1

arm64

支援

LLVM=1

hexagon

維護

LLVM=1

loongarch

維護

LLVM=1

mips

維護

LLVM=1

powerpc

維護

LLVM=1

riscv

支援

LLVM=1

s390

維護

LLVM=1 (LLVM >= 18.1.0), CC=clang (LLVM < 18.1.0)

sparc (僅限 sparc64)

維護

CC=clang LLVM_IAS=0 (LLVM >= 20)

um (使用者模式)

維護

LLVM=1

x86

支援

LLVM=1

獲取幫助

獲取 LLVM

我們在 kernel.org 上提供了 LLVM 的預構建穩定版本。 這些版本已經使用配置檔案資料進行了最佳化,用於構建 Linux 核心,這應該比其他 LLVM 發行版縮短核心構建時間。

以下連結可能有助於從原始碼構建 LLVM 或透過發行版的軟體包管理器獲取它。