make 构建工具介绍
构建工具通常需要定义依赖、目标和规则。
make
是最常用的构建系统之一,您会发现它通常被安装到了几乎所有基于 UNIX 的系统中。make
并不完美,但是对于中小型项目来说,它已经足够好了。当您执行 make
时,它会去参考当前目录下名为 Makefile
的文件。所有构建目标、相关依赖和规则都需要在该文件中定义,它看上去是这样的:
|
|
这个文件中的指令,即如何使用右侧文件构建左侧文件的规则。或者,换句话说,冒号左侧的是构建目标,冒号右侧的是构建它所需的依赖。缩进的部分是从依赖构建目标时需要用到的一段程序。在 make
中,第一条指令还指明了构建的目的,如果您使用不带参数的 make
,这便是我们最终的构建结果。或者,您可以使用这样的命令来构建其他目标:make plot-data.png
。
规则中的 %
是一种模式,它会匹配其左右两侧相同的字符串。例如,如果目标是 plot-foo.png
, make
会去寻找 foo.dat
和 plot.py
作为依赖。现在,让我们看看如果在一个空的源码目录中执行make
会发生什么?
|
|
make
会告诉我们,为了构建出paper.pdf
,它需要 paper.tex
,但是并没有一条规则能够告诉它如何构建该文件。让我们构建它吧!
|
|
哟,有意思,我们是有构建 plot-data.png
的规则的,但是这是一条模式规则。因为源文件data.dat
并不存在,因此 make
就会告诉您它不能构建 plot-data.png
,让我们创建这些文件:
|
|
当我们执行 make
时会发生什么?
|
|
看!PDF !
如果再次执行 make
会怎样?
|
|
什么事情都没做!为什么?好吧,因为它什么都不需要做。**make 回去检查之前的构建是因其依赖改变而需要被更新。**让我们试试修改 paper.tex
在重新执行 make
:
|
|
注意 make
并没有重新构建 plot.py
,因为没必要;plot-data.png
的所有依赖都没有发生改变。
更多用 make 构建目标参考 Standard Targets (GNU make)。
- 大多数的 makefiles 都提供了 一个名为
clean
的构建目标,这并不是说我们会生成一个名为clean
的文件,而是我们可以使用它清理文件,让 make 重新构建。您可以理解为它的作用是“撤销”所有构建步骤。在上面的 makefile 中为paper.pdf
实现一个clean
目标。您需要将构建目标设置为phony。您也许会发现git ls-files
子命令很有用。其他一些有用的 make 构建目标可以在这里找到; - 指定版本要求的方法很多,让我们学习一下 Rust 的构建系统的依赖管理。大多数的包管理仓库都支持类似的语法。对于每种语法(尖号、波浪号、通配符、比较、乘积),构建一种场景使其具有实际意义;
- Git 可以作为一个简单的 CI 系统来使用,在任何 git 仓库中的
.git/hooks
目录中,您可以找到一些文件(当前处于未激活状态),它们的作用和脚本一样,当某些事件发生时便可以自动执行。请编写一个pre-commit
钩子,它会在提交前执行make paper.pdf
并在出现构建失败的情况拒绝您的提交。这样做可以避免产生包含不可构建版本的提交信息; - 基于 GitHub Pages 创建任意一个可以自动发布的页面。添加一个GitHub Action 到该仓库,对仓库中的所有 shell 文件执行
shellcheck
(方法之一); - 构建属于您的 GitHub action,对仓库中所有的
.md
文件执行proselint
或write-good
,在您的仓库中开启这一功能,提交一个包含错误的文件看看该功能是否生效。