系统编程--makefile项目管理

介绍

makefile就是一个命令脚本文件,接下来我们介绍如何使用他

语法结构

总览

在这里插入图片描述
要注意,想要使用与makefile相配合的make命令的话,makefile文件必须命名为“makefile”或者“Makefile”

基础规则

简介

在这里插入图片描述

最简单的makefile

一个规则:目标:依赖
(tab缩进)命令
如下图所示,是一个最简单的Makefile脚本文件
在这里插入图片描述
目标:就是最后要生成的文件的文件名
依赖:就是生成可执行文件的源文件
下一行先起一个tab,之后输入正常情况下我们要在终端输入的命令

在这里插入图片描述

对于基础规则的理解和应用

在这里插入图片描述
假如我们要运行如上所示命令,我们可以将其写入脚本文件makefile。如下图:
在这里插入图片描述
首先对于第一个脚本,目标是hello可执行文件,hello.o是依赖文件
但是目前makefile文件所在目录内没有hello.o文件,所以,我们可以再写一个脚本,用来生成hello.o
在这里插入图片描述
如上图所示,我们有了makefile之后,直接make命令,就可以执行makefile脚本文件里的脚本了,而当makefile中某个脚本所用的依赖在目录里没有时,make命令会接着在makefile文件内寻找有没有能生成所需要的依赖文件的脚本,如果有,则执行生成所需要的依赖文件之后,再去执行相应的脚本

总结

在这里插入图片描述

makefile时尽量使用更独立的命令,减少文件之间的耦合度

需求以及解决

在这里插入图片描述
在这里插入图片描述
假如我们按照如上所示命令,进行多个源文件的联合编译,从而生成可执行文件a.out
那么如果我们要修改其中一个源文件的代码,之后,想要生成新的可执行文件的话,就要再次make,这样,其他的不变的源文件又被编译了一次,比较浪费系统资源,所以,我们最好在写此类多文件联编的命令脚本时,要尽量减少各文件之间的耦合度,但是因为是多文件联合编译,我们也不能将他们完全隔离,我们可以在链接阶段将他们进行联编,其他阶段,各自生成各自的文件,如下图:
在这里插入图片描述
在这里插入图片描述
这个makefile在终端的命令如上图所示,这样,如果其中一个文件被改变了,那么也不会影响到其他文件
先对各个文件独立编译生成各自的可链接文件.o后缀文件,之后再将他们的可链接文件进行联编,生成可执行文件
最终效果如下图所示:
在这里插入图片描述
可以看到,当我们对div函数进行了修改之后,再次make,他就只会去再次编译div函数,其他的不运行,这样,系统资源就被高效利用了

总结

在这里插入图片描述
这就体现了第二条规则,如果依赖被更新了,那么make会先去更新依赖,再去生成目标
(本质上,make在执行时,会检查每个依赖文件的修改时间,如果我们在生成了可执行文件之后,又去修改了某个源文件,那么该源文件的修改时间就会比之前生成的可执行文件的时间要晚,这在make看来是不被允许的,所以如果我们修改了源文件再去make,make检查到这里发现问题之后,会只执行那个被修改了的依赖文件的脚本,然后再去生成可执行文件)

补充(关于makefile中脚本命令的编写顺序)

在这里插入图片描述
假如我们把a.out的脚本放在文本的最下面,那么make在执行完第一个脚本之后,他就会认为自己的使命完成了,就不会继续向下执行了
也就是他会把第一个脚本当成自己的终极目标,所以,我们前面一直把a.out目标脚本放在第一个,但是也有解决办法:
在这里插入图片描述
我们可以加上一个关键字ALL:,规定好终极目标文件为a.out,那么接下来在makefile文件中的顺序就无所谓了

两个函数

总览

在这里插入图片描述
$() 表示调用函数的意思,他会返回函数的返回值
wildcard 是函数名
*.c是函数参数

wildcard函数

在这里插入图片描述
他的作用如上图所示,就是将当前目录下的所有后缀为.c的文件的文件名生成一个列表,返回给字符串变量str(注意,在makefile脚本文件中,只有字符串类型,没有其他类型)
也就是上图中的==右边的效果

patsubst函数

在这里插入图片描述
该函数的作用是,将参数3中包含参数1的部分,替换成参数2的格式,如上图末尾的例子

应用

在这里插入图片描述
有了这两个函数,我们就可以将其应用到makefile中,简化脚本文件的书写。
上图是之前的makefile文件的内容,下图为使用两个函数优化之后的makefile:
在这里插入图片描述
其中$() 表示对一个变量进行取值,也就是将一个左值对象的右值取出来(或者称为展开),如上图是将obj的右值取出,放入脚本

总结

在这里插入图片描述

补充规则:clean规则

语法

