第一个CMake项目:从零开始构建你的第一个程序
说实话,我见过太多人一上来就扎进CMake的复杂语法里,结果被各种变量、函数搞得晕头转向。其实CMake没那么玄乎——它本质上就是个「项目描述文件」。今天我们就从最基础的东西开始,亲手搭一个能跑起来的C++项目。
CMakeLists.txt:项目的「身份证」
每个CMake项目都离不开一个叫 CMakeLists.txt 的文件。这名字是固定的,大小写都不能错。我刚开始用CMake时,就因为手滑写成了 CMakeList.txt(少了个s),结果折腾了半天才发现问题。
这个文件放在项目的根目录下,CMake就是靠它来理解你的项目结构。说白了,它就是一份「说明书」——告诉CMake:你的项目叫什么、用什么语言、需要编译哪些源文件。
cmake_minimum_required:版本兼容的「安全网」
每个 CMakeLists.txt 的第一行,我建议都写上 cmake_minimum_required。为什么?因为不同版本的CMake,行为可能有差异。我曾经接手过一个老项目,它用的是CMake 2.8的语法,而我本地装的是3.20,结果一堆警告和兼容性问题。
cmake_minimum_required(VERSION 3.10)
这行命令告诉CMake:低于3.10版本的,就别来碰我的项目了。它会在构建前检查版本,不满足就直接报错退出。我个人习惯把这个版本号设得稍微保守一点——比如你实际用3.20,但写3.15,这样别人用稍旧一点的CMake也能编译。
project():给你的项目起个名字
接下来就是 project() 命令。它做的事情比你想的要多:
- 定义项目名称
- 设置语言(C、CXX、Fortran等)
- 自动创建一些有用的变量,比如
PROJECT_NAME、PROJECT_SOURCE_DIR
project(HelloWorld LANGUAGES CXX)
这里我指定了语言为 CXX(也就是C++)。如果你不写 LANGUAGES,CMake默认会检测C和C++。我个人建议显式写出来,这样更清晰,也避免不必要的检测开销。
你想想看,如果你的项目只用C++,却让CMake去检测C编译器,是不是有点浪费?
add_executable():把源文件变成可执行程序
核心命令来了——add_executable()。它的作用就是:把一堆源文件编译成一个可执行文件。
add_executable(hello main.cpp)
第一个参数是目标名称(也就是生成的可执行文件名),后面跟的是源文件列表。你可以写多个源文件:
add_executable(hello main.cpp utils.cpp logger.cpp)
嗯,这里要注意:源文件路径是相对于 CMakeLists.txt 所在目录的。如果你把源文件放在 src/ 子目录下,就要写成 src/main.cpp。
完整的CMakeLists.txt:把一切串起来
好了,我们把上面这些拼在一起,就是一个完整的、能工作的CMake项目了:
cmake_minimum_required(VERSION 3.10)
project(HelloWorld LANGUAGES CXX)
add_executable(hello main.cpp)
就这么三行。真的,一个最简单的CMake项目,三行就够了。我当年第一次看到这个时还不敢相信——就这么简单?
构建与运行:让代码跑起来
有了 CMakeLists.txt 和源文件,接下来就是构建了。CMake推荐使用「外部构建」——也就是在项目目录外建一个 build 文件夹,在里面执行构建。这样做的好处是:所有临时文件都集中在 build 里,项目根目录干干净净。
步骤很简单:
- 创建并进入
build目录 - 运行
cmake ..生成构建系统 - 运行
cmake --build .编译项目
mkdir build
cd build
cmake ..
cmake --build .
执行完这些,你会在 build 目录下看到一个可执行文件(Linux/macOS下叫 hello,Windows下叫 hello.exe)。运行它:
./hello
如果一切顺利,你会看到程序输出。嗯,就这么简单。
CMakeLists.txt 里加上 set(CMAKE_EXPORT_COMPILE_COMMANDS ON),这样CMake会生成一个 compile_commands.json 文件,很多代码补全工具(比如clangd)都需要它。
知识体系一览
下面这张图把本章的核心逻辑串起来了——从 CMakeLists.txt 到最终的可执行文件,每一步都清晰可见:
避坑指南:我踩过的几个坑
讲几个我实际遇到过的问题,你遇到了可以少走弯路:
- 源文件路径写错了:CMake报错说找不到文件。检查一下路径是不是相对于
CMakeLists.txt的。 - 忘记创建 build 目录:直接在项目根目录运行
cmake也可以,但会把临时文件散落一地。我建议养成外部构建的习惯。 - cmake_minimum_required 版本太低:比如你写了
VERSION 2.8,但用了3.0才有的语法,CMake会默默忽略一些特性。我曾经因为这个排查了半天。
核心要点回顾:
- 每个CMake项目必须有一个
CMakeLists.txt cmake_minimum_required确保版本兼容project()定义项目元信息add_executable()把源文件变成可执行程序- 使用外部构建(build目录)保持项目整洁
好了,到这里你已经掌握了CMake最核心的「三板斧」。别看简单,这三个命令能覆盖你80%的日常需求。下一节我们会深入目标属性的世界——那才是CMake真正强大的地方。
公众号:蓝海资料掘金营,微信deep3321