首页 > 解决方案 > 如何在 x64 主机上为 AArch64 交叉编译 LLVM/Clang?

问题描述

我想在我的 AArch64 Raspberry Pi 4 上使用 clang-11,运行 Ubuntu 20.04 Focal。我查看了https://apt.llvm.org/,但 AArch64 预构建的二进制文件似乎不可用?

我尝试直接在 Raspberry Pi 上构建 clang,但速度非常慢,最终我的 SD 卡空间不足。

如何在我的 x64 笔记本电脑上交叉编译 clang?

标签: cross-compilingllvm-clangarm64raspberry-pi4

解决方案


构建 LLVM 可能会很棘手,因为它需要大量的计算资源,这使得使用不同的构建选项进行迭代变得困难。我第一次尝试为我的 AArch64 Raspberry PI 构建主干版本的 clang 最终是为 ARM7 构建的,而且大小也为 30GB,这不适合存储卡。哎呀。

项目 wiki 上的研究文档

第一个相关的 Clang 文档页面是Building LLVM with CMake。它解释了 CMake 选项CMAKE_BUILD_TYPECMAKE_INSTALL_PREFIXLLVM_TARGETS_TO_BUILD

最好设置-DCMAKE_BUILD_TYPE=MinSizeRel或设置默认值以外的其他值Debug。clang 的调试版本运行速度会明显变慢。自定义CMAKE_INSTALL_PREFIX是必要的,因为您不想将 Clang 安装到您的主机系统上。给它-DCMAKE_INSTALL_PREFIX=$PWD/install,然后将安装目录复制到您的 AArch64 机器上。

要减小安装大小,请设置-DLLVM_TARGETS_TO_BUILD=AArch64. 默认是构建所有目标。

启用断言

如果您想使用最先进的功能,这很可能,否则为什么要编译 clang,您需要启用 clang 代码中的断言,并且您需要调试符号。它会减慢程序速度并使其变得更大,但由于提高了安全性和可调试性,这绝对值得。查看获取源代码和构建 LLVM-DCMAKE_BUILD_TYPE=RelWithDebInfo -DLLVM_ENABLE_ASSERTIONS=On在这种情况下进行设置。

接下来,阅读构建 LLVM 的发行版。相关建议是通过设置进一步最小化安装尺寸-DLLVM_BUILD_LLVM_DYLIB=On -DLLVM_LINK_LLVM_DYLIB=On -DLLVM_INSTALL_TOOLCHAIN_ONLY=On

最后,阅读如何使用 Clang/LLVM 交叉编译 Clang/LLVM。即使您打算使用 GCC 进行交叉编译,此页面也很有帮助。如果您使用的是 Ubuntu Focal,无论是直接使用还是在 Docker 容器中构建,您最终可能会得到这个 CMake 命令的框架,例如

CC=aarch64-linux-gnu-gcc-10 CXX=aarch64-linux-gnu-g++-10 cmake ../llvm \
  -DCMAKE_CROSSCOMPILING=True \
  -DLLVM_TARGET_ARCH=AArch64 \
  -DLLVM_DEFAULT_TARGET_TRIPLE=aarch64-linux-gnueabihf \
  -DCMAKE_CXX_FLAGS='-march=armv8-a -mtune=cortex-a72' \
  -GNinja

那里的选项应该是直截了当的,除了 forLLVM_TABLEGENCLANG_TABLEGEN。必须指定它们,因为这些二进制文件需要在主机上运行,​​但是构建会为目标编译它们,因此它不能使用它刚刚构建的内容。现有的二进制文件必须由您提供。虽然 llvm-tblgen 可以与 llvm 软件包一起安装,但 clang-tblgen 不是发行版的一部分。这意味着,您需要进行两次构建。首先,为host构建这两个二进制文件(你不必构建完整的LLVM,这两个二进制文件就足够了),然后将交叉编译指向它们。

mkdir build-host
cd build-host
CC=gcc-10 CXX=g++-10 cmake ../llvm -DLLVM_ENABLE_PROJECTS='clang;compiler-rt;lld;clang-tools-extra' -GNinja
ninja llvm-tblgen clang-tblgen

现在,在你的交叉构建中使用这些二进制文件,所以添加到你的 CMake 命令

-DLLVM_TABLEGEN=/usr/bin/llvm-tblgen-11 -DCLANG_TABLEGEN=/mnt/repos/llvm-project/build-host/bin/clang-tblgen

启动泊坞窗

建议将带有 llvm 源的目录从文件系统挂载到容器中。这将使编译结果更容易输出,并且本机文件系统比 docker 中的覆盖更快。

docker run -v `pwd`:/mnt --rm -it ubuntu:focal bash

安装依赖项

在 Ubuntu 20.04 焦点上

apt install g++-10-aarch64-linux-gnu libstdc++-10-dev-arm64-cross gcc-10 g++-10
apt install cmake ninja-build python3

配置

mkdir build-aarch64
cd build-aarch64

CC=aarch64-linux-gnu-gcc-10 CXX=aarch64-linux-gnu-g++-10 cmake ../llvm \
    -DCMAKE_BUILD_TYPE=RelWithDebInfo \
    -DLLVM_ENABLE_ASSERTIONS=On \
    -DCMAKE_CROSSCOMPILING=True \
    -DCMAKE_INSTALL_PREFIX=install \
    -DLLVM_DEFAULT_TARGET_TRIPLE=aarch64-linux-gnueabihf \
    -DLLVM_TARGET_ARCH=AArch64 \
    -DLLVM_TARGETS_TO_BUILD=AArch64 \
    -DCMAKE_CXX_FLAGS='-march=armv8-a -mtune=cortex-a72' \
    -GNinja \
    -DLLVM_ENABLE_PROJECTS='clang;compiler-rt;lld;clang-tools-extra' \
    -DLLVM_TABLEGEN=/mnt/repos/llvm-project/build-host/bin/llvm-tblgen \
    -DCLANG_TABLEGEN=/mnt/repos/llvm-project/build-host/bin/clang-tblgen \
    -DLLVM_BUILD_LLVM_DYLIB=On \
    -DLLVM_LINK_LLVM_DYLIB=On \
    -DLLVM_INSTALL_TOOLCHAIN_ONLY=On

编译

如果可以,请获得功能强大的构建机器。链接一些二进制文件需要大量 RAM。您应该有大约 20 GB 的可用内存,以便能够在合理的时间内到达任何地方,64 GB 会更好。如果发生多个并行运行的链接任务耗尽您的机器内存,请尝试使用 orso 进行编译ninja -j3,以将并行任务的数量限制为例如 3。

ninja install -j3

使用不同的链接器应该可以减少内存需求。据说,ld.gold 在链接时对内存的要求较低。


推荐阅读