自动处理头文件的依赖关系
来源:互联网 发布:微信企业号java 编辑:程序博客网 时间:2024/05/16 07:44
现在我们的Makefile写成这样: 按照惯例,用 接下来的问题是怎么把这些规则包含到Makefile中,GNU 类似于C语言的 一开始找不到 注意,虽然在Makefile中这个命令写了四行,但其实是一条命令, 把原来的 重新生成 这个 最后把临时文件 不管是Makefile本身还是被它包含的文件,只要有一个文件在 如果我在 1、 第一条是把规则 因此 2、由于all: mainmain: main.o stack.o maze.ogcc $^ -o $@main.o: main.h stack.h maze.hstack.o: stack.h main.hmaze.o: maze.h main.hclean:-rm main *.o.PHONY: clean
all
做缺省目标。现在还有一点比较麻烦,在写main.o
、stack.o
和maze.o
这三个目标的规则时要查看源代码,找出它们依赖于哪些头文件,这很容易出错,一是因为有的头文件包含在另一个头文件中,在写规则时很容易遗漏,二是如果以后修改源代码改变了依赖关系,很可能忘记修改Makefile的规则。为了解决这个问题,可以用gcc
的-M
选项自动生成目标文件和源文件的依赖关系:$ gcc -M main.cmain.o: main.c /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-32.h / /usr/lib/gcc/i486-linux-gnu/4.3.2/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/i486-linux-gnu/4.3.2/include/stdarg.h / /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h main.h / stack.h maze.h
-M
选项把stdio.h
以及它所包含的系统头文件也找出来了,如果我们不需要输出系统头文件的依赖关系,可以用-MM
选项:$ gcc -MM *.cmain.o: main.c main.h stack.h maze.hmaze.o: maze.c maze.h main.hstack.o: stack.c stack.h main.h
make
的官方手册建议这样写:all: mainmain: main.o stack.o maze.ogcc $^ -o $@clean:-rm main *.o.PHONY: cleansources = main.c stack.c maze.cinclude $(sources:.c=.d)%.d: %.cset -e; rm -f $@; /$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; /sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.$$$$ > $@; /rm -f $@.$$$$
sources
变量包含我们要编译的所有.c
文件,$(sources:.c=.d)
是一个变量替换语法,把sources
变量中每一项的.c
替换成.d
,所以include
这一句相当于:include main.d stack.d maze.d
#include
指示,这里的include
表示包含三个文件main.d
、stack.d
和maze.d
,这三个文件也应该符合Makefile的语法。如果现在你的工作目录是干净的,只有.c
文件、.h
文件和Makefile
,运行make
的结果是:$ makeMakefile:13: main.d: No such file or directoryMakefile:13: stack.d: No such file or directoryMakefile:13: maze.d: No such file or directoryset -e; rm -f maze.d; /cc -MM maze.c > maze.d.$$; /sed 's,/(maze/)/.o[ :]*,/1.o maze.d : ,g' < maze.d.$$ > maze.d; /rm -f maze.d.$$set -e; rm -f stack.d; /cc -MM stack.c > stack.d.$$; /sed 's,/(stack/)/.o[ :]*,/1.o stack.d : ,g' < stack.d.$$ > stack.d; /rm -f stack.d.$$set -e; rm -f main.d; /cc -MM main.c > main.d.$$; /sed 's,/(main/)/.o[ :]*,/1.o main.d : ,g' < main.d.$$ > main.d; /rm -f main.d.$$cc -c -o main.o main.ccc -c -o stack.o stack.ccc -c -o maze.o maze.cgcc main.o stack.o maze.o -o main
.d
文件,所以make
会报警告。但是make
会把include
的文件名也当作目标来尝试更新,而这些目标适用模式规则%.d: %c
,所以执行它的命令列表,比如生成maze.d
的命令:set -e; rm -f maze.d; /cc -MM maze.c > maze.d.$$; /sed 's,/(maze/)/.o[ :]*,/1.o maze.d : ,g' < maze.d.$$ > maze.d; /rm -f maze.d.$$
make
只创建一个Shell进程执行这条命令,这条命令分为5个子命令,用;
号隔开,并且为了美观,用续行符/
拆成四行来写。执行步骤为:set -e
命令设置当前Shell进程为这样的状态:如果它执行的任何一条命令的退出状态非零则立刻终止,不再执行后续命令。maze.d
删掉。maze.c
的依赖关系,保存成文件maze.d.1234
(假设当前Shell进程的id是1234)。注意,在Makefile中$
有特殊含义,如果要表示它的字面意思则需要写两个$,所以Makefile中的四个$传给Shell变成两个$,两个$在Shell中表示当前进程的id,一般用它给临时文件起名,以保证文件名唯一。sed
命令比较复杂,就不细讲了,主要作用是查找替换。maze.d.1234
的内容应该是maze.o: maze.c maze.h main.h
,经过sed
处理之后存为maze.d
,其内容是maze.o maze.d: maze.c maze.h main.h
。maze.d.1234
删掉。make
过程中被更新了,make
就会重新读取整个Makefile以及被它包含的所有文件,现在main.d
、stack.d
和maze.d
都生成了,就可以正常包含进来了(假如这时还没有生成,make
就要报错而不是报警告了),相当于在Makefile中添了三条规则:main.o main.d: main.c main.h stack.h maze.hmaze.o maze.d: maze.c maze.h main.hstack.o stack.d: stack.c stack.h main.h
main.c
中加了一行#include "foo.h"
,那么:main.c
的修改日期变了,根据规则main.o main.d: main.c main.h stack.h maze.h
要重新生成main.o
和main.d
。生成main.o
的规则有两条:main.o: main.c main.h stack.h maze.h%.o: %.c# commands to execute (built-in): $(COMPILE.c) $(OUTPUT_OPTION) $<
main.o main.d: main.c main.h stack.h maze.h
拆开写得到的,第二条是隐含规则,因此执行cc
命令重新编译main.o
。生成main.d
的规则也有两条:main.d: main.c main.h stack.h maze.h%.d: %.cset -e; rm -f $@; /$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; /sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.$$$$ > $@; /rm -f $@.$$$$
main.d
的内容被更新为main.o main.d: main.c main.h stack.h maze.h foo.h
。main.d
被Makefile包含,main.d
被更新又导致make
重新读取整个Makefile,把新的main.d
包含进来,于是新的依赖关系生效了。
- 自动处理头文件的依赖关系
- 自动处理头文件的依赖关系
- 自动处理头文件的依赖关系
- makefile 自动处理头文件的依赖关系
- Makefile基础---自动处理头文件的依赖关系
- Makefile基础 4. 自动处理头文件的依赖关系
- makefile 自动处理头文件的依赖关系 (zz)
- Makefile基础 4. 自动处理头文件的依赖关系
- Makefile 自动生成头文件的依赖关系
- makefile 自动生成头文件依赖关系
- 头文件的依赖关系
- 头文件和源文件在不同目录情况下 Makefile自动推导依赖关系的实现
- 自动添加头文件依赖
- 自动编译Makefile,原版升级版,支持自动推倒头文件依赖关系、创建目标路径
- Makefile中头文件依赖的自动生成
- Makefile自动依赖所有需要的头文件
- 嵌入式 书写Makefile中头文件自动依赖关系小技巧
- Makefile自动生成头文件依赖
- 计算机基础知识学习(网络必备)强烈推荐!!!
- DBMS_SCHEDULE
- PHP程序员最易犯10种错误(转载)
- XML文件结构和基本语法
- 计算机基础知识学习(网络必备)强烈推荐!!!
- 自动处理头文件的依赖关系
- 聊天室代码
- DOS 下循环命令 FOR
- ZJU 09 复试上机 第五题
- JSTL 在tomcat5.5(liferay+tomcat5.5)下不起作用
- 最新jQuery CHM版中文帮助文档
- 问题解决---xp下组合框的文本颜色更改
- 导出Excel 汉字乱码
- 浅谈前端新人的职业规划