跟我一起写makefile(一)

一、关于make和makefile的基本概念和使用:

Make
是一个能自动判断一个大型程序中哪些源代码需要重新编译 的工具
并且根据判断的结果自动调用编译器去编译源代码
最终按照一定的顺序,将编译结果整合成可执行程序

当项目中的某个文件做过修改,没有的make的情况下可能要重新编译整个项目,而make可以自动的判断哪些需要重新编译,哪些需要先进行编译,节省大量时间。

makefile:
可以认为是一个特殊的脚本文件,对于大型的项目,有很多的源文件需要编译,我们可以通过编写makefile来实现自动的编译,就不需要我们挨个去编译…

makefile来制定的规则,而make来执行这一些规则。

对于源文件比较少的时候:可以我们手动gcc,但是当文件数量特别大时就很不现实
gcc   a.c b.c c.c d.c .....  -o main   
//传统编译链接   如果有很多源文件,看起来很繁琐

一般makefile包含的内容:
1.文件的结构:对什么样的文件进行操作,文件间的引用关系
2.具体的指令:对这些文件怎么操作
在这里插入图片描述

makefile早期的基本语法:

main.o:main.c median.h
	gcc- c main.c

//目标文件名字:生成目标文件的  依赖的   其他源文件和头文件
//编译规则:Tab键不能少,不能用空格代替    然后将规则输入,main.o是根据这个规则生成的
因为make判断这行是不是命令就是根据这里有没有tab键来判断


这样有个缺点,如果文件过多,还是需要我们统统输入文件名,甚至有时候不知道源文件包含了
哪些文件,感觉很繁琐。

在这里插入图片描述

如上图:
解析makefile的基本工作流程:

1.make命名从上往下读取makefile文件时,make命令第一个遇到的文件名是最终要生成的文件,上图中是 all
2.
先看all生成没有,如果没有去看all的依赖top有没有,
如果top没有,再去看top的依赖main.o sort.o median.o有没有生成
假如发现main.o sort.o median.o都没有生成,会根据这三个文件的生成规则依次的去生成这三个文件
(我感觉make命令执行的路径像是一个递归的过程,或者说这本身就是个树形结构)
等到这三个文件生成,再去根据top的生成规则去生成top
然后最后生成all

make命令第一次执行 :
文件最终生成/修改时间先后顺序为:
main.o—>sort.o—>median.o------>top----->all
早 ——————————————> 晚
因为只有当目标文件 所依赖的 依赖文件 生成才能去生成目标文件。

make命令再次执行:
make命令同样的会从上到下的检查所有文件时间戳
如果发现某个目标文件的依赖文件的时间戳居然比最终目标文件all还要迟
就说明这个**文件就被修改过,**依赖这个文件的目标文件就需要重新的编译
(其他不依赖该文件的目标文件不需要重新编译)

比如说:
median.o文件所依赖的median.h的时间戳比all的时间戳居然晚,
说明median.o在前一次的编译以后被修改过,所以median.o和main.o将会被make命令重新编译
最后与其他目标源文件sort.o链接,重新生成新的最终目标文件。

注:
Linux上我们ls -l就可以查看到文件的最终修改时间。
make是通过文件的时间戳以及文件之间的相互依赖关系来决定哪些文件需要重新编译

二、make的隐含规则
1.make知道如何用什么样的工具编译这些文件,如c语言用gcc,c++用g++
2.

foo:foo.o bar.o
	gcc -o foo.o bar.o
//make认为foo.o和bar.o分别来自于foo.c和bar.c,所以我们就不用去写
foo.o:foo.c
	gcc -c foo.c
类似的内容,make会默认的去寻找foo.c去编译它,前提是命名要有规律~
比如main.o它认为就是main.c编译来的

所以,对于上面图片中的makefile的内容直接简化成:

all:top
top:main.o sort.o median.o
	gcc main.o sort.o median.o -o top
CC = gcc
AR
AS
.......   具体参考makefile的隐含规则

三、模式规则
用户自己定义新的隐含规则
格式:
模式规则和普通的规则相似
模式规则的目标有且仅有一个"%","%"可以匹配任意非空的字符串

( % 就像是 linux下的通配符 * 的含义)
’ %.o:%c’
表示把任意一个.c文件编译成.o文件

自动变量:
$@ 表示规则中的     目标文件    的名字
$< 表示规则中源文件   依赖文件   的名字
$^ 表示所有 依赖文件 的名字 

四、自动搜寻源文件所依赖的头文件
存在的问题:
一个源文件可能依赖好多头文件,这些头文件还有可能依赖其他的好多的头文件
编译器的支持:
现代的编译器可以 提供源文件依赖的所有头文件

