Linux工具介绍——自动化构建工具make/Makefile
目录
一、make/Makefile简介
二、make/Makefile的使用
1. 依赖关系与依赖方法
2. make工具
3. 多层依赖关系
4. 回显问题
5. 特殊指代符号$@和$^
6. .PHONY修饰伪目标
7. make编译文件的更广应用
定义变量
编译多个文件
总结:
一、make/Makefile简介
如果是在一个大型项目当中,我们会有成百上千个文件,此时我们不可能通过gcc/g++一个一个地去进行编译。而make就是帮助我们完成自动化构建,对项目进行自动化编译的一个工具了。
make与Makefile的关系:
make是一个命令工具,而Makefile是一个文件,Makefile中记录定义了对项目中文件的编译规则,哪些文件先编译,哪些后编译,哪些和哪些需要链接等等......而make就是用来解释Makefile记录的规则,翻译给系统,再进行自动化编译
所以说一个人会不会写makefile,可以从侧面反映他是否具备完成大型工程的能力
二、make/Makefile的使用
Makefile是一门用于定制自动化编译规则的语言,现在我们来学习他的一些用法。我们首先需要在项目的目录下创建一个普通文件Makefile(makefile也可以),然后再用vim对它进行编辑。

1. 依赖关系与依赖方法
什么是依赖关系,例如,想要编译产生可执行程序test.out就需要有源文件test.c,所以test.out的产生依赖test.c。在Makefile文件中,依赖关系的表示用一个:来指示,:左边是目标文件,:右边是所依赖的文件。注意:依赖文件可以有多个,也可以没有
而依赖方法就是编译的具体实现方式,也就是一行指令,比如gcc test.c -o test。依赖方法写在依赖关系的下一行
第一行便是依赖关系,第二行是对应的依赖方法。
Makefile文件中,通常还需要一个clean方法,用于清除编译产生的文件,且clean没有依赖关系,仅靠自己就能实现
2. make工具
Makefile文件有了依赖关系与依赖方法后,就能对文件进行最简单的编译了。
1. 直接输入make指令,就可进行编译,指令会自动检测目录下的Makefile文件(实质是执行Makefile文件中的第一个指令,相当于 make test,习惯上都会把编译指令放在第一个位置),执行成功后发现目录多了一个可执行文件test,并且能够成功执行
2. 输入make clean清除编译产生的文件

3. 多层依赖关系
有时候会有多层依赖关系,如将编译拆成预处理、编译、汇编、链接这四步时,此时就会有一个顺序的问题。
此时我们应该先写出最终的目标文件,然后再一层层去寻找依赖文件,这个过程中会一层层建立栈帧,找到最深处后再返回。
记得clean也要清除这些产生的中间文件,此处我是写成了四行,不过也可以写成一行,用空格分隔文件名:rm -f test test.o test.i test.s


4. 回显问题
可以观察到之前我们调用make时,会在屏幕上回显执行的依赖方法指令,如果我们想要指令不回显,可以在依赖方法指令先加上@符号

5. 特殊指代符号$@和$^
依赖方法中的目标文件和依赖文件与依赖关系中的有所重复,所以可以用特殊符号来指代,$@可以代替依赖关系中的目标文件,而$^可以代替依赖关系中的依赖文件。

6. .PHONY修饰伪目标
首先我们先了解一个特性,使用make编译时,如果文件没有改变,一般是不能重复编译的,这是为了节省资源,不做无意义的事情。这是怎么办到的呢,原因是文件属性中会记录文件上次修改的时间,如果这个记录的时间没有改变,那就证明文件没有改变。

如果想要实现重复编译,可以用.PHONY来修饰依赖关系命令test,这样就能保证每次顺利执行。因为.PHONY是用于修饰伪目标的(伪目标即是总被执行的命令),不过通常情况下我们是不会给编译指令修饰为伪目标的,此处仅作为演示使用。
使用.PHONY修改后发现make能重复编译
7. make编译文件的更广应用
定义变量
此时依赖关系中的文件名我们还是用具体的文件名来写的,如果我们要修改文件名,那么Makefile中的文件名就要一个个修改,非常麻烦,特别是在比较大的项目中,所以我们可以提前定义变量,用于记录文件名,类似于C语言中的宏定义
BIN和SRC分别用来记录目标文件和依赖文件(makefile语言中没有类型之分,都视为字符串),然后再用$( )来提取变量中的内容就可以使用了。使用效果与之前是一样的。

编译多个文件
BIN,SRC这些变量不仅可以直接定义为一个文件名,还能使用函数,以及一些特殊的使用方法,来存储多个特定的文件名。
来看下面这段代码:

1. 变量SRC不是直接赋值为一个文件名,而是使用了wildcard函数,获取所有以 .c结尾的源代码文件,这样便于将多个 .c文件编译成一个最终的可执行文件(此处为了演示更多细节,将最后的编译过程单独拆出来编译)
2. 变量OBJ使用了一个语法:变量名:原后缀=目标后缀,这样直接批量将 .c后缀更换为了 .o后缀,方便我们链接多个文件
3. 依赖关系使用了$(BIN):$(OBJ),意为将所有编译好的二进制文件链接成一个可执行文件
4. 第8行的%是一个通配符,意思是匹配目录下所有的.o和.c文件,形成依赖关系
5. 第9行,这里没有使用-o是因为在编译时不加-o会默认生成一个将.c替换成.o的文件,而$<又是一个特殊符号,用于指代目标文件的第一个依赖项,其实就是代表:右边的文件名,每次自动取对应的文件,然后可以很方便地进行编译
使用示例:
为了方便演示,我们多创建几个.c文件,同时,把clean也修改了一下
总结:
至此,一份相对通用的Makefile文件就写好了,以后我们想要编译项目代码就可以直接使用这个Makefile文件,只需要在几个地方稍做修改即可!
以上便是本文的全部内容了,如果觉得有帮助的话可以点赞收藏加关注支持一下!






