文件,并把这个文件作为最终的目标文件。
3. 如果 edit 文件不存在,或是 edit 所依赖的后面的 .o 文件的文件修改时间要比 edit 这个文件新,
那么,他就会执行后面所定义的命令来生成 edit 这个文件。
4. 如果 edit 所依赖的.o 文件也存在,那么 make 会在当前文件中找目标为.o 文件的依赖性,如果
找到则再根据那一个规则生成.o 文件。(这有点像一个堆栈的过程)
5. 当然,你的 C 文件和 H 文件是存在的啦,于是 make 会生成 .o 文件,然后再用 .o 文件生命
make 的终极任务,也就是执行文件 edit 了。
这就是整个 make 的依赖性,make 会一层又一层地去找文件的依赖关系,直到最终编译出第一个目
标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么 make 就会直接退
出,并报错,而对于所定义的命令的错误,或是编译不成功,make 根本不理。make 只管文件的依
赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
通过上述分析,我们知道,像 clean 这种,没有被第一个目标文件直接或间接关联,那么它后面所
定义的命令将不会被自动执行,不过,我们可以显示要 make 执行。即命令——“make clean”,以此
来清除所有的目标文件,以便重编译。
于是在我们编程中,如果这个工程已被编译过了,当我们修改了其中一个源文件,比如 file.c,那
么根据我们的依赖性,我们的目标 file.o 会被重编译(也就是在这个依性关系后面所定义的命令),
于是 file.o 的文件也是最新的啦,于是 file.o 的文件修改时间要比 edit 要新,所以 edit 也会被重新链
接了(详见 edit 目标文件后定义的命令)。
而如果我们改变了“command.h”,那么,kdb.o、command.o 和 files.o 都会被重编译,并且,edit 会
被重链接。
1.4 makefile 中使用变量
在上面的例子中,先让我们看看 edit 的规则:
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
我们可以看到[.o]文件的字符串被重复了两次,如果我们的工程需要加入一个新的 [.o]文件,那么我
们需要在两个地方加(应该是三个地方,还有一个地方在 clean 中)。当然,我们的 makefile 并不
复杂,所以在两个地方加也不累,但如果 makefile 变得复杂,那么我们就有可能会忘掉一个需要加
入的地方,而导致编译失败。所以,为了 makefile 的易维护,在 makefile 中我们可以使用变量。
makefile 的变量也就是一个字符串,理解成 C 语言中的宏可能会更好。
比如,我们声明一个变量,叫 objects, OBJECTS, objs, OBJS, obj, 或是 OBJ,反正不管什么啦,只要
能够表示 obj 文件就行了。我们在 makefile 一开始就这样定义:
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
于是,我们就可以很方便地在我们的 makefile 中以“$(objects)”的方式来使用这个变量了,于是我们
的改良版 makefile 就变成下面这个样子:
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h