博主介绍:程序喵大人
- 35 - 资深C/C++/Rust/Android/iOS客户端开发
- 10年大厂工作经验
- 嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手
- 《C++20高级编程》《C++23高级编程》等多本书籍著译者
- 更多原创精品文章,首发gzh,见文末
- 👇👇记得订阅专栏,以防走丢👇👇
😉C++基础系列专栏
😃C语言基础系列专栏
🤣C++大佬养成攻略专栏
🤓C++训练营
👉🏻个人网站
简单跟大家介绍下CMake的基本使用,掌握这几个知识点你应该可以使用CMake成功构建一个小项目。
在学习CMake之前,我们首先要掌握如何使用命令行构建程序,比如下面这个程序:
cpp
// test.cc
#include <iostream>
int main() {
#ifdef HELLO_WORLD
std::cout << HELLO_WORLD << "\n";
#endif
std::cout << "main \n";
}
这一个简单的源文件,如何使用clang构建?
可以这样:
bash
clang++ test.cc -std=c++14 -DHELLO_WORLD=2
如果编译链接成功,会自动在当前目录生成名为a.out的可执行文件,运行时直接./a.out即可,也可以使用-o指定生成可执行文件的名字。
那上面的命令代表什么意思?
clang++不用多说。test.cc表示源文件的名字。-std=C++14表示使用的C++标准,上面我使用的是C++14,你也可以改为使用C++11或C++17或20等。-D表示定义一个宏,-DHELLO_WORLD=2表示定义了一个HELLO_WORLD的宏,它的值是2。
那如果程序复杂点呢,比如这样:

在另一个单独的头文件func.h中声明func,同时在另一个源文件中定义它的实现,这种程序怎么编译?
bash
clang++ test.cc func.cc -std=c++14 -DHELLO_WORLD=2
直接把func.cc加进去即可。
另外,大家平时编译过程中可能会遇到找不到头文件的编译失败问题,比如找不到func.h,那怎么解决?
应该在编译时指定源文件中引用的头文件所在的目录,比如func.h在目录funch中,那怎么指定目录?可以使用-I,这里是大写的I(i),示例如下:
bash
clang++ test.cc func.cc -std=c++14 -I funch -DHELLO_WORLD=2
还有个情况,我们经常会引用一些第三方库,比如我在程序中引用了libxxx.a,它在xxxdir目录中,那怎么链接这个库,这里有两块需要指定,一个是指定链接库所在的目录(使用-L),一个是指定链接库的名字(使用-l,小写的L),可以这样使用:
bash
clang++ test.cc func.cc -std=c++14 -I funch -L xxxdir -lxxx -DHELLO_WORLD=2
还有个情况,比如我还想添加一些编译参数,那可以直接在命令行后面添加:
bash
clang++ test.cc func.cc -std=c++14 -I funch -L xxxdir -lxxx -DHELLO_WORLD=2 -Werror -Wall -fpic
通过上面的命令行构建程序,你应该明白了以下几点:
- 如何指定参与编译的源文件
- 如何设置C++标准
- 如何设置并添加编译参数
- 如何定义宏
- 如何指定头文件目录
- 如何指定链接库目录
- 如何指定要链接哪个库
掌握了上面几点后,再学习CMake就简单了,其实CMake到最后也是会变成命令行来执行。
使用CMake,都需要有个CMakeLists.txt文件,可以在这个文件里添加内容,比如要构建上面的程序,可以这样写CMakeLists.txt:

第1行的cmake_minimum_required表示CMake要求的最低版本号,如果你的CMake用到了高版本特有的功能,需要指定版本号要求用户升级才可以使用。
第2行的project(xxx)表示项目的名字是xxx,项目编译链接生成的程序名字就会叫xxx。
第3行的add_definitions可以用于定义某个宏。
也可以使用第8行和第9行的set(CMAKE_CXX_FLAGS),无脑在后面添加参数,就像命令行一样。
include_directories用于指定头文件目录,类似于命令行中的-I。
link_directories用于指定链接库目录,类似于命令行中的-L。
第14行和第15行的set用于定义变量,而解析变量则使用美元符。
第17行的add_executable用于定义构建可执行程序,指定源文件列表。
第18行的target_link_libraries用于指令链接哪些库,类似于命令行中的-l。
前面说过CMake到最后也会变成命令行去执行,想要看到详细信息可以打开对应的VERBOSE,就是第4行。那现在执行一下,一般使用CMake都会新建一个build目录,用做工作目录,因为会生成很多中间文件,那我们执行一下:
bash
mkdir build
cd build
cmake ../
make
为什么有cmake ../然后make,因为make命令是通过Makefile来构建的,它只识别Makefile。而cmake ..就是识别上一级目录中的CMakeLists.txt然后在当前build目录中生成了一个Makefile,供make识别:
这是cmake后的产物:

然后再执行下make:

因为我打开了VERBOSE,所以这里可以看到详细的命令信息,你也完全可以复制上面的命令来执行,也可以生成可执行程序的。
关于cmake,就简单介绍到这里,有问题欢迎留言讨论哈。
码字不易,欢迎大家点赞,关注,评论,谢谢!