Makefile学习之路(1) — Makefile的引入及规则

Makefile学习之路(1) — Makefile的引入及规则

一、什么是Makefile

在一些有很多源文件的项目工程中使用一个个的gcc命令来编译是非常吃力的,所以我们需要一个工具来管理这些编译过程,这就是make,make是一个应用程序,它根据 Makefile 来做事。
Makefile 负责管理整个编译流程:要编译哪些文件?怎么编译这些文件?怎么把它们链接成一个可执行程序, Makefile 定义了一系列的规则来实现这些管理。

一般来说将 Makefile 文件取名为“ Makefile ” 或“ makefile ” 都可以, 惯例是使用首字母大写的“ Makefile ” 。 也可以使用其他名字,比如 makefile.linux,但你需要用“ -f ”参数指定,示例如下:make -f makefile.linux

Makefile的官方文档:http://www.gnu.org/software/make/manual/make.pdf

二、Makefile的规则

makefile最基本的语法是规则,如下所示:
在这里插入图片描述
如果我们要得到目标文件,那么就要有依赖文件,从依赖文件中得到目标文件的方法就是下一行中TAB键后的命令。
例如我们新建一个Makefile,写入如下内容:


hello : hello.c
	gcc hello.c -o hello

新建一个hello.c文件,并编写以下代码:

#include <stdio.h>

int main(void)
{
    
    
    printf("Hello World!\n");

    return 0;
}

接着执行make命令,可以看到,成功执行了命令,且生成了我们要的可执行程序。
在这里插入图片描述

三、目标生成规则

1)检查规则中的依赖文件是否存在。
2)若依赖文件不存在,则寻找是否有规则用来生成该依赖文件。

我们将hello.c文件修改为hello.txt,再次执行make命令,可以看到,失败了,因为找不到hello.c文件
在这里插入图片描述
接着修改makefile文件如下所示


hello : hello.c
	gcc hello.c -o hello

hello.c : hello.txt
	cp hello.txt hello.c

然后输入make命令,可以看到又再次成功了。这是因为当"依赖"存在时,make会去寻找其他的是否有生成当前依赖文件的规则,如果有,则执行该规则来生成该依赖文件。
在这里插入图片描述
目标生成流程在韦东山老师的文档中有一幅图很好的表示了
在这里插入图片描述

四、目标更新规则

1)检查目标的所有依赖,任何一个依赖有更新时,就要重新生成目标。
2)目标文件比依赖文件更旧,则需要更新。

我们再次输入make,发现提示hello已是最新
在这里插入图片描述
这是因为只有当“依赖”比“目标”新的时候,才会执行它们下面的命令。
我们修改一下c文件,再执行一下make,可以看到,gcc命令再次执行了;但是也只有gcc命令执行了,cp命令并没有执行,这是因为hello.txt并没有比hello.c文件更新,所以cp命令并不执行。
在这里插入图片描述
那我们将hello.txt文件也修改一下,然后执行make命令。可以看到,两个命令都执行了,这是因为执行cp命令后,hello.c文件比hello文件更新了,所以gcc命令也要执行了。
我们也可以看出,即使我们并没有修改hello.c文件,但是他作为了另一条规则的依赖文件,那么这两个规则就有了关联性,make会将后面的规则执行完后来判断当前规则中"目标"和"依赖"的更新时间。
在这里插入图片描述

扫描二维码关注公众号,回复: 12258243 查看本文章

另外,我们将目标文件修改为hello.out


hello.out : hello.c
	gcc hello.c -o hello

可以看到,gcc命令一直在执行,这是因为并没有hello.out文件的生成,所以make认为“依赖”一直比“目标”新,所以命令一直都要执行,这在makefile中被称为伪目标,因为hello.out文件并不生成,但他又在目标文件的位置上。
在这里插入图片描述
同样的,目标更新流程在韦东山老师的文档中有一幅图很好的表示了
在这里插入图片描述

五、规则的执行

直接使用make命令时默认执行第一个规则,如下我们在makeflie添加一条规则
在这里插入图片描述
修改hello.txt,执行make命令,可以看到,touch命令并没有执行生成hello.cpp文件;是因为我们添加的这个规则并没有和第一个规则相关联,所以并不会执行;
在这里插入图片描述
我们用make + 指定目标来执行,可以看到,生成了hello.cpp文件
在这里插入图片描述

六、make clean的由来

上面这个规则有一个漏洞,就是没有hello.txt文件时就不会执行了
在这里插入图片描述
因为下面的命令中并没有用到hello.txt文件,我们将其删去
在这里插入图片描述
执行make命令,可以看到,成功创建了hello.cpp文件,这是因为没有了依赖文件,就不需要依赖了,可以直接执行了
在这里插入图片描述
那么我们就可以编写一个如下规则,从而得到了一个最常见的make clean命令

clean :
	rm -rf hello hello.c

因为他没有依赖文件,所以没有依赖文件的约束,同时执行命令后不会生成目标文件,所以可以一直执行下去,另外,因为他并不和前面的规则关联,所以不用担心在执行其他规则时被执行。
在这里插入图片描述

不过他还有一个漏洞就是,当我们人为的去创建一个clean文件,
在这里插入图片描述
那有没有什么办法解决呢?我们可以使用一个特殊的标记“.PHONY”来显示的指明他为伪目标,向make说明,不管是否有这个文件,这个目标就是伪目标,都要执行。
在这里插入图片描述
可以看到,即使有clean文件的存在,rm命令也执行了
在这里插入图片描述

七、附录

下一篇:Makefile学习之路(2) — Makefile的变量和通配符

猜你喜欢

转载自blog.csdn.net/qq_38113006/article/details/111798123