在这里插入图片描述
首先是一个clean声明
之后一个tab键,接着写删除命令,如上rm -rf $(obj) a.out,表示强制删除obj显示的文件以及a.out文件
之后注意到整个命令前面有个小横杠,这个的作用是,哪怕要删除的文件不存在,也会正常运行命令,如下举例:
在这里插入图片描述
如果我们在命令行使用rm删除一个不存在的文件或者文件夹,那么会报错(如上图),但是如果使用make,且makefile文件中的clean脚本中加了小短杠,那么即使当前目录并不存在要删除的文件,那么也不会报错,而是绕过那个文件,删除其他存在的文件(如下图)
在这里插入图片描述

三个变量

总览

在这里插入图片描述
注意:
这些自动变量是用在命令行的,不能用于目标or依赖
而只能用在目标or依赖的下一行(也就是命令行)

应用

在这里插入图片描述
对于第一个,他的依赖是obj,命令原来是所有的.o文件,所以,可以将其替换成$^,表示规则中所有的依赖(即冒号右边部分)
而其他的,都是表示规则中第一个依赖(即冒号右边第一个依赖,因为依赖只有一个,所以,第一个依赖就是那个依赖)
每个命令行末尾是 $@, 表示命令中的目标文件(即冒号前的文件)

模式规则

在这里插入图片描述
修正:最后的%@改成 $ @
在这里插入图片描述
上图是修改之前的makefile,下图是使用了规则模式之后的makefile,由上图我们可以知道,第9行到第19行,都是用的一个模式,
即%.o:%.c,所以,我们可以将其用该模式替换,如下图(但是要注意,此时命令中的自动变量要用$<,因为如果该变量用在规则模式下,他会把依赖条件列表中的依赖依次取出,套用模式规则)
在这里插入图片描述
然后直接make,也会像上面那样,生成a.out文件

总结(有什么意义)

在这里插入图片描述
通过使用一个规则、两个函数、三个自动变量、规则模式之后,我们生成了最终版的makefile,那么我们为什么要这样该makefile呢,主要是为了程序的拓展性,当我们想再增加一个源文件参与到编译时,我们直接写源文件,然后引入到主函数文件,之后,直接make即可,无需对makefile做任何修改,这些都得益于那些规则的使用,从而大大提高了makefile的使用效率

补充

在这里插入图片描述

静态模式

在这里插入图片描述
首先我们观察图,看到那个模式规则的语法,%.o:% 变色,而后面的.c不变色,说明该模式是通过.o文件列表来推算的,通过拿到一个.o文件,将文件名给到后面的.c的%

当我们有多个规则模式时,假如要生成的都是%.o,那么makefile就不知道要使用哪一个了,所以,我们可以进行规定
在这里插入图片描述
这样的话,$(obj)会与其冒号后面的模式规则建立联系

伪目标

场景

在这里插入图片描述
假如我们在当前目录创建了一个名为“clean”的文件,那么会导致makefile中的clean无法执行,所以,为了解决这个问题,我们引入了伪目标规则
在这里插入图片描述
直接在末尾加入.PHONY: clean ALL(这些容易与文件名冲突的目标名,源文件或者一些.o、.s、.c这些指向性很强的文件名除外)
(一般只有clean ALL)

自定义添加参数

在这里插入图片描述
假如我们想在命令中加 -Wall -g(表示显示所有报错信息、可以进行gdb调试)
我们就可以定义一个变量,赋值为“ -Wall -g”
然后再所有的gcc命令后面加上$(myArgs),表示将里面的内容取出来

多文件编译时的makefile

在这里插入图片描述
第一行:makefile在当前目录,我们要执行makefile脚本,就是以当前makefile所在位置为参考点,所以,我们如果想要获取源文件的文件名,那么就要加上相对路径,因为源文件目前与makefile不在同一个目录下,加上路径之后,生成的str就是带有正确相对路径的源文件

第二行:要生成.o文件的文件名列表,该函数的意思是将参数三中的参数一改为参数二形式,而参数一的%会自动进行匹配,假如说我们只有%.c,那么他会把.c前面的字符全部匹配进%内,这样的话,后面的.o就会被改为./str.???.o,显然这是错误的,因为我们的.o文件在obj文件夹内。
所以,我们这里要修改%的匹配范围,把他限制在只匹配文件名即可,那么我们只要将其各自的前缀路径加上即可,如上图,在.c文件前加上./str/%.c , 然后修改为 ./obj/%.o

然后第14行,我们要将各个源文件编译为可链接文件(.o)这里与上面的原理一样,在目标和依赖都要加上各自的路径

同时,因为我们有了头文件,所以,要加上一个新参数,表示头文件的路径,之后加到编译阶段的命令后面,(第12行不用加,因为链接阶段无需头文件)

  • 11
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值