- 前言
- 简单使用示范
- 运行原理
- [ @ \^在makefile 的含义](# @ ^在makefile 的含义)
- makefile完整写法
前言
前面我们学习了vim的使用,直到vim是一个文本编辑器,那么要形成可执行程序还需要我们手动编译,这是一个相当繁琐的步骤。因此需要一些工具来简化这个步骤。
简单使用示范
首先我们需要清楚,make是一个命令而Makefile是一个文件。
构建
首先我们先编写一个code.c文件:

然后创建一个makefile(或Makefile)文件,在里面写入如下内容:

注意此时我们的文件仅有:
shell
[zhangwho@VM-0-2-centos code]$ ll
total 8
-rw-rw-r-- 1 zhangwho zhangwho 463 Dec 4 18:17 code.c
-rw-rw-r-- 1 zhangwho zhangwho 36 Dec 4 18:21 makefile
运行make之后:
shell
[zhangwho@VM-0-2-centos code]$ make
gcc -o myexe code.c
[zhangwho@VM-0-2-centos code]$ ll
total 20
-rw-rw-r-- 1 zhangwho zhangwho 463 Dec 4 18:17 code.c
-rw-rw-r-- 1 zhangwho zhangwho 36 Dec 4 18:21 makefile
-rwxrwxr-x 1 zhangwho zhangwho 8360 Dec 4 18:24 myexe
可以看到自动生成了myexe的可执行程序.
尝试运行:
shell
[zhangwho@VM-0-2-centos code]$ ./myexe
hello Linux! M=100
hello Linux! M=100
hello Linux! M=100
非常完美!
清理
我们现在还可以给makefile附上一些清理临时文件的功能:

尝试运行make clean:
shell
[zhangwho@VM-0-2-centos code]$ make clean
rm -f myexe
[zhangwho@VM-0-2-centos code]$ ll
total 8
-rw-rw-r-- 1 zhangwho zhangwho 463 Dec 4 18:17 code.c
-rw-rw-r-- 1 zhangwho zhangwho 68 Dec 4 18:27 makefile
直接将myexe删除了!
运行原理
makefile

学习了如何使用make之后,我们来看看makefile的构成。
首先我们将第一行称为依赖关系,第二行称为依赖方法。
其中第一行':'后的部分称为依赖文件列表,可以有多个文件,按照空格分割,如:code.c test.c love.c
':'前的称为目标文件
从语法上来讲,第二行的依赖方法必须以Tab开头而非Space。
make运行过程
- 首先我们输入make命令
- make会在当前目录下找名字叫"Makefile"或"makefile"的文件。
- 然后make根据makefile的内容完成编译或清理工作。
make clean
前面我们已经了解make会默认生成myexe的目标文件,那么clean和PHONY又是什么呢?
首先我们需要明确一个概念:clean也是目标文件,虽然说运行这个命令没有形成什么文件就是了/
并且clean他是不依赖于任何文件的!
那么我们很容易想到,make命令会默认生成第一个目标文件。
因此呢,我们的make还可以像这样调用:
shell
[zhangwho@VM-0-2-centos code]$ make myexe
gcc -o myexe code.c
.PHONY
那么.PHONY又是什么呢?
别急我们再执行一次make看看:
shell
[zhangwho@VM-0-2-centos code]$ make
make: `myexe' is up to date.
holy shit!我们的make文件被拦截了。因为此时目标文件已经是最新的了,主要是上次make之后,依赖文件没有更新。如果此时我们修改一下依赖文件:
shell
[zhangwho@VM-0-2-centos code]$ ll code.c
-rw-rw-r-- 1 zhangwho zhangwho 463 Dec 4 18:17 code.c
[zhangwho@VM-0-2-centos code]$ touch code.c
[zhangwho@VM-0-2-centos code]$ ll code.c
-rw-rw-r-- 1 zhangwho zhangwho 463 Dec 4 18:48 code.c
我们用touch命令修改了依赖文件的acm时间,然后看看能不能make吧:
shell
[zhangwho@VM-0-2-centos code]$ make
gcc -o myexe code.c
可以看到此时就可以make了。
也就是make指令会自动检索依赖文件是否更改,如果没有就不给你执行.
像clean都没有依赖文件,那就从头到尾只能执行一次咯!
因此为了让目标文件能一直生成而不依赖于依赖文件是否改变,仅需在前面加上 .PHONY 列表就可以了。
当然我们也可以让myexe一直生成,就是没什么意义罢了
为什么makefile对最新形成的目标文件,默认不重新形成?
简单来说就是为了提高编译效率。
当写的项目非常大的时候,一个目标文件想要重新编译就会带动其他所有目标文件编译。这是非常消耗资源的,因此默认最新形成的不重新编译。
那么这是怎么做到的?
上面已经提到了,就是看依赖文件和目标文件的acm时间。
如果目标文件的生成时间晚于依赖文件的修改时间,自然说明目标文件是最新的。
$ @ ^在makefile 的含义
首先@可以代表目标文件,^代表所有依赖文件,$的含义就是提取内容。因此我们上面的makefile符号还可以这样写:

实则是一样的效果哦!
makefile完整写法
前面我们不是定义了一个make clean来清理myexe吗,有没有读者觉得这多少有点多余了,毕竟只需要rm myexe即可,还比make clean方便。
实际上是我们的makefile没写全,完整的写法如下:

简单使用下:
shell
[zhangwho@VM-0-2-centos code]$ ls
code.c makefile
[zhangwho@VM-0-2-centos code]$ make
gcc -E -o code.i code.c
gcc -S -o code.s code.i
gcc -c -o code.o code.s
gcc -o code.exe code.o
[zhangwho@VM-0-2-centos code]$ ls
code.c code.exe code.i code.o code.s makefile
[zhangwho@VM-0-2-centos code]$ make clean
rm -f code.i code.o code.s code.exe
[zhangwho@VM-0-2-centos code]$ ls
code.c makefile
可以看到我们的make执行逻辑是在找到依赖关系链中的已存在的依赖文件,然后一次性执行这些依赖关系。类似于递归的实现。
makefile的变量
每次写makefile都要写一堆重复的简单的工作是不是很无趣,有没有办法实现一个模板,然后简单套一下目标文件名和依赖文件名呢?
有的兄弟,有的!
这时候先看用法:

非常直观的用法吧,这时候我们只要将dest和src指向的名称改为目标文件和依赖文件就完成makefile的编写咯。
不显示执行的依赖方法
我们没make一下就会显示执行了什么依赖方法。像这样:
shell
[zhangwho@VM-0-2-centos code]$ make
gcc -o code.exe code.c
多少有点缺少逼格。
为了去掉这些提示,我们只需在每个依赖方法前加上@符号即可:

shell
[zhangwho@VM-0-2-centos code]$ make clean
[zhangwho@VM-0-2-centos code]$ ls
code.c makefile
[zhangwho@VM-0-2-centos code]$ make
[zhangwho@VM-0-2-centos code]$ ls
code.c code.exe makefile
是不是一下就逼格上来了。
多行依赖方法
前面我们的makefile里面的每个依赖关系都只对应一个依赖方法,但这不是必要的。
实际上我们可以写多个依赖方法:

shell
[zhangwho@VM-0-2-centos code]$ make
echo "compiler code.c to code.exe"
compiler code.c to code.exe
可以看到,一下子执行了多个命令哦。