CMake入门:CMake简介、CMakeLists.txt基本语法、project()与add_executable()

各位同学好,我是老张。今天咱们正式开始CMake的学习之旅。说实话,我最早接触CMake的时候也觉得很头大——明明Makefile写得挺顺手的,干嘛要学这个?后来在嵌入式项目里被各种平台、编译器折腾得够呛,才明白CMake这东西,真香。

CMake是什么?为什么需要它?

CMake,全称Cross-platform Make。说白了,它是一个构建系统生成器。你写一份CMakeLists.txt,它就能帮你生成对应平台的Makefile、Visual Studio工程、Xcode工程等等。

我举个例子你就明白了。我在做STM32项目时,代码要在Windows上编译,同事用Linux,还有人用Mac。如果每个人手写Makefile,那维护成本简直灾难。CMake一出马,一份配置文件,三平台通吃。

核心思想:CMake不直接编译代码,它负责生成"编译代码的脚本"。你只管描述"我要编译什么、用什么工具链",剩下的交给CMake。

CMakeLists.txt——CMake的灵魂

每个CMake项目,根目录下必须有一个CMakeLists.txt文件。这是CMake的入口,也是你与CMake对话的唯一方式。

它的语法其实很简单,我总结为三句话:

  • 命令不区分大小写,但习惯用小写
  • 参数用空格分隔,字符串用双引号包起来
  • 注释用#号,跟Shell脚本一样

来看一个最基础的例子:

# 这是注释
cmake_minimum_required(VERSION 3.10)
project(HelloWorld)
add_executable(hello main.c)

就这三行,一个完整的CMake项目就搭起来了。是不是比Makefile清爽多了?

project()——给项目起个名

project()是每个CMakeLists.txt里必须有的命令。它的作用不只是起名字,还会帮你设置一堆有用的变量。

语法很简单:

project(<项目名> [语言列表])

比如:

project(MyApp C CXX ASM)

这表示项目名叫MyApp,用C、C++和汇编语言。如果不指定语言,默认只启用C和C++。

我的习惯:在嵌入式项目中,我通常会显式写上project(MyProject C ASM)。因为很多MCU的启动代码是汇编写的,你不写ASM,CMake可能找不到汇编器,编译直接报错。我曾经在这个坑里爬了半小时...

project()执行后,CMake会自动生成几个变量:

变量名 含义 示例值
PROJECT_NAME 项目名称 MyApp
PROJECT_SOURCE_DIR 项目源码根目录 /home/user/myapp
PROJECT_BINARY_DIR 构建目录 /home/user/myapp/build
CMAKE_PROJECT_NAME 顶层项目名 MyApp

嗯,这里要注意:PROJECT_SOURCE_DIRCMAKE_SOURCE_DIR在单项目时是一样的,但如果你用了add_subdirectory()引入子项目,它们就有区别了。这个后面再细说。

add_executable()——生成可执行文件

这个命令就是告诉CMake:我要生成一个可执行文件,源文件有哪些。

语法:

add_executable(<目标名> [源文件列表])

比如:

add_executable(hello main.c utils.c uart.c)

这就会生成一个叫hello的可执行文件(Windows下是hello.exe),由main.c、utils.c、uart.c编译链接而成。

避坑指南:我曾经犯过一个低级错误——把头文件也写进了add_executable里。比如add_executable(hello main.c utils.h)。CMake不会报错,但头文件会被当成源文件处理,编译时会出奇怪的问题。记住:add_executable只放.c/.cpp/.s文件,头文件用target_include_directories管理

一个完整的入门示例

咱们来写一个完整的例子,把上面两个命令串起来:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)

# 项目名:Blinky,语言:C和汇编
project(Blinky C ASM)

# 生成可执行文件blinky.elf
add_executable(blinky.elf
    main.c
    startup_stm32f4.s
    system_stm32f4.c
)

然后在终端里执行:

mkdir build
cd build
cmake ..
make

搞定!blinky.elf就生成在build目录下了。

知识体系总览

下面这张图,帮你把今天讲的内容串起来:

CMake入门知识体系 CMake是什么 CMakeLists.txt语法 构建流程 跨平台构建系统生成器 命令、变量、注释 cmake → make → 可执行文件 核心命令:project() + add_executable() 定义项目名称、语言 → 指定源文件生成可执行文件 一份CMakeLists.txt,搞定所有平台

几个实用小技巧

最后分享几个我平时常用的写法:

  • 源文件少的时候直接写:add_executable(app main.c),简单粗暴
  • 源文件多的时候用变量:
set(SRC_LIST
    main.c
    driver/gpio.c
    driver/uart.c
    driver/spi.c
)
add_executable(app ${SRC_LIST})

这样写,后期加文件只需要改set那一块,不用动add_executable那行。我在维护一个200+源文件的工程时,这个习惯帮我省了不少事。

关于cmake_minimum_required:我建议你写cmake_minimum_required(VERSION 3.10)或更高。太老的版本不支持很多现代特性,比如后面要讲的target_compile_features。但也不要写太高,比如3.30,因为有些客户的服务器还在用Ubuntu 18.04,自带的CMake才3.10。

好了,今天的内容就到这里。CMake入门其实不难,记住project()add_executable()这两个命令,你就能跑起来第一个CMake项目了。下一节咱们会深入聊聊变量、条件判断和循环,这些都是写复杂构建脚本的基础。


公众号:蓝海资料掘金营,微信deep3321