make 简介
本节阅读量:这一节专门解释 make 和 Makefile。
make 是什么
make 可以先理解成:
|
|
你在第一章目录里运行:
|
|
它会读取当前目录下的:
|
|
然后执行里面写好的编译命令,生成:
|
|
mini 就是这一章的小命令行程序。
一个最小 Makefile
先不看课程代码,先看一个 Hello World。
假设有一个文件叫 hello.cpp:
|
|
如果手动编译,可以运行:
|
|
这条命令的意思是:
|
|
如果写成 Makefile,可以是:
|
|
这里有两行最重要。
第一行:
|
|
可以读成:
|
|
第二行:
|
|
可以读成:
|
|
注意:第二行前面必须是一个 Tab,不是普通空格。这是 Makefile 一个比较古老但必须遵守的规则。
现在运行:
|
|
make 会找到第一个目标 hello,然后执行:
|
|
最后运行:
|
|
会看到:
|
|
所以 Makefile 最核心的形状就是:
|
|
本课程后面的 Makefile 只是这个形状的扩展。
为什么不用每次手写编译命令
第一章真正的编译命令大概长这样:
|
|
这条命令很长,所以我们把它写进 Makefile。以后只要运行:
|
|
就等于让 make 帮你执行那条长命令。
Makefile 里最重要的几行
第一章的 Makefile 大概是:
|
|
先不用学完整的 Makefile 语法。第一遍只看懂几件事:
|
|
还有一行:
|
|
可以先读成:
|
|
为什么要说这个?
make 默认会把目标名当成“要生成的文件名”。比如:
|
|
这里的 mini 确实是一个要生成的文件。
但:
|
|
这里的 clean 不是要生成一个叫 clean 的文件。它只是一个命令入口,意思是“清理生成文件”。
所以写:
|
|
就是告诉 make:
|
|
all 也一样。它只是默认入口,不是真的要生成一个叫 all 的文件。
这里的:
|
|
意思是:
|
|
所以:
|
|
可以读成:
|
|
所以这一行:
|
|
可以读成:
|
|
这一行:
|
|
可以读成:
|
|
编译选项是什么意思
把这行命令拆开看:
|
|
c++ 是 C++ 编译器命令。它负责把 .cpp 源文件编译成可以运行的程序。
-std=c++17 表示使用 C++17 标准。C++ 有不同版本,比如 C++11、C++14、C++17、C++20。本课程使用 C++17,是因为它足够现代,也足够普遍。
-Wall 会让编译器多提醒你一些常见问题。这些提醒不一定会让编译失败,但通常值得看一眼。
-Wextra 会再多打开一些提醒。它比 -Wall 更严格一点,能帮助我们更早发现可疑代码。
-pedantic 表示更严格地按 C++ 标准检查代码。有些编译器支持自己的扩展写法,代码可能能编过,但不一定是标准 C++。加上这个选项后,编译器会尽量提醒你哪些写法不够标准。
-Isrc 表示把 src 目录加入头文件搜索路径。这样代码里就可以写:
|
|
而不是写成更长的相对路径。
$(SOURCES) 是 Makefile 变量,前面已经用:
|
|
把它设置成所有要编译的 .cpp 文件。
-o mini 表示输出文件叫 mini。如果没有这个选项,编译器可能会生成默认名字,例如 a.out。
所以整条命令可以读成:
|
|