使用CMake交叉编译grpc至aarch64时出现链接错误的求助
问题描述
当前使用gRPC v1.67.0,主机系统为Ubuntu 22.04,主机端protoc与grpc_cpp_plugin编译正常。采用aarch64-none-linux-gnu交叉编译工具链(gcc版本12.3.1 20230626),toolchain.cmake配置如下:
SET(CMAKE_SYSTEM_NAME Linux) SET(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_STAGING_PREFIX /tmp/stage) set(CMAKE_C_COMPILER /home/lenli/he01/arm-gnu-toolchain-12.3.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc) set(CMAKE_CXX_COMPILER /home/lenli/he01/arm-gnu-toolchain-12.3.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-g++) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
执行的CMake配置命令:
cmake -DCMAKE_TOOLCHAIN_FILE=/tmp/toolchain.cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/tmp/install \ ../..
CMake配置执行成功,但执行make -j4 install时,编译进度到约30%时出现大量类似如下的未定义引用错误:
re2_arg_test.cc:(.text+0x30): undefined reference to `std::ios_base::ios_base()' regexp_test.cc:(.text+0x8c): undefined reference to `operator delete(void*, unsigned long)' undefined reference to `vtable for std::__cxx11::basic_ostringstream<char, std::char_traits<char>, std::allocator<char> >'
原因分析
这类未定义引用错误属于C标准库符号缺失,核心原因是交叉编译环境下CMake未正确关联aarch64目标架构的C标准库,或编译过程中混用了主机系统的标准库文件,具体包括:
- 工具链配置未明确指定C++标准库搜索路径,CMake误使用主机Ubuntu 22.04的x86_64架构标准库
- gRPC默认启用的RE2等依赖库,交叉编译时未用对应工具链编译,导致链接阶段调用主机版本符号
- 交叉工具链的C++标准库路径未被CMake识别,链接时无法找到对应架构的标准库符号
解决步骤
1. 完善toolchain.cmake配置
在原配置中添加以下内容,强制CMake使用交叉工具链自带的C++标准库:
# 指定C++标准版本(匹配gRPC要求,至少C++17) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 显式指定交叉工具链的sysroot路径 set(CMAKE_SYSROOT /home/lenli/he01/arm-gnu-toolchain-12.3.rel1-x86_64-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc) set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) # 配置链接参数,指定标准库搜索路径 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/lib -L${CMAKE_SYSROOT}/usr/lib") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L${CMAKE_SYSROOT}/lib -L${CMAKE_SYSROOT}/usr/lib")
2. 禁用测试用例编译(推荐)
交叉编译无需构建gRPC及依赖的测试代码,可在CMake配置时添加参数跳过:
cmake -DCMAKE_TOOLCHAIN_FILE=/tmp/toolchain.cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/tmp/install \ -DgRPC_BUILD_TESTS=OFF \ -DRE2_BUILD_TESTING=OFF \ ../..
3. 清理缓存后重新编译
# 进入编译目录 cd <你的build目录路径> # 清理原有CMake缓存 rm -rf CMakeCache.txt CMakeFiles/ # 重新执行配置 cmake -DCMAKE_TOOLCHAIN_FILE=/tmp/toolchain.cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/tmp/install \ -DgRPC_BUILD_TESTS=OFF \ -DRE2_BUILD_TESTING=OFF \ ../.. # 重新编译安装 make -j4 install
4. 验证链接参数(排查用)
若仍有错误,检查编译时的链接命令,确认使用的是交叉工具链的aarch64-none-linux-gnu-g++,且链接路径指向交叉工具链的标准库目录。
内容的提问来源于stack exchange,提问作者lenli
相关产品推荐
相关产品推荐

