CMake编译多核心FreeRTOS遇ninja重复生成文件错误
解决方案
方案1:序列化构建步骤,避免并发修改
冲突根源是两个核的编译任务并发修改同一SDK文件,直接让它们按顺序执行即可禁止并行冲突。
具体实现
- 为每个核的SDK编译创建独立自定义目标
- 让第二个目标依赖第一个目标的完成,确保同一时间只有一个任务修改SDK头文件
- 保留备份-替换-恢复流程,通过CMake的
DEPENDS控制执行顺序
示例CMake代码:
# 第一个核的编译目标 add_custom_target(build_sdk_core1 COMMAND cp ${SDK_DIR}/freertos/config/FreeRTOSConfig.h ${SDK_DIR}/freertos/config/FreeRTOSConfig.h.bak COMMAND cp ${CMAKE_SOURCE_DIR}/config/core1/FreeRTOSConfig.h ${SDK_DIR}/freertos/config/FreeRTOSConfig.h COMMAND make -C ${SDK_DIR} COMMAND cp ${SDK_DIR}/freertos/config/FreeRTOSConfig.h.bak ${SDK_DIR}/freertos/config/FreeRTOSConfig.h COMMAND rm ${SDK_DIR}/freertos/config/FreeRTOSConfig.h.bak BYPRODUCTS ${SDK_DIR}/libfreertos_core1.a # 替换为实际生成的库文件名 ) # 第二个核的编译目标,依赖第一个目标完成 add_custom_target(build_sdk_core2 DEPENDS build_sdk_core1 COMMAND cp ${SDK_DIR}/freertos/config/FreeRTOSConfig.h ${SDK_DIR}/freertos/config/FreeRTOSConfig.h.bak COMMAND cp ${CMAKE_SOURCE_DIR}/config/core2/FreeRTOSConfig.h ${SDK_DIR}/freertos/config/FreeRTOSConfig.h COMMAND make -C ${SDK_DIR} clean # 清理前一次编译产物 COMMAND make -C ${SDK_DIR} COMMAND cp ${SDK_DIR}/freertos/config/FreeRTOSConfig.h.bak ${SDK_DIR}/freertos/config/FreeRTOSConfig.h COMMAND rm ${SDK_DIR}/freertos/config/FreeRTOSConfig.h.bak BYPRODUCTS ${SDK_DIR}/libfreertos_core2.a ) # 导入为IMPORTED目标 add_library(freertos_core1 STATIC IMPORTED) set_target_properties(freertos_core1 PROPERTIES IMPORTED_LOCATION ${SDK_DIR}/libfreertos_core1.a ) add_dependencies(freertos_core1 build_sdk_core1) add_library(freertos_core2 STATIC IMPORTED) set_target_properties(freertos_core2 PROPERTIES IMPORTED_LOCATION ${SDK_DIR}/libfreertos_core2.a ) add_dependencies(freertos_core2 build_sdk_core2)
方案2:修改SDK的Makefile,支持外部配置文件(推荐)
如果允许修改SDK的Makefile,这是最干净的方案,无需替换任何SDK文件,直接通过编译参数指定自定义配置。
具体实现
- 打开SDK中FreeRTOS模块的Makefile,找到CFLAGS定义部分
- 添加可配置参数
CONFIG_INCLUDE_DIR,默认指向SDK原config目录,允许外部覆盖 - 修改CFLAGS,把自定义目录加到头文件搜索路径最前面,确保优先使用外部配置
示例修改SDK的Makefile:
# 新增:允许外部传入配置目录,默认用SDK自带路径 CONFIG_INCLUDE_DIR ?= $(CURDIR)/config # 修改CFLAGS,优先使用自定义配置目录 CFLAGS += -I$(CONFIG_INCLUDE_DIR)
CMake中为每个核指定不同配置目录:
add_custom_target(build_sdk_core1 COMMAND make -C ${SDK_DIR} CONFIG_INCLUDE_DIR=${CMAKE_SOURCE_DIR}/config/core1 BYPRODUCTS ${SDK_DIR}/libfreertos_core1.a ) add_custom_target(build_sdk_core2 COMMAND make -C ${SDK_DIR} CONFIG_INCLUDE_DIR=${CMAKE_SOURCE_DIR}/config/core2 clean COMMAND make -C ${SDK_DIR} CONFIG_INCLUDE_DIR=${CMAKE_SOURCE_DIR}/config/core2 BYPRODUCTS ${SDK_DIR}/libfreertos_core2.a ) # 导入IMPORTED目标的代码同方案1
此方案支持并行编译,因为不会修改SDK任何文件,仅通过编译参数指定不同配置路径。
方案3:用-include编译参数强制覆盖配置
如果无法修改SDK的Makefile,可在调用make时通过CFLAGS传递-include参数,强制所有编译单元先包含自定义配置文件,覆盖SDK原有配置。
具体实现
CMake代码示例:
add_custom_target(build_sdk_core1 COMMAND make -C ${SDK_DIR} CFLAGS="-include ${CMAKE_SOURCE_DIR}/config/core1/FreeRTOSConfig.h" BYPRODUCTS ${SDK_DIR}/libfreertos_core1.a ) add_custom_target(build_sdk_core2 COMMAND make -C ${SDK_DIR} clean COMMAND make -C ${SDK_DIR} CFLAGS="-include ${CMAKE_SOURCE_DIR}/config/core2/FreeRTOSConfig.h" BYPRODUCTS ${SDK_DIR}/libfreertos_core2.a ) # 导入IMPORTED目标的代码同前
注意:自定义配置文件需包含FreeRTOS所需的所有宏定义,确保功能完整。
内容的提问来源于stack exchange,提问作者NetoBF
相关产品推荐
相关产品推荐

