1.1 CMake Windows x64 MSI:

cmake-4.3.2-windows-x86_64.msi
在这里插入图片描述

1.2 Ninja 官方 GitHub Release

https://github.com/ninja-build/ninja/releases
在这里插入图片描述
解压到E:/Programs,这里路径,arm-none-eabi-gcc.cmake里面修改

1.3 gcc

https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
arm-gnu-toolchain-15.2.rel1-mingw-w64-x86_64-arm-none-eabi.zip
解压后,路径加入系统环境变量

1.4 验证

cmake --version
ninja --version

CMake + Ninja 工程说明

本工程使用 CMake 生成 Ninja 构建规则,再由 Ninja 调用 ARM GCC 编译固件。

整体关系如下:

CMakeLists.txt
    |
    v
cmake -G Ninja
    |
    v
build/build.ninja
    |
    v
ninja
    |
    v
TARGET_NAME.elf / TARGET_NAME.hex / TARGET_NAME.bin / TARGET_NAME.map

1. CMakeLists.txt 是什么

CMakeLists.txt 是 CMake 工程的主配置文件。

它用来描述:

项目名称
使用的编程语言
源文件列表
头文件搜索路径
宏定义
CPU 编译参数
链接脚本
最终输出文件
构建后的转换动作

对于嵌入式工程,它通常还会配置:

MCU 内核参数,例如 cortex-m0plus
启动汇编文件
链接脚本 .ld
objcopy 生成 .hex / .bin
size 输出 Flash / RAM 占用

2. CMake、Ninja、GCC 的关系

三者分工不同:

CMake:读取 CMakeLists.txt,生成构建规则
Ninja:读取 build.ninja,执行具体编译命令
GCC:真正编译 C/ASM 文件并链接生成固件

也就是:

CMakeLists.txt  --cmake-->  build.ninja  --ninja-->  gcc 编译/链接

3. 为什么不直接手写 build.ninja

build.ninja 通常不手写。

原因是:

Ninja 语法很简单,适合快速执行,不适合维护复杂工程逻辑
CMakeLists.txt 更适合描述跨平台工程结构
CMake 可以自动生成依赖关系和构建规则

所以推荐维护:

CMakeLists.txt

而不是维护:

build.ninja

4. toolchain 文件是什么

交叉编译时,CMake 需要知道使用哪一套编译器。

因此会单独准备一个 toolchain 文件,例如:

arm-none-eabi-gcc.cmake

它里面通常指定:

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(TOOLCHAIN_DIR "E:/Programs/arm-gnu-toolchain/bin")

set(CMAKE_C_COMPILER "${TOOLCHAIN_DIR}/arm-none-eabi-gcc.exe")
set(CMAKE_ASM_COMPILER "${TOOLCHAIN_DIR}/arm-none-eabi-gcc.exe")
set(CMAKE_OBJCOPY "${TOOLCHAIN_DIR}/arm-none-eabi-objcopy.exe")
set(CMAKE_SIZE "${TOOLCHAIN_DIR}/arm-none-eabi-size.exe")

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

这样即使 arm-none-eabi-gcc.exe 没有加入系统 PATH,CMake 也能找到它。

5. 典型目录结构

推荐目录结构如下:

Project_ninja/
    CMakeLists.txt
    arm-none-eabi-gcc.cmake
    startup_xxx_gcc.s
    target.ld
    build/
        build.ninja
        TARGET_NAME.elf
        TARGET_NAME.hex
        TARGET_NAME.bin
        TARGET_NAME.map

其中:

CMakeLists.txt              CMake 主配置文件
arm-none-eabi-gcc.cmake     ARM GCC 工具链配置
startup_xxx_gcc.s           MCU 启动文件
target.ld                   链接脚本
build/                      CMake/Ninja 构建输出目录

6. 配置工程

第一次构建前,需要先执行 CMake 配置:

cmake -S .\Project_ninja -B .\Project_ninja\build -G Ninja -DCMAKE_TOOLCHAIN_FILE=.\Project_ninja\arm-none-eabi-gcc.cmake

参数含义:

-S .\Project_ninja
指定源码目录,也就是 CMakeLists.txt 所在目录

-B .\Project_ninja\build
指定构建输出目录

-G Ninja
指定生成 Ninja 构建规则

-DCMAKE_TOOLCHAIN_FILE=...
指定 ARM GCC 工具链文件

配置成功后,会生成:

Project_ninja/build/build.ninja

7. 编译工程

