自动生成依赖性
一个大型的工程,在加入或删除头文件时,需要小心地改makefile,这是一个很没有维护性的工作。为了避免这种繁重而又容易出错的事情,我们可以使用C语言编译的一个功能。-M选项自动找寻源文件中包含的头文件,并生成一个依赖关系。例子 cc -M main.c,输出是main.o: main.c defs.h。于是由编译器自动生成了依赖关系。如果使用GNU的编译器,得用-MM参数,不然会把标准库的头文件也包含进来。GNU建议把编译器为每个源文件自动生成的依赖关系放到一个文件中,生成一个name.d的文件。
%.d: %.c
@set -e; rm -f $@; \
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
这个规则的意思是,在编译器生成的依赖关系中加入.d文件的依赖,即把依赖关系main.o: main.c defs.h转成main.o main.d: main.c defs.h。于是,我们的.d文件也会自动更新了,并会自动生成了。我们就要把这些自动生成的规则放进我们的主makefile中。我们可以用include命令来引入别的makefile文件。例如:
sources = foo.c bar.c
include $(sources: .c=.d)
书写命令
每条规则中的命令和shell的命令行是一致的。make会按顺序执行命令,每条命令必须以tab开头。除非,命令是紧跟在依赖规则后的分号的。默认的命令行解释器是/bin/sh。
显示命令
通常,make会把要执行的命令行在命令执行前输出到屏幕上。当用@字符在命令行前,那么,这个命令将不被显示出来。如果make执行时,带入-n参数,那么只是显示命令,但不会执行命令。
命令的执行
当规则的目标需要被更新时,make会一条一条的执行后面的命令。如果要让上一条命令的结果应用在下一条命令时,应该使用分号分隔两条命令。
命令出错
为了忽略命令的出错,在命令行前加一个-,标记为不管命令出不出错都认为是成功的。make加入-i参数,那么所有命令都回忽略错误。
嵌套执行make
在一些大型工程中,我们会把不同的模块或是不同功能的源文件放在不同的目录中。可以在每个目录中都书写一个makefile。那么我们总控的makefile可以这样写:
subsystem:
cd subdir && $(MAKE)
总控makefile的变量可以传递到下级makefile中,但是不会覆盖下层的makefile中所定义的变量,除非了指定-e参数。