Makefile中自动生成头文件依赖

为什么需要自动生成头文件依赖?

  编译单个源文件时,需要获取文件中包含的头文件的信息,但是一般的Makefile不会在规则中明确写明文件依赖的头文件,所以单独修改头文件后,不会导致包含头文件的源文件重新编译。如果每次手动的添加头文件依赖,又会非常的繁琐,所以需要一种自动生成依赖的方法。

编译器中神奇的选项

  • 使用$(CC)中的-M命令就可以完美的解决问题,因为-M选项可以将源文件依赖的所有头文件,自动解析出来。
  • 例子:在当前路径下,编辑test.c和test.h文件,test.c如下所示,test.h为空
#include <stdio.h>
#include "test.h"

int main()
{
	return 0;
}
  • 运行命令:gcc -M test.c,输出如下:
test.o: test.c /usr/include/stdc-predef.h /usr/include/stdio.h 
 /usr/include/features.h /usr/include/sys/cdefs.h 
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h 
 /usr/include/gnu/stubs-64.h 
 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h 
 /usr/include/bits/types.h /usr/include/bits/typesizes.h 
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h 
 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stdarg.h 
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h test.h  
  • 运行命令:gcc -MM test.c,输出如下:
test.o: test.c test.h  
  • 结论:gcc -MM 命令可以自动生成源文件对头文件的依赖关系,且剔除掉库里面的头文件

解决方法

%.d: %.c
    @set -e; 
    rm -f $@; 
    $(CC) -MM $(CPPFLAGS) $< > $@.$$$$; 
    sed 's,($*).o[ :]*,1.o $@ : ,g' < $@.$$$$ > $@; 
    rm -f $@.$$$$
  • set -e : 后续命令只要执行失败,直接结束全部流程,返回
  • rm -f $@ : 删除上一次编译的残留文件
  • $(CC) -MM $(CPPFLAGS) $< > $@.$$$$ : 将生成的依赖关系输出到指定的目录中,其中$$$$表示一个随机数,防止文件名重复
  • sed 's,($*).o[ :]*,1.o $@ : ,g' < $@.$$$$ > $@ : ;利用sed命令,将xxx.d添加到规则中的目标里面,形成多目标,如:将 main.o : main.o mian.h 变成main.o main.d : main.o mian.h。目的:头文件更新后,d文件也需要同步更新
  • rm -f $@.$$$$ : 删除中间文件

提示:上述方法中隐含了,目标相同的多条规则会自动进行合并的机制,所以规则的目标一定要相同,才能使得原来的编译规则(%.c:%.o)中添加对头文件的依赖。

原文地址:https://www.cnblogs.com/chusiyong/p/11385221.html