使用 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=
设置相同的值。 当运行最终将运行 make
的脚本时,还应将 LLVM=
设置为环境变量。
交叉编译¶
单个 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
一起使用以改进后续构建,(虽然为了避免 100% 缓存未命中,应将 KBUILD_BUILD_TIMESTAMP 设置为构建之间的确定性值,有关更多信息,请参见 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 或通过发行版的软件包管理器获取它。