如何用CMake实现嵌入式项目C文件转汇编再编译的构建流程?
用CMake实现C→汇编→目标文件的定制嵌入式构建流程
针对嵌入式项目中要求将C源文件依次转换为汇编文件、最终生成目标文件的需求,以下是符合要求的CMake实现方案,同时满足并行编译、自动处理源文件、IDE识别等要求:
完整CMake配置代码
# 1. 定义项目根目录(根据实际项目结构调整) set(Project_root "${CMAKE_CURRENT_SOURCE_DIR}") # 2. 定义待处理的C源文件列表 set(C_SOURCES ${Project_root}/SEGGER/SEGGER_RTT.c ${Project_root}/sdk/components/boards/boards.c ${Project_root}/sdk/modules/nrfx/mdk/system_nrf52840.c ${Project_root}/sdk/integration/nrfx/legacy/nrf_drv_clock.c ${Project_root}/sdk/integration/nrfx/legacy/nrf_drv_spi.c ${Project_root}/sdk/modules/nrfx/drivers/src/nrfx_clock.c # 添加更多源文件... ) # 3. 定义自定义的C和ASM编译参数(根据项目需求调整) set(D_C_FLAGS "-DNRF52840_XXAA -DDEBUG") set(D_ASM_FLAGS "-DNRF52840_XXAA") # 4. 设置输出目录并创建 set(OUTPUT_DEBUG_DIR "${Project_root}/Output/Debug") set(ASM_OUTPUT_DIR "${OUTPUT_DEBUG_DIR}/asm") set(OBJ_OUTPUT_DIR "${OUTPUT_DEBUG_DIR}/obj") file(MAKE_DIRECTORY ${ASM_OUTPUT_DIR} ${OBJ_OUTPUT_DIR}) # 5. 自动收集include_directories配置的包含路径,转换为编译参数 get_property(INCLUDE_DIRS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) foreach(DIR ${INCLUDE_DIRS}) list(APPEND INCLUDES "-I${DIR}") endforeach() # 6. 遍历所有C源文件,生成C→ASM→OBJ的转换规则 set(ALL_OBJ_FILES "") foreach(SOURCE_FILE ${C_SOURCES}) get_filename_component(FILE_NAME ${SOURCE_FILE} NAME) get_filename_component(FILE_BASE ${SOURCE_FILE} NAME_WE) set(ASM_FILE "${ASM_OUTPUT_DIR}/${FILE_BASE}.asm") set(OBJ_FILE "${OBJ_OUTPUT_DIR}/${FILE_BASE}.o") # C文件转汇编 add_custom_command( OUTPUT ${ASM_FILE} COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS_DEBUG} ${INCLUDES} ${D_C_FLAGS} ${SOURCE_FILE} -o ${ASM_FILE} MAIN_DEPENDENCY ${SOURCE_FILE} COMMENT "Generating assembly: ${FILE_NAME} → ${FILE_BASE}.asm" ) # 汇编文件转目标文件 add_custom_command( OUTPUT ${OBJ_FILE} COMMAND ${CMAKE_ASM_COMPILER} ${CMAKE_ASM_FLAGS_DEBUG} ${INCLUDES} ${D_ASM_FLAGS} ${ASM_FILE} -o ${OBJ_FILE} MAIN_DEPENDENCY ${ASM_FILE} COMMENT "Assembling: ${FILE_BASE}.asm → ${FILE_BASE}.o" ) list(APPEND ALL_OBJ_FILES ${OBJ_FILE}) endforeach() # 7. 创建总构建目标,触发所有转换流程 add_custom_target( all_objects ALL DEPENDS ${ALL_OBJ_FILES} COMMENT "Building all object files via custom C→ASM→OBJ pipeline" ) # 8. 让IDE识别C源文件属于总目标 set_property(TARGET all_objects PROPERTY SOURCES ${C_SOURCES}) # 9. 配置clean操作,清除生成的汇编和目标文件 set_directory_properties( PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${ASM_OUTPUT_DIR};${OBJ_OUTPUT_DIR}" )
方案满足的要求说明
- 并行编译支持:每个C文件的转换流程都是独立的构建单元,Ninja、Make等构建工具会自动调度并行执行,提升构建效率。
- 批量处理源文件:通过
foreach循环遍历C_SOURCES列表,自动为每个文件生成转换规则,无需逐个手动配置。 - 自动填充包含路径:通过
get_property获取include_directories()配置的目录,自动转换为编译所需的-I参数,无需手动维护包含路径列表。 - clean操作支持:设置
ADDITIONAL_MAKE_CLEAN_FILES后,执行cmake --build . --target clean会自动删除asm和obj目录下的所有生成文件。 - 总目标触发所有操作:
all_objects被标记为ALL目标,执行cmake --build .时会自动触发所有C→ASM→OBJ的转换流程。 - IDE源文件识别:通过
set_property将C_SOURCES关联到all_objects目标,CLion等IDE会将这些C文件显示在目标的源文件列表中,支持代码编辑、跳转和索引。
使用说明
- 确保
Project_root指向你的项目根目录,C_SOURCES包含所有需要处理的C源文件。 - 根据项目需求调整
D_C_FLAGS和D_ASM_FLAGS中的宏定义与编译参数。 - 使用
include_directories()添加项目所需的头文件目录,配置会自动同步到编译参数中。 - 执行构建:
mkdir build && cd build cmake -G Ninja .. # 或其他构建器,如Unix Makefiles ninja # 或make,自动构建所有目标文件 - 执行清理:
ninja clean # 或make clean
内容的提问来源于stack exchange,提问作者Patrik Staron
相关产品推荐
相关产品推荐

