CMake跨编译场景下子目录二进制需先于主库构建的问题求助
交叉编译库前用主机编译器生成头文件的CMake解决方案
问题背景
- 需求:为嵌入式平台交叉编译库,但必须先用主机编译器生成一个辅助二进制,用它来产出库依赖的头文件
- 尝试的方案:主CMakeLists.txt负责交叉编译库,通过
add_subdirectory引入子目录编译主机二进制,但无法保证子目录构建流程先于主库执行,add_dependencies命令未生效
极简示例代码
主CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(EmbeddedLib) # 设置交叉编译工具链 set(CMAKE_C_COMPILER arm-none-eabi-gcc) set(CMAKE_CXX_COMPILER arm-none-eabi-g++) # 添加子目录构建主机工具 add_subdirectory(host_tool) # 构建嵌入式库 add_library(embedded_lib src/lib.c) # 尝试添加依赖,但未生效 add_dependencies(embedded_lib host_tool) # 引入生成的头文件目录 target_include_directories(embedded_lib PRIVATE generated_headers)
host_tool/CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(HostTool) # 强制使用主机编译器 set(CMAKE_C_COMPILER gcc) set(CMAKE_CXX_COMPILER g++) add_executable(host_tool src/host_tool.c) # 生成头文件的自定义命令 add_custom_command( OUTPUT ${PROJECT_BINARY_DIR}/../generated_headers/generated.h COMMAND host_tool ${PROJECT_BINARY_DIR}/../generated_headers/generated.h DEPENDS host_tool ) add_custom_target(generate_header ALL DEPENDS ${PROJECT_BINARY_DIR}/../generated_headers/generated.h )
问题现象(构建输出)
-- The C compiler identification is GNU 10.3.1 -- The CXX compiler identification is GNU 10.3.1 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /usr/bin/arm-none-eabi-gcc - skipped -- Detecting C compile features -- Detecting C compile features - done -- The C compiler identification is GNU 12.2.1 -- The CXX compiler identification is GNU 12.2.1 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /usr/bin/gcc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Configuring done -- Generating done -- Build files have been written to: ./build [ 25%] Building C object host_tool/CMakeFiles/host_tool.dir/src/host_tool.c.o [ 50%] Linking C executable host_tool [ 50%] Built target host_tool [ 75%] Building C object CMakeFiles/embedded_lib.dir/src/lib.c.o In file included from ./src/lib.c:1: ./generated_headers/generated.h: No such file or directory compilation terminated. make[2]: *** [CMakeFiles/embedded_lib.dir/build.make:76: CMakeFiles/embedded_lib.dir/src/lib.c.o] Error 1 make[1]: *** [CMakeFiles/Makefile2:100: CMakeFiles/embedded_lib.dir/all] Error 2 make: *** [Makefile:91: all] Error 2
可见主机工具虽编译完成,但生成头文件的步骤未在库编译前触发,导致头文件缺失。
解决方案(参考@KamilCuk的实现)
核心思路是在子目录中单独创建使用主机编译器的CMake实例,通过execute_process在主CMake配置阶段就触发子构建,确保头文件在主库编译前生成完毕。
修改后的主CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(EmbeddedLib) # 设置交叉编译工具链 set(CMAKE_C_COMPILER arm-none-eabi-gcc) set(CMAKE_CXX_COMPILER arm-none-eabi-g++) # 单独构建主机工具并生成头文件 execute_process( COMMAND ${CMAKE_COMMAND} -S ${CMAKE_SOURCE_DIR}/host_tool -B ${CMAKE_BINARY_DIR}/host_tool COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/host_tool RESULT_VARIABLE HOST_TOOL_BUILD_RESULT ) if(NOT HOST_TOOL_BUILD_RESULT EQUAL 0) message(FATAL_ERROR "Failed to build host tool") endif() # 构建嵌入式库 add_library(embedded_lib src/lib.c) # 引入生成的头文件目录 target_include_directories(embedded_lib PRIVATE ${CMAKE_BINARY_DIR}/generated_headers)
调整后的host_tool/CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(HostTool) # 强制使用主机编译器 set(CMAKE_C_COMPILER gcc) set(CMAKE_CXX_COMPILER g++) add_executable(host_tool src/host_tool.c) # 生成头文件的自定义命令和目标 add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/../generated_headers/generated.h COMMAND host_tool ${CMAKE_BINARY_DIR}/../generated_headers/generated.h DEPENDS host_tool ) add_custom_target(generate_header ALL DEPENDS ${CMAKE_BINARY_DIR}/../generated_headers/generated.h )
修改后,主CMake配置阶段会优先完成主机工具的编译和头文件生成,确保后续交叉编译库时依赖的头文件已存在。
内容的提问来源于stack exchange,提问作者ArthurLambert
相关产品推荐
相关产品推荐

