3. 规则
要学会使用 Makefile 首先你要了解规则和定义规则。本节课我们来学习规则定义的语法和用法。
我们以编译 C 语言的应用程序为例。首先我们使用编辑器编写一个 C 语言源文件 hello.c
内容如下:
文件: hello.c
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello World!\n");
return 0;
}
下面是在我的电脑上手动进行编译成可执行程序 hello 并进行运行的方法。
weimingze@mzstudio:~$ ls
hello.c
weimingze@mzstudio:~$ gcc -o hello hello.c
weimingze@mzstudio:~$ ls
hello hello.c
weimingze@mzstudio:~$ ./hello
Hello World!
注:
ls命令是列出当前文件夹下所有的文件。
gcc -o hello hello.c是编译hello.c并输出为hello可执行程序。
./hello是运行 编译后生成的hello程序文件。
可见,上述 gcc -o hello hello.c 的目标是 使用 hello.c 生成 hello。
下面我们把上述编译规则写入 Makefile 文件,然后使用 make 命令进行编译。
先来看 规则语法:
目标文件1 [目标文件2]: [依赖文件1 依赖文件2 ...]
<制表符>命令1
<制表符>命令2
...
或者
目标文件1 [目标文件2]: [依赖文件1 依赖文件2 ...] ; 命令1
<制表符>命令2
...
说明:
[]表示其中的内容可以省略。- 冒号(
:) 是目标文件列表和依赖文件列表的分隔符。 - 目标文件是要生成的文件,可以是一个或多个(大多只有一个),用空格分隔开,如:
hello。- 当一个规则含有多个目标时,会为每个目标单独执行相应的命令,各个目标共享依赖。自动变量
$@表示当前处理的目标(后面会讲)
- 当一个规则含有多个目标时,会为每个目标单独执行相应的命令,各个目标共享依赖。自动变量
- 依赖文件通常是为生成目标文件所需要的文件,可以有零个、一个或多个文件,用空格分隔。如:
hello.c。 - 命令 通常是用来生成目标文件所需要的命令,可以写多条命令,每一条要写在一行内。如:
gcc -o hello hello.c。 - 命令前必须使用制表符(
<tab>键打出来的符号),不能是空格。 - 一个 Makefile 文件中的规则语法可以有多个。如果在使用
make命令时不指定目标文件,则默认执行第一个规则。
示例
文件:Makefile
hello : hello.c
gcc -o hello hello.c
echo "compile complete!"
make 命令的用法
make [目标文件]
Makefile 规则命令的执行顺序
- 先检查目标文件,如果目标文件不存在,则执行此规则对应的命令。
- 如果目标文件存在,则对比目标文件和依赖文件的修改时间,如果目标文件的修改时间只要比其中一个依赖文件的修改时间早(目标文件比较旧),则执行此规则对应的命令。
- 否则放弃执行规则对应的命令。
make 两次执行的结果如下:
weimingze@mzstudio:~$ ls
hello.c Makefile
weimingze@mzstudio:~$ make
gcc -o hello hello.c
echo "compile complete!"
compile complete!
weimingze@mzstudio:~$ ls
hello hello.c Makefile
weimingze@mzstudio:~$ ls -l hello*
-rwxrwxr-x 1 weimingze weimingze 15960 12月 18 21:11 hello
-rw-rw-r-- 1 weimingze weimingze 101 12月 18 19:29 hello.c
weimingze@mzstudio:~$ make
make: “hello”已是最新。
从执行结果可知。Makefile 中只有这一条规则,第一次执行 make 命令时,因为 不存在文件 hello,所以规则对应的命令都执行了,并生成了 hello。此时文件 hello 的修改时间是 12月 18 21:11 比文件 hello.c的修改时间 12月 18 19:29 新,因此第二次在执行 make 命令时,对应的规则命令不会执行。
尝试重新编辑 hello.c 并保存,此时再运行 make 命令,则此规则对应的命令又会重新执行。原因是重新保存 hello.c 文件的同时会更新此文件的修改时间为当前时间。
实验:
完成上述示例程序的编写,尝试使用 touch 命令,修改文件 hello.c 和 hello 的时间,然后再使用 make 命令进行编译,查看规则命令的执行情况。