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
...

说明:

  1. [] 表示其中的内容可以省略。
  2. 冒号(:) 是目标文件列表依赖文件列表的分隔符。
  3. 目标文件是要生成的文件,可以是一个或多个(大多只有一个),用空格分隔开,如:hello
    • 当一个规则含有多个目标时,会为每个目标单独执行相应的命令,各个目标共享依赖。自动变量 $@ 表示当前处理的目标(后面会讲)
  4. 依赖文件通常是为生成目标文件所需要的文件,可以有零个、一个或多个文件,用空格分隔。如:hello.c
  5. 命令 通常是用来生成目标文件所需要的命令,可以写多条命令,每一条要写在一行内。如:gcc -o hello hello.c
  6. 命令前必须使用制表符(<tab> 键打出来的符号),不能是空格。
  7. 一个 Makefile 文件中的规则语法可以有多个。如果在使用 make 命令时不指定目标文件,则默认执行第一个规则。

示例

文件:Makefile

hello : hello.c
    gcc -o hello hello.c
    echo "compile complete!"

make 命令的用法

make [目标文件]

Makefile 规则命令的执行顺序

  1. 先检查目标文件,如果目标文件不存在,则执行此规则对应的命令。
  2. 如果目标文件存在,则对比目标文件和依赖文件的修改时间,如果目标文件的修改时间只要比其中一个依赖文件的修改时间早(目标文件比较旧),则执行此规则对应的命令。
  3. 否则放弃执行规则对应的命令。

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.chello 的时间,然后再使用 make 命令进行编译,查看规则命令的执行情况。