Makefile学习之路(4) — 添加头文件依赖
一、编写代码
编写如下源文件和头文件:
提示编写Makefile如下:
hello : hello.o william.o
gcc $^ -o hello
hello.o : hello.c
gcc -c hello.c -o hello.o -I.
william.o : william.c
gcc -c william.c -o william.o -I.
clean :
rm *.o hello -rf
二、make编译
我们使用make命令进行编译,然后执行,如下所示
接下啦我们修改william.h
中age的宏定义为22,再次编译,执行
可以看到,执行make编译失败,因为Makefile中并没有对william.h
的依赖。
三、添加头文件依赖
在Makefile文件中添加一条规则
这条规则只有目标和依赖,没有命令,并且和如下规则是同一个目标
william.o : william.c
gcc -c $< -o $@ -I.
对于多规则同目标文件是只有描述的
Makefile 中,一个文件可以作为多个规则的目标出现。这种情况时,此目标文件的所有依赖文件将会被合并成此目标一个依赖文件列表,其中任何一个依赖文件比目标更新(比较目标文件和依赖文件的时间戳)时, make 将会执行特定的命令来重建这个目标。
对于一个多规则的目标,重建此目标的命令只能出现在一个规则中(可以是多条命令)。如果多个规则同时给出重建此目标的命令, make将使用最后一个规则所以的命令,同时提示错误信息(一个特殊的例外是:使用“.”开头的多规则目标文件,可以在多个规则中给出多个重建命令。这种方式只是为了和其他版本make进行兼容,一般在GNU make中应该避免使用这个功能)。
所以当william.h
有更新后,会执行如下规则的命令,重新生成william.o
文件
我们再次执行make命令,可以看到,make执行编译成功,且age值也更新了。
四、优化头文件依赖
使用gcc的-M
参数可以打印出一个源文件的所有文件依赖,如下所示,其中除了william.c和william.h外都是标准库文件
使用-MM
参数可以打印出除标准以外的所有文件依赖,如下所示
如果可以将这个信息直接添加到Makefile中,那么就非常方便了,刚好gcc提供-MF
和-MMF
命令来帮助使用
参考文章:
使用如下命令,我们可以得到一个依赖文件william.o.d
,打开后如下所示
所以我们将该文件包含Makefile中即可得到我们自动添加依赖的效果,修改Makefile如下
hello : hello.o william.o
gcc $^ -o hello
hello.o : hello.c
gcc -c hello.c -o hello.o -I. -MMD -MF hello.o.d
william.o : william.c
gcc -c william.c -o william.o -I. -MMD -MF william.o.d
-include william.o.d
-include hello.o.d
clean :
rm *.o hello -rf
五、优化Makefile
使用变量通配符和函数优化Makefile如下所示
OBJECTS = hello.o william.o
dep_files := $(patsubst %,.%.d, $(OBJECTS))
dep_files := $(wildcard $(dep_files))
hello : $(OBJECTS)
gcc $^ -o hello
%.o : %.c
gcc -c $< -o $@ -I. -MMD -MF .$@.o.d
william.o : william.c
gcc -c william.c -o william.o -I. -MMD -MF william.o.d
-include dep_files
clean :
rm *.o *.o.d hello -rf