第一个CMake项目:从零开始构建你的第一个可执行程序
说实话,我见过太多新手一上来就对着CMakeLists.txt发懵。其实这东西没那么玄乎,说白了就是一个告诉编译器「怎么干活」的脚本文件。今天我们就从零开始,亲手搭建一个最简单的CMake项目。
我个人习惯把第一个项目叫做「Hello CMake」,而不是传统的「Hello World」。为什么?因为我们要学的不是打印字符串,而是理解CMake的工作流。
创建CMakeLists.txt:项目的灵魂文件
每个CMake项目的根目录下,都必须有一个CMakeLists.txt文件。这是CMake的入口,就像C程序的main()函数一样。
先创建一个空目录,比如my_first_cmake_project,然后在里面新建一个文本文件,命名为CMakeLists.txt(注意大小写,一个字母都不能错)。
核心原则:CMakeLists.txt 是纯文本文件,用任何编辑器都能打开。我建议用VS Code或者Sublime,别用记事本——编码问题会坑死你。
cmake_minimum_required:告诉CMake「你得够新」
文件的第一行,我通常会写这个:
cmake_minimum_required(VERSION 3.10)
这行命令的意思是:当前项目要求CMake的最低版本是3.10。如果用户机器上的CMake版本低于3.10,构建时会直接报错退出。
为什么要加这个?我在项目中遇到过一件事:有同事用了3.5版本的CMake,结果死活编译不过,查了半天才发现是某个新特性不支持。从那以后,我每条CMakeLists.txt都会写这一行。
我的建议:版本号别写太高,3.10或3.16是比较稳妥的选择。写太高了,用户还得升级CMake,体验不好。
project():给你的项目起个名字
第二行,定义项目名称:
project(HelloCMake)
这个project()命令不只是起名字那么简单。它会自动定义几个变量:
PROJECT_NAME:项目名称,就是"HelloCMake"PROJECT_SOURCE_DIR:源码目录路径PROJECT_BINARY_DIR:构建目录路径
你想想看,有了这些变量,后面引用路径就方便多了。比如我要引用源码目录下的某个文件,直接写${PROJECT_SOURCE_DIR}/src/main.c就行。
| 变量名 | 含义 | 示例值 |
|---|---|---|
| PROJECT_NAME | 项目名称 | HelloCMake |
| PROJECT_SOURCE_DIR | 源码根目录 | /home/user/my_first_cmake_project |
| PROJECT_BINARY_DIR | 构建目录 | /home/user/my_first_cmake_project/build |
add_executable():把源码变成可执行文件
接下来是最关键的一步——告诉CMake:我要编译一个可执行程序,源码是哪个文件。
add_executable(hello_cmake main.c)
这行命令的意思是:用main.c这个源文件,生成一个名为hello_cmake的可执行文件。
注意,这里hello_cmake是目标名称,在Windows上会生成hello_cmake.exe,在Linux/macOS上生成hello_cmake。CMake会自动处理平台差异。
我曾经踩过的坑:源文件名写错了大小写。在Linux上,main.c和Main.c是两个不同的文件。CMake不会帮你纠错,只会报「找不到文件」。所以文件名一定要和磁盘上的一模一样。
现在,我们还需要一个main.c文件。在项目目录下创建它:
#include <stdio.h>
int main() {
printf("Hello CMake!\n");
return 0;
}
嗯,这里要注意:main.c和CMakeLists.txt必须在同一个目录下。这是最简单的单文件项目结构。
完整的CMakeLists.txt长什么样?
把上面三行拼起来,就是一份完整的构建脚本:
cmake_minimum_required(VERSION 3.10)
project(HelloCMake)
add_executable(hello_cmake main.c)
就三行,没了。是不是比你想象中简单?
构建与运行:见证奇迹的时刻
CMake推荐「外部构建」,也就是在项目目录外单独建一个build目录,所有临时文件都扔里面。这样做的好处是:源码目录干干净净,想重新构建时直接删掉build目录就行。
打开终端,进入项目目录,执行:
mkdir build
cd build
cmake ..
make
解释一下:
mkdir build:创建构建目录cd build:进入构建目录cmake ..:告诉CMake「源码在上一级目录」,CMake会读取../CMakeLists.txt并生成Makefilemake:用生成的Makefile真正编译代码
如果一切顺利,你会看到类似这样的输出:
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/build
[ 50%] Building C object CMakeFiles/hello_cmake.dir/main.c.o
[100%] Linking C executable hello_cmake
然后运行它:
./hello_cmake
屏幕上会打印出:
Hello CMake!
一个小技巧:如果你用的是CMake 3.13以上版本,可以直接用cmake -B build代替mkdir build && cd build && cmake ..。一行命令搞定创建目录和配置。
知识体系总览
下面这张图,把整个流程串起来了。我建议你多看几遍,理解每个环节的作用:
常见问题与避坑指南
我刚开始用CMake时,也踩过不少坑。这里列几个最常见的:
- 找不到CMakeLists.txt:检查文件名大小写,必须是
CMakeLists.txt,不是CmakeLists.txt或cmakelists.txt - 版本不匹配:如果报错说CMake版本太低,要么升级CMake,要么把
cmake_minimum_required的版本号改低一点 - 编译报错:先检查
main.c的语法有没有问题,别急着怀疑CMake - 找不到源文件:确认
add_executable里写的文件名和磁盘上的文件名完全一致
我曾经犯过的错:在Windows上用VS Code写CMakeLists.txt,保存时用了UTF-8 with BOM编码。结果CMake解析时多了一个不可见字符,报了一堆莫名其妙的错误。后来我学乖了,所有CMake文件一律用UTF-8无BOM格式保存。
好了,到这里你已经完成了第一个CMake项目。虽然只有三行命令,但整个构建流程已经跑通了。后面我们会在这个基础上,一步步加入更多功能。