CMake从Mac交叉编译ARM Linux时add_executable正常但add_library失效
问题原因
你遇到的问题核心是交叉编译配置的执行顺序错误,其次缺少库编译相关的显式配置:
- CMake 进行交叉编译时,
CMAKE_SYSTEM_NAME、CMAKE_SYSTEM_PROCESSOR、CMAKE_CXX_COMPILER、CMAKE_SYSROOT这类全局交叉编译配置,必须放在project()指令之前执行。project()指令执行时会自动完成编译器检测、平台参数初始化、宿主机特性识别等流程,你把这些配置放在project()之后,project()执行阶段还是用的Mac宿主机的默认配置,生成了针对宿主机的库编译默认参数。 add_executable能正常工作是因为你手动在CMAKE_CXX_FLAGS里添加的交叉编译参数覆盖了可执行文件编译的默认参数,而add_library编译时会额外调用project()阶段初始化的库专属编译参数(比如位置无关代码标记、平台特定库编译标记),这些参数是当初针对宿主机生成的,因此会带出错误的宿主机编译参数。- 你在
CMAKE_CXX_FLAGS里用了反引号调用brew --prefix,属于shell执行语法,CMake配置阶段不会解析,部分场景下也会导致参数识别混乱。
修复步骤
- 调整配置顺序,所有交叉编译全局配置移到
project()之前,同时增加C编译器配置避免检测异常:
cmake_minimum_required(VERSION 3.19) # 交叉编译配置必须放在project指令之前 set(CMAKE_SYSTEM_NAME Linux CACHE INTERNAL "") set(CMAKE_SYSTEM_PROCESSOR arm CACHE INTERNAL "") set(SYS_ROOT $ENV{HOME}/Projects/rpi-zero/sysroot) set(CMAKE_SYSROOT ${SYS_ROOT} CACHE INTERNAL "") set(CMAKE_OSX_SYSROOT "" CACHE INTERNAL "") # 配置编译器 set(CMAKE_C_COMPILER "clang" CACHE INTERNAL "") set(CMAKE_CXX_COMPILER "clang++" CACHE INTERNAL "") # 提前解析brew安装路径,避免shell语法问题 execute_process(COMMAND brew --prefix arm-linux-gnueabihf-binutils OUTPUT_VARIABLE ARM_GNUEABIHF_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) # 再执行project指令 project(rpi-zero)
- 补充库编译相关的显式配置,覆盖宿主机默认参数:
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "Generate PIC for static/shared libraries") set(CMAKE_THREAD_LIBS_INIT "-lpthread") set(CMAKE_HAVE_THREADS_LIBRARY 1) set(CMAKE_USE_WIN32_THREADS_INIT 0) set(CMAKE_USE_PTHREADS_INIT 1) set(THREADS_PREFER_PTHREAD_FLAG ON) set(CMAKE_BUILD_TYPE Debug) # 配置CXX_FLAGS时用提前解析好的路径 set(CMAKE_CXX_FLAGS " -std=gnu++2a -fcolor-diagnostics -fdiagnostics-color=always -Wno-ignored-attributes -Werror=return-type -Wfatal-errors" ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-anon-enum-enum-conversion") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-macro-redefined") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-volatile") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-format-security") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --target=arm-linux-gnueabihf ") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${ARM_GNUEABIHF_PREFIX}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -B${SYS_ROOT}/usr/lib/gcc/arm-linux-gnueabihf/10 ") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=vfpv2 -march=armv6 -mfloat-abi=hard -std=c++20")
- 完全清空之前的构建目录缓存,重新执行cmake生成构建文件,避免旧的缓存配置干扰。
内容的提问来源于stack exchange,提问作者somebody4
相关产品推荐
相关产品推荐

