⚔️ Nimmake vs CMake — 嵌入式构建工具全面对比
CMake 是通用构建系统的行业标准,Nimmake 是专为嵌入式 MCU 打造的现代替代方案。当你的项目是 ARM/RISC-V 固件而非桌面应用时,选择可能比你想象的更简单。
📋 一句话概括
| CMake | 跨平台 构建系统生成器(meta-build) | 编写 CMakeLists.txt → 生成 Makefile/Ninja → 编译 |
| Nimmake | 嵌入式专用 构建系统 | 编写 Python → 直接编译,零中间步骤 |
🔍 核心差异总览
| 语言 | 自定义 DSL(cmake 语法) | 纯 Python | 🏆 Nimmake |
| 学习曲线 | ⭐⭐⭐ 中高(DSL + 多阶段模型) | ⭐ 低(会 Python 就会用) | 🏆 Nimmake |
| 芯片预设 | ❌ 需要手写 set(MCU cortex-m4) 等 | ✅ 内置 ARM/RISC-V 预设,一行搞定 | 🏆 Nimmake |
| 厂商型号支持 | ❌ 无 | ✅ VENDOR_MODEL_OF(Vendor.ST, "STM32F407") | 🏆 Nimmake |
| 源码管理 | aux_source_directory() 或手写列表 | Party 系统 目录级自动扫描 | 🏆 Nimmake |
| 头文件路径 | target_include_directories() 手动添加 | 自动推导,按 Party 自动包含 | 🏆 Nimmake |
| 宏定义 | target_compile_definitions() 手动添加 | 声明式传入,自动注入 | 🏆 Nimmake |
| 依赖管理 | target_link_libraries() 链接级 | DependOn() 编译级,自动排序 | 🏆 Nimmake |
| 多工具链切换 | 工具链文件(Toolchain file) 较复杂 | 一键切换,更新 3 行配置 | 🏆 Nimmake |
| RISC-V 支持 | 需手写 -march=rv32imac 等 | 内置 RISCV_32_IMAC_CFG,开箱即用 | 🏆 Nimmake |
| 增量编译 | 依赖后端(Make/Ninja) | 内置增量 + 命令哈希 + 头文件追踪 | 🏆 Nimmake |
| 构建缓存 | ❌ 不自带(需 ccache 等外部工具) | ✅ 内置 –cache | 🏆 Nimmake |
| Ninja 后端 | ✅ 支持(-G Ninja) | ✅ 支持(-n / –ninja) | 平手 |
| 编译数据库 | ✅ 支持(CMAKE_EXPORT_COMPILE_COMMANDS) | ✅ 支持(–compiledb) | 平手 |
| 第三方库集成 | FetchContent / find_package 较复杂 | 内置 FreeRTOS/LVGL/FatFS 等,一行 third_party="FREERTOS" | 🏆 Nimmake |
| IDE 集成 | 极强(VS、CLion、Qt Creator 官方支持) | compile_commands.json + VS Code | 🏆 CMake |
| 大型项目管理 | 极强(数万源文件、复杂依赖) | 中(专注嵌入式,单芯片项目) | 🏆 CMake |
| 桌面/服务端应用 | 行业标准 | ❌ 不支持(纯嵌入式) | 🏆 CMake |
| 构建步骤 | 配置 → 生成 → 构建(三步) | 一步到位 | 🏆 Nimmake |
| 跨平台 | ✅ Windows/Linux/macOS | ✅ Windows/Linux/macOS | 平手 |
📝 实战对比:STM32F407 完整项目
让我们用同一个 STM32F407 + HAL 库 + FreeRTOS 项目,分别用 CMake 和 Nimmake 实现。
项目结构
STM32_Project/
├── Core/
│ ├── main.c
│ ├── stm32f4xx_it.c
│ └── system_stm32f4xx.c
├── Drivers/
│ ├── Inc/
│ └── Src/ (20+ HAL 源文件)
├── FreeRTOS/
│ ├── include/
│ ├── portable/
│ └── src/
├── startup_stm32f407xx.s
└── STM32F407XX_FLASH.ld
🔴 CMake 实现(~100 行)
cmake_minimum_required(VERSION 3.20)
project(STM32F407 LANGUAGES C ASM)
# —- 芯片参数(手动查手册!) —-
set(MCU_FAMILY STM32F407xx)
set(CPU cortex-m4)
set(FPU fpv4-sp-d16)
set(FLOAT_ABI hard)
# —- 工具链设置 —-
set(TOOLCHAIN_PREFIX arm-none-eabi-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_AR ${TOOLCHAIN_PREFIX}ar)
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size)
# —- 编译参数(逐个手动写!) —-
set(COMMON_FLAGS
-mcpu=${CPU}
-mfpu=${FPU}
-mfloat-abi=${FLOAT_ABI}
-mthumb
-O2
-g
-Wall
-fdata-sections
-ffunction-sections
)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMMON_FLAGS} -std=gnu99")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${COMMON_FLAGS}")
# —- 链接参数 —-
set(LINKER_FLAGS
${COMMON_FLAGS}
-nostartfiles
-Wl,–gc-sections
-T${CMAKE_SOURCE_DIR}/STM32F407XX_FLASH.ld
-lm -lc -lgcc
)
# —- 头文件路径(手动添加每个路径) —-
target_include_directories(${PROJECT_NAME} PRIVATE
Core/Inc
Drivers/Inc
FreeRTOS/include
FreeRTOS/portable/GCC/ARM_CM4F
)
# —- 宏定义(手动添加) —-
target_compile_definitions(${PROJECT_NAME} PRIVATE
${MCU_FAMILY}
USE_HAL_DRIVER
)
# —- 源文件(手动列每个文件!) —-
set(CORE_SRCS
Core/main.c
Core/stm32f4xx_it.c
Core/system_stm32f4xx.c
)
file(GLOB DRV_SRCS "Drivers/Src/*.c") # GLOB 不自动更新!
set(FREERTOS_SRCS
FreeRTOS/src/list.c
FreeRTOS/src/queue.c
FreeRTOS/src/tasks.c
FreeRTOS/src/timers.c
FreeRTOS/portable/GCC/ARM_CM4F/port.c
FreeRTOS/portable/MemMang/heap_4.c
)
set(ASM_SRCS startup_stm32f407xx.s)
# —- 构建目标 —-
add_executable(${PROJECT_NAME}
${CORE_SRCS} ${DRV_SRCS} ${FREERTOS_SRCS} ${ASM_SRCS}
)
target_link_options(${PROJECT_NAME} PRIVATE ${LINKER_FLAGS})
# —- 自定义命令:生成 bin/hex —-
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
COMMAND ${CMAKE_OBJCOPY} -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
)
# —- 自定义目标:烧录 —-
add_custom_target(flash
COMMAND openocd -f interface/cmsis-dap.cfg -f target/stm32f4x.cfg
-c "program ${PROJECT_NAME}.elf verify reset exit"
)
🟢 Nimmake 实现(~40 行)
from nimmake.datasets import CORTEX_M4_CFG
from nimmake.Helper import BuildType, Helper
# ★ 工具链
TOOLCHAIN = {
"TOOLPATH": r"D:\\LLVM\\arm-none-eabi-gcc14\\bin",
"TOOL": "gcc",
"TOOL_PREFIX": "arm-none-eabi-",
}
hlp = Helper()
# ★ 芯片配置:自动生成所有 -mcpu/-mfpu/-mthumb 参数
CFG = CORTEX_M4_CFG.clone()
CFG.set("model", "STM32F407")
hlp.Config(CFG)
hlp.set_cfg("linkscript", "STM32F407XX_FLASH.ld")
hlp.set_cfg("std_c", "gnu99")
# ★ 工具链
hlp.Update(TOOLCHAIN)
hlp.Refresh()
# ★ Party 模块:按目录自动扫描源码
core = hlp.Parties("CORE", "Core")
driver = hlp.Parties(
"Driver", "Drivers",
third_party="HAL",
defines={"STM32F407xx": "", "USE_HAL_DRIVER": ""},
)
freertos = hlp.Parties(
"FREERTOS", "FreeRTOS",
third_party="FREERTOS", # ← 内置 FreeRTOS 配置!
include_macros={"chip": "ARM_CM4F", "heap": "4"},
)
# ★ 依赖关系
core.DependOn([driver, freertos])
driver.DependOn([core, freertos])
freertos.DependOn([core])
# ★ 构建目标
srcs = ["startup_stm32f407xx.s"]
t = hlp.Program("test", sources=srcs)
hlp.DefaultTarget(t)
# ★ 烧录命令
hlp.Command("FLASH", [
"openocd -f interface/cmsis-dap.cfg "
"-f target/stm32f4x.cfg "
"-c \\"program build/test.elf verify reset exit\\""
])
hlp.Phony("flash", ["FLASH"])
🔄 构建流程对比
CMake:三步走
# Step 1: 配置(Configure)— 生成构建系统
cmake -B build -G "Ninja" \\
-DCMAKE_TOOLCHAIN_FILE=arm-gcc.cmake \\
-DCMAKE_BUILD_TYPE=Release
# Step 2: 构建(Build)— 执行编译
cmake –build build
# Step 3: 烧录(需要额外的自定义 target)
cmake –build build –target flash
问题:
- 配置阶段耗时,大型项目可能 10-30 秒
- 工具链文件需要额外维护
- 配置错误要到构建阶段才能发现
Nimmake:一步到位
# 直接编译,无需配置阶段
nimmake
# 烧录
nimm- **零配置开销**,Python 文件直接执行
– 工具链检测在 `Refresh()` 时立即报错
– 编译参数在脚本中一目了然` 时立即报错
– 编译参数在脚本中清晰可见
—
## 🧩 关键特性深度对比
### 1️⃣ 芯片配置
```cmake
# CMake — 每个参数手动写,容易遗漏
set(CPU cortex-m4)
set(FPU fpv4-sp-d16)
set(FLOAT_ABI hard)
# 忘了加 -mthumb → 链接报错,排查半天
# Nimmake — 内置预设,一行搞定
CFG = CORTEX_M4_CFG.clone()
# 自动生成: -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mflo- **零配置开销**,Python 文件直接执行
– 工具链检测在 `Refresh()` 时立即报错
– 编译参数在脚本中一目了然thumb
2️⃣ 工具链切换
# CMake — 需要额外维护工具链文件
# arm-gcc.cmake
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_AR arm-none-eabi-ar)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
# 构建时通过 -DCMAKE_TOOLCHAIN_FILE 传入
cmake -B build -DCMAKE_TOOLCHAIN_FILE=arm-gcc.cmake
# Nimmake — 字典直接配置
hlp.Update({
"TOOLPATH": r"D:\\LLVM\\arm-none-eabi-gcc14\\bin",
"TOOL": "gcc",
"TOOL_PREFIX": "arm-none-eabi-",
})
# 换 RISC-V?改三行:
hlp.Update({
"TOOLPATH": r"D:\\LLVM\\xpack-riscv-none-elf-gcc-15\\bin",
"TOOL": "gcc",
"TOOL_PREFIX": "riscv-none-elf-",
})
3️⃣ 第三方库集成
# CMake — 集成 FreeRTOS 需要:
# 1. 下载/添加源码
# 2. 手动列出所有源文件(至少 6 个)
# 3. 手动添加 4 个头文件路径
# 4. 手动添加宏定义
# 5. 处理 portable 层路径
# 或者用 FetchContent(也很复杂):
include(FetchContent)
FetchContent_Declare(
freertos
GIT_REPOSITORY https://github.com/FreeRTOS/FreeRTOS.git
GIT_TAG V10.5.1
)
# … 然后还是要手动配置源文件列表和头文件路径
# Nimmake — 一行搞定
freertos = hlp.Parties("FREERTOS", "FreeRTOS",
third_party="FREERTOS",
include_macros={"chip": "ARM_CM4F", "heap": "4"},
)
# 内置 FreeRTOS 配置自动处理所有细节:
# ✅ 自动选择 portable/GCC/ARM_CM4F 层
# ✅ 自动添加 include 路径
# ✅ 自动添加源文件
# ✅ 自动选择堆管理方案(heap_4.c)
内置的第三方库支持:
| FreeRTOS | ⭐⭐⭐ 手动 | ⭐ third_party="FREERTOS" |
| LVGL | ⭐⭐⭐ 手动 | ⭐ third_party="LVGL" |
| FatFS | ⭐⭐⭐ 手动 | ⭐ third_party="FATFS" |
| CherryUSB | ⭐⭐⭐ 手动 | ⭐ third_party="CHERRYUSB" |
| FreeModbus | ⭐⭐⭐ 手动 | ⭐ third_party="FREEMODBUS" |
| HAL Drivers | ⭐⭐ 半自动 | ⭐ third_party="HAL" |
4️⃣ 编译数据库生成
# CMake
cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
# 生成 build/compile_commands.json
# 需要额外的配置参数记忆
# Nimmake
nimmake –compiledb
# 直接生成 compile_commands.json
5️⃣ 缓存加速
# CMake — 需要外部工具
# 安装 ccache
sudo apt install ccache
# 设置 cmake
cmake -B build -DCMAKE_C_COMPILER_LAUNCHER=ccache
# 跨平台配置不一致(Windows 下麻烦)
# Nimmake — 内建
nimmake –cache # 首次编译
nimmake –cache # 二次编译,缓存命中
📊 适用场景建议
选 CMake 的场景
- ✅ 桌面/服务端应用(Linux/Windows/macOS GUI 程序)
- ✅ 大型项目(百万行代码、数百个模块)
- ✅ 复杂依赖管理(需要 find_package、FetchContent)
- ✅ 需要支持多种 IDE(VS、CLion、Qt Creator 官方支持)
- ✅ 团队已熟练掌握 CMake
- ✅ 需要同时构建嵌入式 + 主机测试程序
选 Nimmake 的场景
- 🏆 ARM / RISC-V MCU 固件开发
- 🏆 多芯片/多平台嵌入式项目(快速切换架构)
- 🏆 快速原型验证(几分钟搭好编译环境)
- 🏆 项目依赖 FreeRTOS/LVGL 等第三方库
- 🏆 团队不熟悉 CMake 但熟悉 Python
- 🏆 CI/CD 嵌入式流水线(命令行驱动,自| 维度 | CMake | Nimmake |
| ———————- | ————————- | —————————— |
| MCU 专精程度 | ⭐⭐ 通用工具,需手动适配 | ⭐⭐⭐⭐⭐ 为嵌入式而生 |
| 上手速度 | ⭐⭐ 学习曲线陡峭 | ⭐⭐⭐⭐⭐ 会 Python 即可上手 |
| 第三方库集成 | ⭐⭐ 灵活但繁琐 | ⭐⭐⭐⭐⭐ 开箱即用 |
| 多芯片切换 | ⭐⭐ 工具链文件 + 参数 | ⭐⭐⭐⭐⭐ 改几行配置 |
| 大型项目管理 | ⭐⭐⭐⭐⭐ 行业标准 | ⭐⭐ 适合中小型项目 |
| 桌面应用 | ⭐⭐⭐⭐⭐ 行业标准 | ❌ 不支持 |
| IDE 集成 | ⭐⭐⭐⭐⭐ 官方支持 | ⭐⭐⭐⭐ compile_commands.json |
| 构建速度 | ⭐⭐⭐⭐ 依赖 Ninja | ⭐⭐⭐⭐⭐ 内置缓存加速 |
| 代码量(MCU 项目) | 80-150 行 | 30-50 行 |
| 代码可读性 | ⭐⭐⭐ DSL 语法 | ⭐⭐⭐⭐⭐ 纯 Python | | ⭐⭐⭐⭐⭐ 纯 P> **CMake 是一个通用构建系统的瑞士军刀> CMake 是一个通用构建系统的瑞士军刀——无所不能,但为嵌入式 MCU 项目配置它常常大材小用。
**Nimmake 是一把专门为嵌入式打造的手术刀——功能聚焦,一刀精准。造的 surgical blade——功能聚焦,一刀精准。
选择建议:
你的项目是桌面/服务端应用? → CMake ✅
你的项目是嵌入式 Linux(Yocto/Buildroot)? → CMake ✅
你的项目超过 50 个模块需要精细管理? → CMake ✅
你的团队已经深度绑定 CLion/Qt Creator? → CMake ✅
你的项目是 ARM/RISC-V MCU 固件? → Nimmake 🏆
你需要快速切换多种芯片? → Nimmake 🏆
你集成了 FreeRTOS/LVGL 等库? → Nimmake 🏆
你希望构建脚本简洁可读? → Nimmake 🏆
🚀 立即体验 Nimmake
# 安装
pip install nimmake
# 查看示例
git clone https://github.com/pophu/nimmake.git
cd nimmake/samples/05_arm32
# 一键编译(对比 cmake -B build && cmake –build- [Nimmake GitHub](https://github.com/pophu/nimmake)
– [Nimmake PyPI](https://pypi.org/project/nimmake/)
– [Nimmake vs Makefile 对比](./nimmake_vs_makefile.md)
– [示例:ARM 项目](file:///d:/MyCodeNew/nimmake/samples/05_arm32/Nimmake.py)
– [示例:RISC-V 项目](file:///d:/MyCodeNew/nimmake/samples/07_riscv32/Nimmake.py)
– [示例:厂商型号自动配置](file:///d:/MyCodeNew/nimmake/samples/60_vendor_model/Nimmake.py)/samples/60_vendor_model/Nimmake.py)
网硕互联帮助中心





评论前必须登录!
注册