makefile自动生成依赖关系

简介: 手工编写依赖关系不仅工作量大而且极易出现遗漏,更新也很难及时,修改源或头文件后makefile可能忘记修改。为了解决这个问题,可以用gcc的-M选项自动生成目标文件和源文件的依赖关系。-M选项会把包含的系统头文件以及其所包含的其他系统头文件也找出来了,如果我们不需要输出系统头文件的依赖关系时,可以用-MM选项。

手工编写依赖关系不仅工作量大而且极易出现遗漏,更新也很难及时,修改源或头文件后makefile可能忘记修改。为了解决这个问题,可以用gcc的-M选项自动生成目标文件和源文件的依赖关系。-M选项会把包含的系统头文件以及其所包含的其他系统头文件也找出来了,如果我们不需要输出系统头文件的依赖关系时,可以用-MM选项。

下面我们以一个简单的例子来说明如何自动生成依赖关系:

exm/

     main.c

     s.c

     s.h

makefile文件内容如下:

all:a

src=$(wildcard *.c)

obj:=$(patsubst %.c,%.o,$(src))

ifneq($(MAKECMDGOALS),clean)

-include$(src:.c=.d)

endif

a:$(obj)

gcc$(obj)-o $@

%.d:%.c

set-e;rm -f $@; \

gcc-MM$(CPPFLAGS) $< > $@.

 

; \

 

sed's,$\.o[:]*,\1.o $@ : ,g' < $@.

 

> $@; \

 

rm-f$@.

 

 

%.o:%.c

@echo'Buildingfile: $<'

@echo'Invoking:GCC C Compiler'

gcc-O0-g3 -Wall -c -o "$@" "$<"

@echo'Finishedbuilding: $<'

@echo''

 

其中wildcard作用就是将指定目录下.c文件全部找出,所以这里src=main.cs.c

patsubst作用是把$(src)中的.c全部换为.o,于是obj=main.os.o

include$(src:.c=.d)相当于includemain.ds.d

由于此时这两个文件并不存在,所以会出现下面提示:

makefile:6:main.d:没有那个文件或目录

makefile:6:s.d:没有那个文件或目录

如果不想要这个提示,可以将include替换为-include

尽管一开始找不到.d文件,所以make会报警告。但是make会把include的文件名也当作目标来尝试更新,而这些目标适用模式规则%.d:%c

注意,虽然在Makefile中这个命令写了四行,但其实是一条命令,make只创建一个Shell进程执行这条命令,这条命令分为5个子命令,用;号隔开,并且为了美观,用续行符\拆成四行来写。执行步骤为:

1)set-e命令设置当前Shell进程为这样的状态:如果它执行的任何一条命令的退出状态非零则立刻终止,不再执行后续命令。@表示makefile执行这条命令时不显示出来

2)把原来的.d文件删掉。

3)$<依赖的目标集(即*.c), -MM:表示生成文件依赖关系,$@:表示生成的目标文件(即*.d),$$:表示本身的ProcessID。注意,在Makefile中$有特殊含义,如果要表示它的字面意思则需要写两个$,所以Makefile中的四个$传给Shell变成两个$,两个$在Shell中表示当前进程的id,一般用它给临时文件起名,以保证文件名唯一。

4)这个sed命令比较复杂,就不细讲了,主要作用是查找替换,并加入.d的依赖关系。

5)最后把临时文件删掉。

 

不管是Makefile本身还是被它包含的文件,只要有一个文件在make过程中被更新了,make就会重新读取整个Makefile以及被它包含的所有文件,现在main.dstack.dmaze.d都生成了,就可以正常包含进来了,相当于在Makefile中添了下面规则:

main.omain.d : main.c s.h

s.os.d : s.c s.h

当源或头文件修改时,如果依赖关系发生变化,执行makefile时将更新具有依赖关系的.d文件,而.d文件的更新又促使make重新读取makefile文件,把新的.d文件包括进来,于是新的依赖关系被建立。

除了上面方法外,还可使用GCC的-MMD-MP -MF -MT选项,如下,可起到同样目的:

all:a

src=$(wildcard *.c)

obj:=$(patsubst %.c,%.o,$(src))

ifneq($(MAKECMDGOALS),clean)

-include$(src:.c=.d)

endif

a:$(obj)

gcc$(obj)-o $@

%.o:%.c

@echo'Buildingfile: $<'

@echo'Invoking:GCC C Compiler'

gcc-O0-g3 -Wall -c -fmessage-length=0 -MMD -MP-MF"$(@:%.o=%.d)"-MT"$(@:%.o=%.d)" -o "$@""$<"

@echo'Finishedbuilding: $<'

@echo''

 

目录
相关文章
|
Shell Linux C语言
Makefile基础教程(自动生成依赖关系)
Makefile基础教程(自动生成依赖关系)
375 0
|
Android开发
autojs按钮不可点击
牙叔教程 简单易懂
1232 0
|
11月前
|
关系型数据库 MySQL 数据库
mysql 里创建表并插入数据
【10月更文挑战第5天】
606 1
|
9月前
|
API
Istio 使用ingress和gateway两种方式公开服务
本文档指导您完成Istio网关的部署与配置。首先安装`istiod`(步骤略过)。接着,创建`ingress.yaml`文件,定义Istio入口网关的服务、部署及权限设置,通过`kubectl apply -f ingress.yaml`命令应用。最后,创建Ingress资源,指定主机名、后端服务及TLS配置,实现对外部请求的路由管理。
830 1
|
11月前
|
存储 Python
使用 struct 模块打包/解包二进制数据
使用 struct 模块打包/解包二进制数据
244 2
|
11月前
|
SQL 监控 数据库
SQL语句性能分析技巧与方法
在数据库管理中,分析SQL语句的性能是优化数据库查询、提升系统响应速度的重要步骤
|
11月前
|
SQL 安全 网络安全
网络安全与信息安全:防范措施与加密技术解析
【10月更文挑战第9天】在数字化时代,网络安全与信息安全已成为我们日常生活中不可或缺的一部分。本文将深入探讨网络安全漏洞、加密技术和安全意识等方面的内容,以帮助读者更好地了解和应对网络安全威胁。通过分享相关知识和案例分析,我们希望提高大家对网络安全的认识和重视程度,共同维护一个安全、可靠的网络环境。
796 0
|
Kubernetes 负载均衡 调度
在K8S中,如何实现集群管理?
在K8S中,如何实现集群管理?
|
机器学习/深度学习 并行计算 PyTorch
PyTorch与CUDA:加速深度学习模型训练的最佳实践
【8月更文第27天】随着深度学习应用的广泛普及,高效利用GPU硬件成为提升模型训练速度的关键。PyTorch 是一个强大的深度学习框架,它支持动态计算图,易于使用且高度灵活。CUDA (Compute Unified Device Architecture) 则是 NVIDIA 开发的一种并行计算平台和编程模型,允许开发者直接访问 GPU 的并行计算能力。本文将详细介绍如何利用 PyTorch 与 CUDA 的集成来加速深度学习模型的训练过程,并提供具体的代码示例。
1391 3
|
开发工具 git
解决Git push提交时Permission denied(publickey).Could not read from remote...的问题
解决Git push提交时Permission denied(publickey).Could not read from remote...的问题
829 0