云计算百科
云计算领域专业知识百科平台

⚔️ Nimmake vs CMake — 嵌入式构建工具全面对比

⚔️ Nimmake vs CMake — 嵌入式构建工具全面对比

CMake 是通用构建系统的行业标准,Nimmake 是专为嵌入式 MCU 打造的现代替代方案。当你的项目是 ARM/RISC-V 固件而非桌面应用时,选择可能比你想象的更简单。


📋 一句话概括

工具本质设计哲学
CMake 跨平台 构建系统生成器(meta-build) 编写 CMakeLists.txt → 生成 Makefile/Ninja → 编译
Nimmake 嵌入式专用 构建系统 编写 Python → 直接编译,零中间步骤

🔍 核心差异总览

对比维度CMakeNimmake🏆
语言 自定义 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)

内置的第三方库支持:

库CMake 集成难度Nimmake 集成
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)

赞(0)
未经允许不得转载:网硕互联帮助中心 » ⚔️ Nimmake vs CMake — 嵌入式构建工具全面对比
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!