如何使用CMake将C/C++代码编译生成raw binary格式的*.bin文件
解决方案
推荐基于CMake原生add_executable改造实现,你提到的add_executable的两个限制都可以通过显式配置内置属性关闭,最终得到的目标完全兼容所有原生CMake配置接口。
前置工具链配置(可选,建议放在裸机工具链文件中)
# 跳过工具链检测阶段对main函数的要求 set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY CACHE STRING "") # 关闭C/C++默认隐式链接的标准库,避免自动引入-lstdc++等依赖 set(CMAKE_C_STANDARD_LIBRARIES "" CACHE STRING "") set(CMAKE_CXX_STANDARD_LIBRARIES "" CACHE STRING "")
add_binary 封装实现
function(add_binary target) # 声明原生可执行目标,原生支持所有target_*配置接口 add_executable(${target} ${ARGN}) # 基础编译链接属性配置,匹配你期望的编译参数 target_compile_options(${target} PRIVATE -ffreestanding $<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>:-fno-exceptions -fno-rtti> ) target_link_options(${target} PRIVATE -nostdlib -nostartfiles ) # 方案1:直接链接输出raw binary(不需要保留elf调试文件可选) set_target_properties(${target} PROPERTIES LINK_EXECUTABLE "$<IF:$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,CXX>,${CMAKE_CXX_COMPILER},${CMAKE_C_COMPILER}> <LINK_FLAGS> <OBJECTS> -o ${target}.bin <LINK_LIBRARIES> -lgcc" ) # 方案2:先生成elf文件,再通过objcopy转bin(推荐,保留elf用于调试) # find_program(OBJCOPY_PATH ${CMAKE_OBJCOPY} REQUIRED) # add_custom_command(TARGET ${target} POST_BUILD # COMMAND ${OBJCOPY_PATH} -O binary $<TARGET_FILE:${target}> $<TARGET_FILE_DIR:${target}>/${target}.bin # BYPRODUCTS $<TARGET_FILE_DIR:${target}>/${target}.bin # COMMENT "Generating raw binary: ${target}.bin" # ) endfunction()
使用示例
完全符合你期望的调用方式,且直接支持所有原生CMake目标配置:
add_binary(something src/start.c src/kernel.cpp) # 直接对外层目标配置属性,不需要操作内部中间目标 target_include_directories(something PRIVATE include) target_compile_options(something PRIVATE -O2 -march=i686) # 传入链接脚本 target_link_options(something PRIVATE -T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld) # 链接其他依赖目标 target_link_libraries(something PRIVATE libprintf)
方案优势
- 对外暴露的目标是原生CMake可执行目标,兼容
target_include_directories/target_compile_options/target_link_libraries等所有标准接口 - 不需要额外维护中间对象库,配置逻辑更简洁
- 两种输出方案可选,兼顾直接输出bin和保留调试信息的需求
- 完全匹配你给出的裸机编译命令参数
内容的提问来源于stack exchange,提问作者Bitwize
相关产品推荐
相关产品推荐