比如编译c源文件的时候:
gcc -M main.c
-M:该选项会将生成main.o所依赖的所有头文件输出到.d文件

对于每个源文件,xxx.c编译器都会产生一个xxx.d的文件
这个 .d 文件中保存着xxx.o所依赖的所有头文件

我在我的ubuntu中写一个main.c,然后gcc -M main.c

king@ubuntu:~/mypython$ gcc -M main.c 
main.o: main.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
 /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/bits/long-double.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
 /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h \
 /usr/include/x86_64-linux-gnu/bits/types.h \
.....
我在这里并没有列出所有的头文件

我们可以在makefile中将.d文件包含进去

include$(source :.c = .d)
跟我一起 Makefile 作者:陈皓 整理:祝冬华 来源网络,希望能与大家分享这份学习资料,资源分数也设置了最低值,如有侵权,请联系我删除文件。 第一部分、概述 (6) 第二部分、关于程序的编译和链接 (6) 第三部分、Makefile 介绍 (7) 一、Makefile的规则 (7) 二、一个示例 (8) 三、make是如何工作的 (9) 四、makefile中使用变量 (10) 五、让make自动推导 (11) 六、另类风格的makefile (12) 七、清空目标文件的规则 (13) 第四部分、Makefile 总述 (13) 一、Makefile里有什么? (13) 1、显式规则。 (14) 2、隐晦规则。 (14) 3、变量的定义。 (14) 4、文件指示。 (14) 5、注释。 (14) 二、Makefile的文件名 (15) 三、引用其它的Makefile (15) 四、环境变量 MAKEFILES (16) 五、make的工作方式 (16) 第五部分、书规则 (17) 一、规则举例 (17) 二、规则的语法 (17) 三、在规则中使用通配符 (18) 四、文件搜寻 (19) 五、伪目标 (20) 六、多目标 (22) 七、静态模式 (22) 八、自动生成依赖性 (24) 第六部分书命令 (25) 一、显示命令 (26) 二、命令执行 (26) 三、命令出错 (27) 四、嵌套执行make (28) 五、定义命令包 (30) 第七部分使用变量 (30) 一、变量的基础 (31) 二、变量中的变量 (32) 三、变量高级用法 (34) 四、追加变量值 (37) 五、override 指示符 (37) 六、多行变量 (38) 八、目标变量 (39) 九、模式变量 (40) 第八部分使用条件判断 (40) 一、示例 (40) 二、语法 (42) 第九部分使用函数 (43) 一、函数的调用语法 (44) 二、字符串处理函数 (44) 1、subst (44) 2、patsubst (45) 3、strip (45) 4、findstring (46) 5、filter (46) 6、filter-out (46) 7、sort (47) 8、word (47) 9、wordlist (47) 10、words (47) 11、firstword (48) 12、字符串函数实例 (48) 三、文件名操作函数 (48) 1、dir (48) 2、notdir (48) 3、suffix (49) 4、basename (49) 5、addsuffix (49) 6、addprefix (49) 7、join (50) 四、foreach 函数 (50) 五、if 函数 (50) 六、call函数 (51) 七、origin函数 (51) “undefined” (52) “default” (52) “file” (52) “command line” (52) “override” (52) “automatic” (52) 八、shell函数 (53) 九、控制make的函数 (53) 1、error (53) 2、warning (54) 第十部分 make 的运行 (54) 二、指定Makefile (54) 三、指定目标 (55) “all” (56) “clean” (56) “install” (56) “print” (56) “tar” (56) “dist” (56) “TAGS” (56) “check”和“test” (56) 四、检查规则 (57) 五、make的参数 (57) 第十一部分隐含规则 (61) 一、使用隐含规则 (61) 二、隐含规则一览 (62) 1、编译C程序的隐含规则 (63) 2、编译C++程序的隐含规则 (63) 3、编译Pascal程序的隐含规则 (63) 4、编译Fortran/Ratfor程序的隐含规则 (63) 5、预处理Fortran/Ratfor程序的隐含规则 (63) 6、编译Modula-2程序的隐含规则 (63) 7、汇编和汇编预处理的隐含规则 (64) 8、链接Object文件的隐含规则 (64) 9、Yacc C程序时的隐含规则 (64) 10、Lex C程序时的隐含规则 (64) 11、Lex Ratfor程序时的隐含规则 (65) 12、从C程序、Yacc文件或Lex文件创建Lint库的隐含规则 (65) 三、隐含规则使用的变量 (65) 1、关于命令的变量。 (65) 2、关于命令参数的变量 (66) 四、隐含规则链 (67) 五、定义模式规则 (68) 1、模式规则介绍 (68) 2、模式
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值