4. 多规则 Makefile
本节课我们讲解多规则 Makefile 的编写。
上节课使用 gcc -o hello hello.c 命令将 hello .c 编译成 hello 文件看似编译过程是这样的:
+---------+ +-------+
| hello.c | ------------------> | hello |
+---------+ +-------+
而实际编辑过程中会生成目标文件 hello.o,也就是说命令 gcc -o hello hello.c 实际是由 gcc -o hello.o -c hello.c 和 gcc -o hello hello.o 两条命令组合而成。
实际编译过程如下图所示:
+---------+ +---------+ +-------+
| hello.c | --> | hello.o | --> | hello |
+---------+ +---------+ +-------+
我们改写 Makefile 文件如下:
hello : hello.o
gcc -o hello hello.o
hello.o : hello.c
gcc -o hello.o -c hello.c
上述 Makefile 文件中有两个规则,其中规则 hello : hello.o 通过 hello.o 生成 hello;而规则 hello.o : hello.c 则是通过 hello.c 生成 hello.o。在执行 make 命令时,实际执行的是第一个规则。但第一个规则发现没有 hello.o 这个文件,则 make 会再以 hello.o 作为目标来执行第二个规则 hello.o : hello.c。
Makefile 为了生成目标,通常会形成了一个依赖树。这个树中的任何一个文件更新。都会执行对应的规则来生成新的目标。而对于不需要更新的目标则不会执行对应的规则。
执行结果如下:
weimingze@mzstudio:~$ ls
Makefile hello.c
weimingze@mzstudio:~$ make
gcc -o hello.o -c hello.c
gcc -o hello hello.o
weimingze@mzstudio:~$ ls
Makefile hello hello.c hello.o
weimingze@mzstudio:~$ make
make: “hello”已是最新。
可见 执行 make 后,会生成 hello.o 和 hello 这两个文件,两个规则都执行了。
在 使用 Makefile 时,并不是所有的规则都一定会执行。而只有需要更新的目标对应的规则才会执行。如 现在我们使用 rm hello 命令删除最终的目标文件 hello 而保留 hello.o。再次 make 则只会调用 规则 hello : hello.o ,而不会执行规则 hello.o : hello.c。这样可以避免没有必要的更新以节省 make 执行的时间。如:
weimingze@mzstudio:~$ rm hello
weimingze@mzstudio:~$ ls
Makefile hello.c hello.o
weimingze@mzstudio:~$ make
gcc -o hello hello.o
weimingze@mzstudio:~$ ls
Makefile hello hello.c hello.o
生成指定的目标
默认 make 命令会 执行 Makefile 中的第一个规则。我们也可以使用 make 目标文件 的方式来指定执行的第一个规则,如上述程序中我们使用 rm 命令删除 hello 和 hello.o 两个文件,然后只使用 make hello.o 命令来生成 hello.o 而 hello 则不会生成。
执行结果如下:
weimingze@mzstudio:~$ rm hello hello.o
weimingze@mzstudio:~$ ls
Makefile hello.c
weimingze@mzstudio:~$ make hello.o
gcc -o hello.o -c hello.c
weimingze@mzstudio:~$ ls
Makefile hello.c hello.o
通过上述执行结果。可见使用 make 目标文件 的方式可以将 Makefile 中的任意规则当成第一执行规则。
实验:
将上述 Makefile 的两个规则上下颠倒,改写如下:
hello.o : hello.c
gcc -o hello.o -c hello.c
hello : hello.o
gcc -o hello hello.o
使用 make 命令执行的结果是怎样的?如何才能够生成最终的可执行文件 hello 呢?尝试使用命令来验证你的想法。