使用 Clang/LLVM 构建 Linux¶
本文档介绍如何使用 Clang 和 LLVM 工具构建 Linux 内核。
关于¶
Linux 内核传统上一直使用 GNU 工具链(如 GCC 和 binutils)进行编译。目前的工作已经允许使用 Clang 和 LLVM 工具作为可行的替代品。诸如 Android、 ChromeOS、OpenMandriva 和 Chimera 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-14
、ld.lld-14
等。
为了支持树外路径和版本后缀的组合,我们推荐
PATH=/path/to/llvm/:$PATH make LLVM=-14
LLVM=0
与完全省略 LLVM
不同,它的行为将类似于 LLVM=1
。 如果你只想使用某些 LLVM 工具,请使用它们各自的 make 变量。
如果通过不同的命令进行配置和构建,则每次调用 make
时都应设置与 LLVM=
相同的值。LLVM=
还应在运行最终将运行 make
的脚本时设置为环境变量。
交叉编译¶
单个 Clang 编译器二进制文件(以及相应的 LLVM 工具)通常会包含所有支持的后端,这可以帮助简化交叉编译,尤其是在使用 LLVM=1
时。 如果你只使用 LLVM 工具,则 CROSS_COMPILE
或目标三元组前缀将变得不必要。 例子
make LLVM=1 ARCH=arm64
作为混合 LLVM 和 GNU 工具的一个示例,对于像 ARCH=s390
这样尚不支持 ld.lld
或 llvm-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
一起使用,以改进后续的构建,(虽然应该在构建之间将 KBUILD_BUILD_TIMESTAMP 设置为确定性值,以避免 100% 的缓存未命中,有关详细信息,请参阅 Reproducible_builds)
KBUILD_BUILD_TIMESTAMP='' make LLVM=1 CC="ccache clang"
支持的架构¶
LLVM 并非定位 Linux 支持的所有架构,并且仅仅因为 LLVM 支持某个目标,并不意味着内核可以在没有任何问题的情况下构建或工作。 以下是当前使用 CC=clang
或 LLVM=1
工作的架构的一般摘要。 支持级别与 MAINTAINERS 文件中的“S”值相对应。 如果某个架构不存在,则意味着 LLVM 不定位它,或者存在已知问题。 使用 LLVM 的最新稳定版本甚至是开发树通常会产生最佳结果。 通常期望架构的 defconfig
工作良好,某些配置可能存在尚未发现的问题。 欢迎随时在下面的问题跟踪器中提交错误报告!
架构 |
支持级别 |
|
---|---|---|
arm |
支持 |
|
arm64 |
支持 |
|
hexagon |
维护 |
|
loongarch |
维护 |
|
mips |
维护 |
|
powerpc |
维护 |
|
riscv |
支持 |
|
s390 |
维护 |
|
sparc(仅限 sparc64) |
维护 |
|
um(用户模式) |
维护 |
|
x86 |
支持 |
|
获取帮助¶
获取 LLVM¶
我们在 kernel.org 上提供了 LLVM 的预构建稳定版本。 这些已使用用于构建 Linux 内核的配置文件数据进行了优化,这应相对于 LLVM 的其他发行版缩短内核构建时间。
以下链接可能有助于从源代码构建 LLVM 或通过发行版的软件包管理器获取它。