配置完成后,执行:

cmake --build .\Project_ninja\build

或者进入 build 目录后直接执行:

ninja

构建成功后,通常会生成:

Project_ninja/build/TARGET_NAME.elf
Project_ninja/build/TARGET_NAME.hex
Project_ninja/build/TARGET_NAME.bin
Project_ninja/build/TARGET_NAME.map

8. 清理工程

删除构建目录即可完整清理:

Remove-Item -Recurse -Force .\Project_ninja\build

然后重新配置:

cmake -S .\Project_ninja -B .\Project_ninja\build -G Ninja -DCMAKE_TOOLCHAIN_FILE=.\Project_ninja\arm-none-eabi-gcc.cmake

9. CMakeLists.txt 常见内容

一个嵌入式 CMake 工程通常包含:

cmake_minimum_required(VERSION 3.20)

project(TARGET_NAME C ASM)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)

set(TARGET_NAME target_name)
set(ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
set(LINKER_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/target.ld)

源文件:

set(PROJECT_SOURCES
    ${ROOT_DIR}/User/main.c
    ${ROOT_DIR}/User/system_xxx.c
    ${CMAKE_CURRENT_LIST_DIR}/startup_xxx_gcc.s
)

头文件路径:

target_include_directories(${TARGET_NAME}.elf PRIVATE
    ${ROOT_DIR}/User
    ${ROOT_DIR}/Drivers/CMSIS/Include
)

宏定义:

target_compile_definitions(${TARGET_NAME}.elf PRIVATE
    MCU_MODEL
    USE_FULL_LL_DRIVER
)

CPU 参数:

set(CPU_FLAGS
    -mcpu=cortex-m0plus
    -mthumb
    -mfloat-abi=soft
)

编译参数:

target_compile_options(${TARGET_NAME}.elf PRIVATE
    ${CPU_FLAGS}
    -Os
    -g3
    -Wall
    -Wextra
    -ffunction-sections
    -fdata-sections
)

链接参数:

target_link_options(${TARGET_NAME}.elf PRIVATE
    ${CPU_FLAGS}
    -T${LINKER_SCRIPT}
    -Wl,-Map=${CMAKE_BINARY_DIR}/${TARGET_NAME}.map
    -Wl,--gc-sections
    -Wl,--print-memory-usage
    -specs=nano.specs
    -specs=nosys.specs
    -nostartfiles
)

生成 HEX / BIN:

add_custom_command(TARGET ${TARGET_NAME}.elf POST_BUILD
    COMMAND ${CMAKE_OBJCOPY} -O ihex
            $<TARGET_FILE:${TARGET_NAME}.elf>
            ${CMAKE_BINARY_DIR}/${TARGET_NAME}.hex
    COMMAND ${CMAKE_OBJCOPY} -O binary
            $<TARGET_FILE:${TARGET_NAME}.elf>
            ${CMAKE_BINARY_DIR}/${TARGET_NAME}.bin
    COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${TARGET_NAME}.elf>
)

10. 常见问题

cmake 找不到

确认 CMake 已加入 PATH。

验证:

cmake --version

ninja 找不到

确认 ninja.exe 所在目录已加入 PATH。

验证:

ninja --version

arm-none-eabi-gcc 找不到

如果 toolchain 文件中写了绝对路径,一般不需要加入 PATH。

检查路径是否正确:

E:/Programs/arm-gnu-toolchain/bin/arm-none-eabi-gcc.exe

修改了源文件列表后怎么办

重新构建即可:

cmake --build .\Project_ninja\build

如果改了 CMake 配置,建议重新配置一次:

cmake -S .\Project_ninja -B .\Project_ninja\build -G Ninja -DCMAKE_TOOLCHAIN_FILE=.\Project_ninja\arm-none-eabi-gcc.cmake

11. 推荐工作流

日常开发建议流程:

cmake -S .\Project_ninja -B .\Project_ninja\build -G Ninja -DCMAKE_TOOLCHAIN_FILE=.\Project_ninja\arm-none-eabi-gcc.cmake
cmake --build .\Project_ninja\build

修改 C 文件后,只需要:

cmake --build .\Project_ninja\build

完全清理后重新构建:

Remove-Item -Recurse -Force .\Project_ninja\build
cmake -S .\Project_ninja -B .\Project_ninja\build -G Ninja -DCMAKE_TOOLCHAIN_FILE=.\Project_ninja\arm-none-eabi-gcc.cmake
cmake --build .\Project_ninja\build
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