文档章节

学会使用makefile:4

e
 eversliver
发布于 2016/08/07 15:17
字数 912
阅读 2
收藏 0

这里主要介绍一下如何处理编译文件以来的问题:

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
    gcc $^ -o $@
main.o: main.h stack.h maze.h
stack.o: stack.h main.h
maze.o: maze.h main.h
clean:
    -rm main *.o
.PHONY: clean

一般一概将makefile写成下面这种形式:

all: main
main: main.o stack.o maze.o
    gcc $^ -o $@
clean:
    -rm main *.o.PHONY: clean
sources = main.c stack.c maze.c
include $(sources:.c=.d)
%.d: %.c
    set -e; rm -f $@; \
    $(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
    sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
    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; \
    cc -MM maze.c > maze.d.$$; \
    sed 's,\(maze\)\.o[ :]*,\1.o maze.d : ,g' < maze.d.$$ >
maze.d; \
    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 包含进来,于是新的依赖关系生效了。

 

 

© 著作权归作者所有

e
粉丝 0
博文 57
码字总数 10582
作品 0
成都
私信 提问
Make 命令教程

代码变成可执行文件,叫做编译(compile);先编译这个,还是先编译那个(即编译的安排),叫做构建(build)。 Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目。但是实际上 ,...

阮一峰
2015/02/20
0
0
嵌入式linux裸板开发--点亮LED

----------上一篇文章写的是linux下通过gcc完成程序源文件的编译执行的过程。以及makefile文件的编写,最后在终端平台输出myhello word!有了这个基础,这次学习的就是通过linux编译生成的代...

ludy51
2017/12/09
0
0
linux驱动编写(usb host驱动入门)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 usb协议是一个复杂的协议,目前涉及到的版本就有usb1.0, usb2.0, usb3.0。大家如果打开kernel usb ho...

feixiaoxing
2018/04/06
0
0
Mini2440上的第一个程序——点亮Led

手头的Mini2440搁置了两年半之后,我再次决定拿出它,重新尝试嵌入式Linux的学习。 我使用的是友善之臂的Mini2440开发板、韦东山的《嵌入式Linux应用开发完成手册》及其视频教程。所以,本篇...

icuic
2018/07/15
0
0
最全LinuxC语言系统开发资源视频资源

1小时快速攻破链表数据结构----(视频可下载)http://www.wyzc.com/forum/56796.html 深入理解auto register static关键字 http://www.wyzc.com/forum/56132.html 如何使用日期时间函数 http...

马洪伟
2014/12/26
195
0

没有更多内容

加载失败,请刷新页面

加载更多

Android 图片加载带进度条的ImageView

https://blog.csdn.net/shu_quan/article/details/79975578

shzwork
22分钟前
7
0
关于XAMPP默认端口80 和443被占用的问题

本文转载于:专业的前端网站➩关于XAMPP默认端口80 和443被占用的问题 关于安装xampp-win32-1.8.1-VC9-installer.zip后启动时候报端口80和443被占用的问题解决 xampp-win32-1.8.1-VC9-instal...

前端老手
24分钟前
6
0
错误Setting the parent of a transform which resides in a Prefab Asset is...

错误日志 Setting the parent of a transform which resides in a Prefab Asset is disabled to prevent data corruption 原因1 用Resouce.Load加载一个prefab,没有实例化直接设置parent ......

XBlock
24分钟前
9
0
Spring boot 配置mybatis

当然任何模式都需要首先引入mybatis-spring-boot-starter的pom文件,现在最新版本是1.1.1(刚好快到双11了 :)) <dependency>    <groupId>org.mybatis.spring.boot</groupId>    <......

雷开你的门
25分钟前
9
0
云栖干货回顾 | 更强大的实时数仓构建能力!分析型数据库PostgreSQL 6.0新特性解读

阿里云 AnalyticDB for PostgreSQL 为采用MPP架构的分布式集群数据库,完备支持SQL 2003,部分兼容Oracle语法,支持PL/SQL存储过程,触发器,支持标准数据库事务ACID。AnalyticDB PG通过行存...

开源中国小二
37分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部