构建——如何交叉构建host是其他架构的LLVM
推荐步骤
我使用的 AMD,想要构建一个 RISC-V 上可以直接使用的 LLVM工具链,这 AMD 比较新,所以我们先安装依赖!
陷阱一,在使用riscv-gnu-toolchain 的子 module glibc 时候尽量使用目标机器版本的 GLIBC!
sudo apt install -y bison texinfo libmpc-dev libgmp-dev libmpfr-dev ninja-build
然后安装 riscv-gnu-toolchain:git clone https://github.com/riscv-collab/riscv-gnu-toolchain.git mkdir build-64 && cd build-64 ../configure --prefix=/home/bosc/yangz/riscv64-install --with-arch=rv64gc --with-abi=lp64d --disable-gdb make linux -j$(nproc) | tee log
构建 riscv-gnu 环境时报错想想是不是依赖没有安装到位![milkv@fedora-riscv llvm-riscv]$ ./bin/clang -v ./bin/clang: /lib64/lp64d/libc.so.6: version `GLIBC_2.38' not found (required by ./bin/clang)
然后开始构建 LLVM:cd llvm-project mkdir build && cd build cmake ../llvm -G "Ninja" \ -DCMAKE_SYSTEM_NAME=Linux \ -DCMAKE_C_COMPILER=/home/bosc/yangz/riscv64-install/bin/riscv64-unknown-linux-gnu-gcc \ -DCMAKE_CXX_COMPILER=/home/bosc/yangz/riscv64-install/bin/riscv64-unknown-linux-gnu-g++ \ -DCMAKE_SYSROOT=/home/bosc/yangz/riscv64-install/sysroot \ -DCMAKE_INSTALL_PREFIX=/home/bosc/yangz/llvm-host-riscv \ -DLLVM_TARGETS_TO_BUILD=RISCV \ -DLLVM_DEFAULT_TARGET_TRIPLE=riscv64-unknown-linux-gnu \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PROJECTS="clang;lld;bolt"
这时有一个支线任务:需要将 AMD 机器的公钥配置到 RISC-V 机器的~/.ssh/authorized_keys
里cat ~/.ssh/id_rsa.pub # 然后放到RISC-V对应位置:即`~/.ssh/authorized_keys`里面
这个时候就可以免密登录了!ssh milkv@172.38.9.242
可以直接登录!
接下来(每次对 llvm 有改动时)使用如下脚本==一键部署==!#!/bin/bash set -e IP=172.38.9.242 TARGET=/home/milkv/yangz/llvm-riscv LOCAL=/home/bosc/yangz/llvm-host-riscv # Release 版 cd /home/bosc/yangz/bisheng/bisheng-bolt-riscv32/build && ninja -j32 && ninja install cd $LOCAL # 打包 tar -czf /home/bosc/yangz/llvm.tar.gz . # 传输并解压 + 设置 PATH scp llvm.tar.gz milkv@$IP:/home/milkv/yangz ssh milkv@$IP "mkdir -p $TARGET && tar -xzf /home/milkv/yangz/llvm.tar.gz -C $TARGET && echo '✅ LLVM 已部署到 $TARGET'"
此时可能还有一个隐藏 bug,报错为:[milkv@fedora-riscv yangz]$ ./llvm-riscv/bin/clang --version ./llvm-riscv/bin/clang: /lib64/lp64d/libc.so.6: version `GLIBC_2.38' not found (required by ./llvm-riscv/bin/clang)
这个问题可能是双方的 GLIBC 版本不一致引起,也可能是操作系统不一致引起。你可以使用ldd --version
查看各自版本。
解决办法是:在 RISCV 上,先去https://mirrors.aliyun.com/gnu/glibc/下载缺失的GLIBC压缩包,上传到 RISC-V 服务器。
然后cd glibc-2.38 mkdir build && cd build ../configure --prefix=/home/milkv/yangz/glibc-2.38-install --enable-add-ons --disable-werror --with-headers=/usr/include --host=riscv64-unknown-linux-gnu make -j$(nproc) && make install
然后大功告成!LD_LIBRARY_PATH=/home/milkv/yangz/glibc-2.38-install/lib ./llvm-riscv/bin/clang --versio
这样打印出类似如下内容就成功了![milkv@fedora-riscv yangz]$ LD_LIBRARY_PATH=/home/milkv/yangz/glibc-2.38-install/lib ./llvm-riscv/bin/clang --version clang version 17.0.6 (git@gitlab.com:759569457/bisheng-bolt-riscv32.git 6e3db8d3cd4f680315d38656a1d5acdd0e4c0bd0) Target: riscv64-unknown-linux-gnu Thread model: posix InstalledDir: /home/milkv/yangz/./llvm-riscv/bin
如果缺 32 位库文件的话,传进去一份,然后:[milkv@fedora-riscv yangz]$ mkdir -p llvm-riscv/lib/clang-runtimes/riscv32/lib [milkv@fedora-riscv yangz]$ mkdir -p llvm-riscv/lib/clang-runtimes/riscv32/include [milkv@fedora-riscv yangz]$ cp -r riscv32/lib/* llvm-riscv/lib/clang-runtimes/riscv32/lib [milkv@fedora-riscv yangz]$ cp -r riscv32/include/* llvm-riscv/lib/clang-runtimes/riscv32/include
使用LD_LIBRARY_PATH=/home/milkv/yangz/glibc-2.38-install/lib ../llvm-riscv/bin/clang -Os --target=riscv32 -static 1.c -g -Wl,--emit-relocs ../riscv32/lib/crt0.o -mabi=ilp32d
即可不推荐步骤
GPT 推荐给我一种策略解决 GLIBC 缺失,我觉得很愚蠢:首先在 RISC-V 上执行这个脚本以便提取出 GLIBC 等环境:(-a 是避免符号链接,防止递归收入其他符号炸目录!)
#!/bin/bash set -e OUTDIR=/home/milkv/yangz/sysroot-fedora-clean OUTTAR=/home/milkv/yangz/sysroot-fedora.tar.gz echo "🧹 清理旧版本(如有)..." sudo rm -rf "$OUTDIR" echo "🛠️ 构建干净 sysroot 到: $OUTDIR" # 1. 创建目录结构 mkdir -p "$OUTDIR/usr" mkdir -p "$OUTDIR/usr/lib64" mkdir -p "$OUTDIR/lib64" mkdir -p "$OUTDIR/lib" # 2. 拷贝 glibc 动态库 echo "📦 拷贝 lib64" sudo rsync -aH --no-links --progress /lib64/ "$OUTDIR/lib64/" sudo rsync -aH --no-links --progress /usr/lib64/ "$OUTDIR/usr/lib64/" # 3. 拷贝头文件 echo "📦 拷贝 /usr/include" sudo rsync -a --progress /usr/include "$OUTDIR/usr/" # 4. 拷贝启动文件 crt*.o echo "📌 拷贝 crt*.o" CRT_FILES=(crt1.o crti.o crtn.o) for f in "${CRT_FILES[@]}"; do if [ -f "/usr/lib64/$f" ]; then sudo cp "/usr/lib64/$f" "$OUTDIR/usr/lib64/" echo "✅ 拷贝 $f" else echo "❌ 缺失 /usr/lib64/$f" fi done # 5. 拷贝 LP64D ABI 路径 echo "📦 拷贝 lp64d ABI 库" if [ -d /lib64/lp64d ]; then sudo rsync -a /lib64/lp64d "$OUTDIR/lib64/" echo "✅ /lib64/lp64d 拷贝完成" else echo "⚠️ /lib64/lp64d 不存在,可能不需要" fi if [ -d /usr/lib64/lp64d ]; then sudo rsync -a /usr/lib64/lp64d "$OUTDIR/usr/lib64/" echo "✅ /usr/lib64/lp64d 拷贝完成" else echo "⚠️ /usr/lib64/lp64d 不存在,可能不需要" fi # 6. 拷贝动态链接器 # 6. 拷贝动态链接器(直接拷贝到 lib/ 而非 usr/lib) echo "📦 拷贝 ld-linux-riscv64-lp64d.so.1" if [ -f /usr/lib/ld-linux-riscv64-lp64d.so.1 ]; then sudo cp /usr/lib/ld-linux-riscv64-lp64d.so.1 "$OUTDIR/lib/" echo "✅ 已复制到 lib/" else echo "❌ 未找到 /usr/lib/ld-linux-riscv64-lp64d.so.1" fi # 7. 创建 /usr/lib → lib64 软链接(必须在最后创建) echo "🔗 创建 usr/lib → lib64" rm -rf "$OUTDIR/usr/lib" ln -sf lib64 "$OUTDIR/usr/lib" # 8. 权限修复 echo "🔧 修复权限" sudo chown -R $(whoami):$(whoami) "$OUTDIR" # 9. 检查关键文件是否存在 echo "🔍 最后检查:" check_file() { if [ ! -e "$1" ]; then echo "❌ 缺失: $1" else echo "✅ 存在: $1" fi } check_file "$OUTDIR/lib64/lp64d/libc.so.6" check_file "$OUTDIR/usr/lib64/lp64d/libc_nonshared.a" check_file "$OUTDIR/lib/ld-linux-riscv64-lp64d.so.1" check_file "$OUTDIR/usr/lib64/crt1.o" # 10. 打包 echo "📦 打包为: $OUTTAR" tar -czf "$OUTTAR" -C "$(dirname "$OUTDIR")" "$(basename "$OUTDIR")" echo "✅ 完成!sysroot 打包于: $OUTTAR"
此时去到 AMD 机器将刚才的 GLIBC 等环境拷贝过来。
scp milkv@172.38.9.242:/home/milkv/yangz/sysroot-fedora.tar.gz ~/yangz/
cd ~/yangz
tar -xzf sysroot-fedora.tar.gz
cd /home/bosc/yangz/sysroot-fedora-clean/usr
ln -s lib64 lib
然后编译…
如果是 DEBUG 版
在 AMD 上:
cmake ../llvm -G "Ninja" \
-DCMAKE_SYSTEM_NAME=Linux \
-DCMAKE_C_COMPILER=/home/bosc/yangz/riscv64-install/bin/riscv64-unknown-linux-gnu-gcc \
-DCMAKE_CXX_COMPILER=/home/bosc/yangz/riscv64-install/bin/riscv64-unknown-linux-gnu-g++ \
-DCMAKE_SYSROOT=/home/bosc/yangz/riscv64-install/sysroot \
-DCMAKE_INSTALL_PREFIX=/home/bosc/yangz/llvm-host-riscv-debug \
-DLLVM_TARGETS_TO_BUILD=RISCV \
-DLLVM_DEFAULT_TARGET_TRIPLE=riscv64-unknown-linux-gnu \
-DCMAKE_BUILD_TYPE=Debug \
-DLLVM_ENABLE_PROJECTS="bolt"
ninja -j$(nproc) && ninja install
第一次建议传输所有:
cd ~/yangz/llvm-host-riscv-debug
tar -czf llvm-debug-toolchain.tar.gz .
scp llvm-debug-toolchain.tar.gz milkv@172.38.9.242:/home/milkv/yangz
然后去 RISC-V 机器:
cd /home/milkv/yangz
mkdir -p llvm-riscv-debug && cd llvm-riscv-debug
tar -xzf ../llvm-debug-toolchain.tar.gz -C .
mkdir -p /home/milkv/yangz/llvm-riscv-debug/lib/clang-runtimes/riscv32/lib
mkdir -p /home/milkv/yangz/llvm-riscv-debug/lib/clang-runtimes/riscv32/include
cp -r /home/milkv/yangz/riscv32/lib/* /home/milkv/yangz/llvm-riscv-debug/lib/clang-runtimes/riscv32/lib
cp -r /home/milkv/yangz/riscv32/include/* /home/milkv/yangz/llvm-riscv-debug/lib/clang-runtimes/riscv32/include
后续比如我指改造部分文件的话,重新编译后只需打包传输某一个工具链就行,以 BOLT 为例:脚本 deploy. sh
#!/bin/bash
set -e
# 1. 在构建机器上,进入到 llvm-debug 目录并执行构建
echo "🚀 开始构建 Debug 版工具链..."
# 进入到构建目录,执行构建
cd ~/yangz/bisheng/bisheng-bolt-riscv32/build
ninja -j12 install
echo "✅ Debug 版工具链构建完成!"
# 2. 在 RISC-V 机器上更新工具链
echo "🚚 正在更新 RISC-V 机器上的工具链..."
# 使用 rsync 增量同步文件到目标目录
rsync -avz --progress ./lib/ milkv@172.38.9.242:/home/milkv/yangz/llvm-riscv-debug/lib/
rsync -avz --progress ./bin/llvm-bolt milkv@172.38.9.242:/home/milkv/yangz/llvm-riscv-debug/bin/
echo "✅ 成功更新到 RISC-V 机器!"
echo "🌟 完成:llvm-bolt 工具链已成功更新!"
评论