Makefile自动生成头文件依赖
前言
Makefile自动生成头文件依赖是很常用的功能,本文的目的是想尽量详细说明其中的原理和过程。
Makefile模板
首先给出一个本人在小项目中常用的Makefile模板,支持自动生成头文件依赖。
CC = gcc
CFLAGS = -Wall -O
INCLUDEFLAGS =
LDFLAGS =
OBJS = seq.o
TARGETS = test_seq
.PHONY:all
all : $(TARGETS)
test_seq:test_seq.o $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS)
%.o:%.c
$(CC) -o $@ -c $< $(CFLAGS) $(INCLUDEFLAGS)
%.d:%.c
@set -e; rm -f $@; $(CC) -MM $< $(INCLUDEFLAGS) > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
-include $(OBJS:.o=.d)
.PHONY:clean
clean:
rm -f $(TARGETS) *.o *.d *.d.*
基础知识
在进行下一步之前,首先需要了解make的执行步骤:
- 读入Makefile
- 读入被include的其它Makefile
- 初始化Makefile中的变量
- 推导隐晦规则,并分析所有规则
- 为所有目标创建依赖关系链
- 根据依赖关系,决定哪些目标需要重新生成
- 执行生成命令
如何动态生成依赖关系?
从上面make的执行过程中可看出,要动态生成依赖关系,只能利用第2步读入其它Makefile的机制。那么,我们是否可以先把生成的依赖关系保存到文件,然后再把该文件的内容包含进来?
答案是Yes! 只要利用include的机制。
include关键字是用于读入其它Makefile文件。当该文件不存在时,make会寻找是否有生成它的规则,如果有,则执行其生成命令,然后再尝试读入。在include前加减号"-"可以上make忽略其产生的错误,并不输出任何错误信息。
即是说,我们需要提供生成规则文件的规则。例如,我们可以这样动态生成头文件依赖关系:
seq.d : seq.c
@echo “seq.o seq.d : seq.c seq.h" > $@
-include seq.d
当make执行时,Makefile中的内容将是这样子(指内存上的数据):
seq.d : seq.c
@echo “seq.o seq.d : seq.c seq.h" > $@
seq.o seq.d : seq.c seq.h
特别注意的是,由于对seq.c和seq.h的修改需要更新seq.d的内容(因为依赖关系可能已变化),因此seq.d也要在依赖关系的目标列表中。
自动生成头文件依赖
基于上面的例子,现在可以开始讨论如何自动生成头文件依赖。
自动生成依赖关系
大多数c/c++编译器提供了-M选项,可自动寻找源文件依赖的头文件,并生成依赖规则。对于gcc,需要使用-MM选项,否则它会把系统依赖的头文件也包含进来。例如执行下面一个命令:
gcc -MM seq.c
将输出:
seq.o : seq.c seq.h
但我们需要结果是seq.d也要包含在目标列表中,所以还需要对它进行文本处理。因此,上面的例子可改为:
seq.d : seq.c
@set -e; \
gcc -MM $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
-include seq.d
生成规则中的执行命令解释
第一个命令@set -e
。@关键字告诉make不输出该行命令;set -e的作用是,当后面的命令的返回值非0时,立即退出。
那么为什么要把几个命令写在”同一行“(是对于make来说,因为\的作用就是连接行),并用分号隔开每个命令?因为在Makefile这样做才能使上一个命令作用于下一个命令。这里是想要set -e作用于后面的命令。
第二个命令gcc -MM $< > $@.$$$$
, 作用是根据源文件生成依赖关系,并保存到临时文件中。内建变量$<
的值为第一个依赖文件(那seq.c),$$$$
为字符串"$$"
,由于makefile中所有的$字符都是特殊字符(即使在单引号之中!),要得到普通字符$,需要用$$
来转义; 而$$
是shell的特殊变量,它的值为当前进程号;使用进程号为后缀的名称创建临时文件,是shell编程常用做法,这样可保证文件唯一性。
第三个命令作用是将目标文件加入依赖关系的目录列表中,并保存到目标文件。关于正则表达式部分就不说了,唯一要注意的是内建变量$*
,$*
的值为第一个依赖文件去掉后缀的名称(这里即是seq)。
第四个命令是将该临时文件删除。
如果把内建变量都替换成其值后,实际内容是这样子:
seq.d : seq.c
@set -e; \
gcc -MM seq.c > seq.d.$$$$; \
sed 's,\(seq\)\.o[ :]*,\1.o seq.d : ,g' < seq.d.$$$$ > seq.d; \
rm -f seq.d.$$$$
-include seq.d
Makefile的模式匹配
最后,再把Makefile的模式匹配应用上,就完成自动生成头文件依赖功能了:
%.d : %.c
@set -e; \
gcc -MM $@ > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
-include seq.d
参考资料
<跟我一起写Makefile> by 陈晧
GNU make官方文档 http://www.gnu.org/software/make/manual/make.html
Makefile自动生成头文件依赖的更多相关文章
- Makefile中自动生成头文件依赖
为什么需要自动生成头文件依赖? 编译单个源文件时,需要获取文件中包含的头文件的信息,但是一般的Makefile不会在规则中明确写明文件依赖的头文件,所以单独修改头文件后,不会导致包含头文件的源文件重新 ...
- makefile自动生成目标与依赖的关系
有main.c: #include <stdio.h> #include "command.h" int main(int argc, const char *argv ...
- pycharm自动生成头文件注释
1.在file->settings->file and code templates->python script即可自定制pycharm创建文件自动生成的头文件注释信息 2.创建p ...
- makefile自动生成依赖关系
手工编写依赖关系不仅工作量大而且极易出现遗漏,更新也很难及时,修改源或头文件后makefile可能忘记修改.为了解决这个问题,可以用gcc的-M选项自动生成目标文件和源文件的依赖关系.-M选项会把包含 ...
- 用shell脚本新建shell文件并自动生成头说明信息
目标: 新建文件后,直接给文件写入下图信息 代码实现: [root@localhost test]# vi AutoHead.sh #!/bin/bash#此程序的功能是新建shell文件并自动生成头 ...
- 用shell脚本新建文件并自动生成头说明信息
目标: 新建文件后,直接给文件写入下图信息 代码实现: [root@localhost test]# vi AutoHead.sh #!/bin/bash #此程序的功能是新建shell文件并自动生成 ...
- CPLUSPLUS 获得 一个源文件的头文件依赖。即该文件所需要的所有头文件
核心命令:gcc -M *.h.*.cpp 转: 自动处理头文件的依赖关系 http://blog.csdn.net/su_ocean16/article/details/5374696 现在我们的M ...
- makefile自动生成学习
https://www.cnblogs.com/jrglinux/p/6964169.html 关键是如何写Makefile.am 其他的交给 自动工具完成 添加一个 很好的博客 学习下 https ...
- 程序自动生成Dump文件
前言:通过drwtsn32.NTSD.CDB等调试工具生成Dump文件, drwtsn32存在的缺点虽然NTSD.CDB可以完全解决,但并不是所有的操作系统中都安装了NTSD.CDB等调试工具.了解了 ...
随机推荐
- Jquery VailDate初探
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Autolayout的在storyboard警告和错误
警告 控件的frame不匹配所添加的约束, 比如比如约束控件的宽度为100, 而控件现在的宽度是110 错误 缺乏必要的约束, 比如只约束了宽度和高度, 没有约束具体的位置 两个约束冲突, 比如 1个 ...
- C# Unix时间戳转换为时间
在做一些接口的时候,比如返回数据中有一个时间的属性,它的值是使用Unix时间戳表示的,当我们处理它(保存到本地或者格式化前台展示)时需要转换成日期时间,在此就需要根据时间戳转换为日期时间 (注:Uni ...
- Eclipse使用Maven创建Web项目
一.Maven插件下载.jdk下载 1.maven下载地址: http://maven.apache.org/download.cgi 2.jdk下载地址: http://www.oracle.com ...
- ZOJ 2745 01-K Code(DP)(转)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1745 题目大意:一个串由N个字符组成,每个字符是‘0’或者是‘1’, ...
- 【BZOJ3270】【高斯消元】博物馆
Description 有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博物馆.这座博物馆有着特别的样式.它包含由m条走廊连接的n间房间,并且满足可以从任何一 ...
- Android从服务端获取json解析显示在客户端上面
Android从服务端获取json解析显示在客户端上面 百度经验:jingyan.baidu.com 首先说一下Json数据的最基本的特点,Json数据是一系列的键值对的集合,和XML数据来比,Jso ...
- ajax GET和POST请求web api 的几种方式
GET请求 1.无参数get请求 一般get请求有两种写法,一种是 $.get() 一种是$.ajax({type:"get"}), 我个人比较喜欢用后者. 下面例子主要是ge ...
- event的属性
t获取鼠标相对于浏览器左上角的坐标 <div id="dv" style=" width:300px; height:200px; background-color ...
- properties文件的继承(套用)关系
现项目中有多个配置文件分布于/props____def.properties____/env_______def.propertiess_______/dev_______def.properties ...