如何强制Clang使用GCC C++运行时库?
在Windows的MSYS2环境中,尝试将Clang用作交叉编译器(Clang原生支持交叉编译能力),编译面向Linux AArch64开发板的代码时,链接阶段出现如下报错:
ld.lld: error: cannot open C:/msys64/clang64/lib/clang/17/lib/linux/libclang_rt.builtins-aarch64.a: No such file or directory
[cmake] ld.lld: error: unable to find library -lunwind
MSYS2自带的Clang包未提供上述缺失文件,已知可替换为GCC C运行时库,且已从目标开发板下载sysroot到本地开发机。请问如何修改Clang构建时使用的C运行时库?
要让Clang改用GCC的C++运行时库,核心是通过编译/链接参数指定sysroot路径、GCC交叉工具链的目标前缀,引导Clang使用GCC的标准库和链接脚本,以下是具体操作步骤:
1. 确认GCC交叉工具链的目标前缀
针对AArch64 Linux的GCC工具链前缀通常为aarch64-linux-gnu-,如果你的工具链前缀不同(比如aarch64-none-linux-gnu-),请自行替换对应参数。
2. 给Clang添加关键编译参数
无论直接调用Clang还是通过构建工具,都需要添加以下核心参数:
-target aarch64-linux-gnu:明确目标架构与系统类型--sysroot=/path/to/your/sysroot:指定从开发板下载的本地sysroot路径(替换为实际路径)-gcc-toolchain=/path/to/aarch64-gcc-toolchain:若GCC交叉工具链不在默认搜索路径,需指定其安装根目录-stdlib=libstdc++:强制Clang使用GCC的libstdc作为C标准库,替代默认的libc++
3. CMake构建场景的配置调整
如果使用CMake构建项目,可通过两种方式配置:
命令行参数传递
cmake .. \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ -DCMAKE_C_COMPILER_TARGET=aarch64-linux-gnu \ -DCMAKE_CXX_COMPILER_TARGET=aarch64-linux-gnu \ -DCMAKE_SYSROOT=/path/to/your/sysroot \ -DCMAKE_CXX_FLAGS="-stdlib=libstdc++" \ -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld --sysroot=/path/to/your/sysroot -L/path/to/sysroot/usr/lib/aarch64-linux-gnu"
直接修改CMakeLists.txt
set(CMAKE_C_COMPILER clang) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_C_COMPILER_TARGET aarch64-linux-gnu) set(CMAKE_CXX_COMPILER_TARGET aarch64-linux-gnu) set(CMAKE_SYSROOT "/path/to/your/sysroot") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld --sysroot=${CMAKE_SYSROOT} -L${CMAKE_SYSROOT}/usr/lib/aarch64-linux-gnu")
4. 解决-lunwind缺失问题
针对报错中的unwind库缺失,可按以下方式处理:
- 检查本地sysroot的
/usr/lib/aarch64-linux-gnu目录下是否存在libunwind.so或libunwind.a,若存在,通过-L参数指定该目录即可(已包含在上述链接参数中) - 若sysroot中无unwind库,可从目标板的包管理工具安装
libunwind-dev(Debian/Ubuntu系)后同步到本地sysroot;或在链接时添加-Wl,--no-as-needed -lunwind强制链接;若代码不需要异常处理,可添加-fno-exceptions编译选项取消对unwind库的依赖
5. 验证配置有效性
编译时添加-v参数,查看Clang的搜索路径和链接命令,确认是否正确使用了指定的sysroot和libstdc++:
clang++ -v -target aarch64-linux-gnu --sysroot=/path/to/sysroot -stdlib=libstdc++ your_code.cpp
内容的提问来源于stack exchange,提问作者Alexandr Zarubkin

