学会使用makefile:4
2016-01-12 17:07
411 查看
这里主要介绍一下如何处理编译文件以来的问题:
举个例子,来说明吧:
一个普通的makefile如下所示:
一般一概将makefile写成下面这种形式:
source这一项指出了所有的要编译的.c文件, $(sources: .c = .d),相当于讲所有的.c文件都替换成.d文件。
那么include那一项实际上就相当于 include main.d stack.d maze.d
但是当前目录下实际上目前是没有.d文件的,但是 make 会把 include 的文件名也当作目标来尝试更新,而这些目标适用模式规则 %.d: %c ,所以执行它的命令列表,比如生成 maze.d 的命令:
1.set -e;命令设置当前Shell进程为这样的状态:如果它执行的任何一条命令的退出状态非零则立刻终止,不再执行后续命令。
2.删除原来的maze.d
3. 通过gcc的-MM选项重新生成maze.c的依赖关系,两个$$的主要作用是表示当前进程的id,一般用于生成唯一的文件名。
4.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 。
5. 最后删除maze.d.1234文件。
不管是Makefile本身还是被它包含的文件,只要有一个文件在 make 过程中被更新了, make 就会重新读取整个Makefile以及被它包含的所有文件,现在 main.d 、 stack.d 和 maze.d 都生成了,就可以正常包含进来了(假如这时还没有生成, make 就要报错而不是报警告了),相当于在Makefile中添了三条规则:
1、 main.c 的修改日期变了,根据规则 main.o main.d: main.c main.h stack.h maze.h 要重新生成 main.o 和 main.d 。生成 main.o 的规则有两条:
第一条是把规则 main.o main.d: main.c main.h stack.h maze.h 拆开写得到的,第二条是隐含规则,因此执行 cc 命令重新编译 main.o 。生成 main.d 的规则也有两条:
因此 main.d 的内容被更新为 main.o main.d: main.c main.h stack.h maze.h foo.h 。
2、由于 main.d 被Makefile包含, main.d 被更新又导致 make 重新读取整个Makefile,把新
的 main.d 包含进来,于是新的依赖关系生效了。
main.o: main.h stack.h maze.h stack.o: stack.h main.h maze.o: maze.h main.h可见上面几个文件都依赖与几个头文件,实际上自己一个一个动手去写会比较麻烦,而且还容易弄错。可以用 gcc 的 -M 选项自动生成目标文件和源文件的依赖关系。如果像去除对系统库文件的以来关系,可以去使用gcc -MM
举个例子,来说明吧:
一个普通的makefile如下所示:
all: main
main: main.o stack.o maze.o
<span style="white-space:pre"> </span>gcc $^ -o $@
main.o: main.h stack.h maze.h stack.o: stack.h main.h maze.o: maze.h main.h
clean:
<span style="white-space:pre"> </span>-rm main *.o
.PHONY: clean
一般一概将makefile写成下面这种形式:
all: main main: main.o stack.o maze.o <span style="white-space:pre"> </span>gcc $^ -o $@ clean: <span style="white-space:pre"> </span>-rm main *.o.PHONY: clean sources = main.c stack.c maze.c include $(sources:.c=.d) %.d: %.c <span style="white-space:pre"> </span>set -e; rm -f $@; \ <span style="white-space:pre"> </span>$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \ <span style="white-space:pre"> </span>sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ <span style="white-space:pre"> </span>rm -f $@.$$$$
source这一项指出了所有的要编译的.c文件, $(sources: .c = .d),相当于讲所有的.c文件都替换成.d文件。
那么include那一项实际上就相当于 include main.d stack.d maze.d
但是当前目录下实际上目前是没有.d文件的,但是 make 会把 include 的文件名也当作目标来尝试更新,而这些目标适用模式规则 %.d: %c ,所以执行它的命令列表,比如生成 maze.d 的命令:
set -e; rm -f maze.d; \ <span style="white-space:pre"> </span>cc -MM maze.c > maze.d.$$; \ <span style="white-space:pre"> </span>sed 's,\(maze\)\.o[ :]*,\1.o maze.d : ,g' < maze.d.$$ > maze.d; \ <span style="white-space:pre"> </span>rm -f maze.d.$$上面这一段的执行步骤实际上如下所示:
1.set -e;命令设置当前Shell进程为这样的状态:如果它执行的任何一条命令的退出状态非零则立刻终止,不再执行后续命令。
2.删除原来的maze.d
3. 通过gcc的-MM选项重新生成maze.c的依赖关系,两个$$的主要作用是表示当前进程的id,一般用于生成唯一的文件名。
4.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 。
5. 最后删除maze.d.1234文件。
不管是Makefile本身还是被它包含的文件,只要有一个文件在 make 过程中被更新了, make 就会重新读取整个Makefile以及被它包含的所有文件,现在 main.d 、 stack.d 和 maze.d 都生成了,就可以正常包含进来了(假如这时还没有生成, make 就要报错而不是报警告了),相当于在Makefile中添了三条规则:
main.o main.d: main.c main.h stack.h maze.h maze.o maze.d: maze.c maze.h main.h stack.o stack.d: stack.c stack.h main.h如果我在 main.c 中加了一行 #include "foo.h" ,那么:
1、 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.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: %.c set -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 。
2、由于 main.d 被Makefile包含, main.d 被更新又导致 make 重新读取整个Makefile,把新
的 main.d 包含进来,于是新的依赖关系生效了。
相关文章推荐
- NSNotificationCenter通知,用userInfo实现
- 理解Spark的核心RDD
- 自定义Adpter使用方法以及注意点
- JS组件系列——Bootstrap 树控件使用经验分享
- Windows Server 2012 Hyper-V群集
- linux PS1环境变量使用
- .Net读取AD中的用户并使用BootstrapTable的ajax分页
- IOS界面弹窗显示多个按钮
- oracle 11g GRID 中 关于 OLR 需要知道的一些内容
- stat函数的用法
- mysql中Access denied for user 'root'@'localhost' (using password:YES)的解决办法(本人实操)
- Linux下软件安装和卸载
- DIY:利用Arduino制作智能家居系统
- 多媒体格式
- 坦克大战游戏步骤 思路 与代码(一)
- Android网络图片加载框架:Universal-ImageLoader简介
- C3P0 相关配置描述
- lightoj 1214 大数的整除
- windows下使用TortoiseGit代替Git命令行操作
- Swift开发IOS-UIActionSheet