CMake入门教程

博主介绍:程序喵大人

简单跟大家介绍下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,就简单介绍到这里,有问题欢迎留言讨论哈。

码字不易,欢迎大家点赞,关注,评论,谢谢!

相关推荐
十年Java程序媛23 分钟前
Java 面试常问 this、super:构造方法调用顺序避坑
java·开发语言·spring boot·面试·个人开发
yuniko-n42 分钟前
【JUC】内存屏障
java·开发语言
Linux运维技术栈1 小时前
近期 PHP 高危安全风险排查与多环境升级实操
开发语言·安全·php
凯瑟琳.奥古斯特1 小时前
力扣1015C++解法技巧
c++·算法·leetcode·链表·职场和发展
Fnetlink11 小时前
Fnet 云网安 261023
运维·开发语言·网络·人工智能·安全·web安全·php
悠仁さん1 小时前
【算法C++】双指针(一)
数据结构·c++·算法
ESDWAN1 小时前
SD-WAN 主备切换为什么仍会断网?从检测、切换到会话恢复分析
运维·开发语言·网络·php
jimy11 小时前
lvalue、xvalue、prvalue(二):引用是哪一类?
开发语言·c++·1024程序员节
cxyxixiy1 小时前
数智码力:数据核对不用人工比对,Python 快速完成多表格差异校验
开发语言·python·学习
一个风轻云淡1 小时前
从 int $0x80 到 iret:用 gdb 把 getpid 走一遍
linux·c语言·开发语言·汇编