一、CMake是什么?
说实话,我第一次接触CMake的时候,心里是有点抵触的。那时候我还在用Makefile写嵌入式项目,觉得"一个项目一个Makefile,简单直接,干嘛要学新工具?"直到有一次,我需要把一个STM32的项目移植到GD32上,还要同时支持Keil和GCC两种工具链……嗯,那天我改Makefile改到凌晨三点。
从那以后,我彻底明白了:CMake不是来取代你的Makefile的,它是来拯救你的。
1.1 CMake的历史背景
CMake诞生于2000年,最初是为了解决VTK(可视化工具包)的跨平台构建问题。它的全称是"Cross-Platform Make",说白了就是一套跨平台的构建系统生成器。
你想想看,Windows用Visual Studio,Linux用GCC,macOS用Xcode,每个平台都有自己的构建方式。CMake的作用就是:你写一份CMakeLists.txt,它能帮你生成对应平台的构建文件——VS的.sln、Linux的Makefile、Xcode的.xcodeproj,全都能搞定。
我个人习惯把CMake比作"翻译官"。你告诉它"我要编译这些源文件,链接这些库",它就去跟各个平台的构建工具沟通,帮你把事情办了。
核心理解:CMake本身不编译代码,它只负责生成构建系统的配置文件。真正的编译工作,还是交给Make、Ninja或者IDE去干。
1.2 CMake在嵌入式开发中的角色
嵌入式开发有个特点:碎片化严重。STM32用HAL库,ESP32用ESP-IDF,NXP用MCUXpresso,瑞萨用e2 studio……每个厂商都有自己的IDE和工具链。你换一个芯片,可能整个构建流程都要重写。
CMake在嵌入式领域的角色,就是统一这个混乱的局面。我举个例子:
- 你用STM32CubeMX生成了代码,它默认给你的是Keil或者IAR的工程文件
- 但你的团队用的是GCC + VS Code
- 怎么办?手动改?不现实
- 用CMake写一套构建脚本,以后不管换什么IDE,跑一下CMake就能生成对应的工程
我在项目中遇到过最典型的情况:客户要求代码必须能在Keil和GCC两种环境下编译。如果没有CMake,你得维护两套工程文件,改一个源文件就要同步两次。有了CMake,我只需要维护一份CMakeLists.txt,生成两个工程就行了。
我的建议:如果你还在用IDE自带的工程管理方式,赶紧试试CMake。刚开始可能有点不习惯,但一旦上手,你会发现它带来的灵活性是IDE给不了的。
1.3 CMake vs Makefile vs IDE构建
这三者的关系,我用一张图来说明:
从这张图你能看出来:CMake站在了中间位置。它不像IDE那样"傻瓜式",但也不像Makefile那样"裸奔"。它提供了一套高级抽象,让你用更少的代码管理更复杂的项目。
1.4 为什么嵌入式项目需要CMake?
我总结了几点,都是我在实际项目中踩过的坑:
- 芯片型号切换:从STM32F103换到STM32F407,CMake里改个芯片型号就行,不用重建整个工程
- 工具链切换:从ARM GCC换到IAR,CMake里改个工具链路径就行
- 单元测试:嵌入式代码也能跑单元测试了!用CMake可以轻松切换编译目标,编译成PC上的测试程序
- CI/CD集成:Jenkins、GitLab CI都能直接调用CMake,实现自动化构建
注意:CMake不是万能的。如果你的项目只有一个芯片、一个IDE、一个人维护,那用IDE自带的工程管理完全够用。CMake的优势在于复杂项目和团队协作。
1.5 一个简单的例子
说了这么多,不如看个实际例子。这是一个最简单的嵌入式CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(blink LANGUAGES C CXX ASM)
# 设置芯片型号
set(MCU STM32F103C8T6)
# 添加可执行文件
add_executable(blink.elf
main.c
startup_stm32f103xb.s
)
# 链接脚本
target_link_options(blink.elf PRIVATE
-T ${CMAKE_SOURCE_DIR}/STM32F103C8T6_FLASH.ld
)
你看,就这几行代码,就把一个嵌入式项目的基本框架搭起来了。换成Makefile的话,光处理依赖关系和编译选项就得写几十行。
我曾经帮一个团队从Makefile迁移到CMake,他们的Makefile有300多行,改一次编译选项要翻半天。换成CMake后,核心配置压缩到了50行以内。团队成员都说:"早知道CMake这么好用,我们早就该换了。"
小技巧:刚开始用CMake时,不要追求一步到位。先写一个能编译通过的版本,然后逐步优化。我见过太多人想一次性写出完美的CMakeLists.txt,结果卡在语法上放弃了。
1.6 本章小结
CMake不是银弹,但它确实是目前嵌入式领域最值得学习的构建工具。它帮你把"构建"这件事从IDE的束缚中解放出来,让你的代码真正实现"一次编写,到处编译"。
下一章,我们会深入CMake的核心语法,看看那些常用的命令到底是怎么工作的。嗯,到时候我会分享一些我在项目中踩过的坑,保证让你少走弯路。
公众号:蓝海资料掘金营,微信deep3321