You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 02:05:14