llvm-project 是 llvm 编译器基础设施的官方统一代码仓库,包含 llvm 核心库、clang 前端、lld 链接器、libc++、compiler-rt、mlir 等全部子项目,构成一套可拆卸、可定制的完整编译工具链生态。

必须装 GCC、CMake、Ninja 和 zlib,运行库取决于目标系统——裸机用 newlib,Linux 用 glibc 或 musl。
基础构建工具链缺一不可
LLVM 本身是用 C++ 写的,编译它需要另一套能跑在宿主机(x86_64)上的编译器:gcc(≥5.1.0)或 clang;cmake(≥3.13.4,推荐 3.23+)负责生成构建配置;ninja(比 make 快且更可靠)执行实际编译;zlib用于压缩/解压 bitcode 和测试数据。
常见错误现象:cmake: command not found 或 ninja: no work to do(其实是没生成 build.ninja)。
- Ubuntu 上一键装全:
sudo apt install build-essential cmake ninja-build zlib1g-dev - 不要用系统自带太老的 cmake(如 Ubuntu 20.04 自带 3.16),建议从 Kitware 官网下二进制包手动安装
- 不推荐用
make驱动 LLVM 构建,容易卡在链接阶段,尤其并行数高时
RISC-V 运行库选哪个,取决于你跑在哪
Clang 编译出 RISC-V 目标代码后,printf、malloc 这些函数靠谁实现?不是 LLVM 提供的,而是你指定的运行库。关键区别在于:
- 裸机(bare-metal)或 RTOS 环境:用
newlib—— 轻量、无系统调用依赖,头文件和库都静态链接 - Linux 用户态程序:必须用
glibc或musl—— 它们提供完整的 POSIX 接口,但需要对应架构的 sysroot(即riscv64-unknown-linux-gnu/sysroot) - Clang 本身不自带这些库,得自己编译或下载预构建的
riscv-gnu-toolchain
典型错误:undefined reference to `__libc_start_main' —— 就是 clang 找不到 glibc 的入口符号,说明没配对的 sysroot 或没传 --sysroot。
Clang 命令里必须显式指定 triple 和 sysroot
光有工具和库还不够,Clang 不会自动猜你要生成哪种 RISC-V 程序。必须用 -target 和 --sysroot 锁死行为:
-
-target riscv64-unknown-elf→ 裸机,链接newlib,入口是_start -
-target riscv64-unknown-linux-gnu→ Linux,需配套sysroot,入口是__libc_start_main - 漏掉
--sysroot导致链接时找不到crt1.o、libc.a,报错像:cannot find crti.o: No such file or directory - ABI 不匹配也会失败,比如用
lp64dtriple 却链接了lp64版本的库
示例命令:clang --target=riscv64-unknown-linux-gnu --sysroot=$RISCV/sysroot -o hello hello.c
容易被忽略的点:链接器脚本和 multilib 支持
即使工具、库、triple 全对,仍可能链接失败——根源常在链接器层面:
- RISC-V 工具链默认启用 multilib(比如同时支持
rv64imac-lp64和rv64imafdc-lp64d),但 LLVM 的lld对 multilib 支持不如riscv64-unknown-elf-gcc的ld成熟 - 裸机开发时,你得自己提供链接脚本(
.ld文件)定义内存布局;Clang 不会自动生成,-T参数必须显式传入 - 如果用
lld链接 Linux 程序,确保已启用-DLLVM_USE_LINKER=lld且lld本身编译时支持 ELF RISC-V 后端(默认开启,但交叉编译时易漏)
最常卡住的地方不是编译,是链接:ld: error: unable to find library -lc 或 relocation truncated to fit —— 这些都不是 Clang 报的错,得顺着 ld 的输出往 sysroot 和链接脚本里查。











