makefile 自动生成依赖性

本文介绍如何利用C/C++编译器的-M或-MM选项自动生成Makefile中的依赖关系,避免手动维护依赖项的繁琐和错误,通过将自动生成的依赖关系存储在.d文件中,并在Makefile中包含这些文件,实现依赖关系的自动化管理和更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在 Makefile 中, 我们的依赖关系可能会需要包含一系列的头文件,比如, 如果我们的 main.c
中有一句“#include “defs.h””,那么我们的依赖关系应该是:
main.o : main.c defs.h
但是,如果是一个比较大型的工程,你必需清楚哪些 C 文件包含了哪些头文件,并且,
你在加入或删除头文件时,也需要小心地修改 Makefile,这是一个很没有维护性的工作。
为了避免这种繁重而又容易出错的事情,我们可以使用 C/C++编译的一个功能。大多数的
C/C++编译器都支持一个“-M”的选项,即自动找寻源文件中包含的头文件,并生成一个依
赖关系。例如,如果我们执行下面的命令:
cc -M main.c
其输出是:
main.o : main.c defs.h
于是由编译器自动生成的依赖关系,这样一来,你就不必再手动书写若干文件的依赖关
系,而由编译器自动生成了。需要提醒一句的是,如果你使用 GNU 的 C/C++编译器,你得用
“-MM”参数,不然,“-M”参数会把一些标准库的头文件也包含进来。
gcc -M main.c 的输出是:
main.o: main.c defs.h /usr/include/stdio.h /usr/include/features.h
/usr/include/sys/cdefs.h /usr/include/gnu/stubs.h
/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stddef.h
/usr/include/bits/types.h /usr/include/bits/pthreadtypes.h
/usr/include/bits/sched.h /usr/include/libio.h
/usr/include/_G_config.h /usr/include/wchar.h
/usr/include/bits/wchar.h /usr/include/gconv.h
/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stdarg.h
/usr/include/bits/stdio_lim.h
gcc -MM main.c 的输出则是:
main.o: main.c defs.h
那么,编译器的这个功能如何与我们的 Makefile 联系在一起呢。因为这样一来,我们
的 Makefile 也要根据这些源文件重新生成, 让 Makefile 自已依赖于源文件?这个功能并不
现实,不过我们可以有其它手段来迂回地实现这一功能。GNU 组织建议把编译器为每一个源
文件的自动生成的依赖关系放到一个文件中,为每一个“name.c”的文件都生成一个
“name.d”的 Makefile 文件,[.d]文件中就存放对应[.c]文件的依赖关系。于是,我们可
以写出[.c]文件和[.d]文件的依赖关系,并让 make 自动更新或自成[.d]文件,并把其包含
在我们的主 Makefile 中,这样,我们就可以自动化地生成每个文件的依赖关系了。
这里,我们给出了一个模式规则来产生[.d]文件:
%.d: %.c
@set -e; rm -f $@;
$(CC) -M $(CPPFLAGS) $< > @.@.@.$KaTeX parse error: Undefined control sequence: \ at position 3: ; \̲ ̲sed 's,\($*\)\.…KaTeX parse error: Can't use function '$' in math mode at position 4: > $̲@; \ rm -f $@.KaTeX parse error: Can't use function '$' in math mode at position 37: …于[.c]文件,“rm -f $̲@”的意思是删除所有 的目标,…$$”意为一个随机编号,第二行生成的文件有可能是“name.d.12345”,第
三行使用 sed 命令做了一个替换,关于 sed 命令的用法请参看相关的使用文档。第四行就是
删除临时文件。
总而言之,这个模式要做的事就是在编译器生成的依赖关系中加入[.d]文件的依赖,即
把依赖关系:
main.o : main.c defs.h
转成:
main.o main.d : main.c defs.h
于是,我们的[.d]文件也会自动更新了,并会自动生成了,当然,你还可以在这个[.d]
文件中加入的不只是依赖关系,包括生成的命令也可一并加入,让每个[.d]文件都包含一个
完赖的规则。一旦我们完成这个工作,接下来,我们就要把这些自动生成的规则放进我们的
主 Makefile 中。 我们可以使用 Makefile 的“include”命令,来引入别的 Makefile 文件(前
面讲过),例如:
sources = foo.c bar.c
include (sources:.c=.d)上述语句中的“(sources:.c=.d) 上述语句中的“(sources:.c=.d)(sources:.c=.d)”中的“.c=.d”的意思是做一个替换,把变量
$(sources)所有[.c]的字串都替换成[.d],关于这个“替换”的内容,在后面我会有更为详
细的讲述。当然,你得注意次序,因为 include 是按次来载入文件,最先载入的[.d]文件中
的目标会成为默认目标

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值