在Linux环境下,为了便捷我们的指令,我们使用make和makefile来操作。他们的功能和复用代码类似,当我们用make命令时,Makefile就会在该目录被检测,并执行其中的命令,包括编译命令。
make命令只有一个,但makefile有三个。键入make后,系统会依次搜索GNUmakefile、makefile和Makefile,由于我们在使用ll命令的时候,Makefile会在相对靠前的位置出现,所以我推荐大家使用Makefile。
Makefile不会关心命令到底是什么,而是纯粹的执行这些命令,只要命令本身不出错,Makefile就会毫不犹豫地执行。
一、make的使用范例
单纯输入make的时候,将会递归地执行Makefile里的第一个目标,优先执行目标的依赖项。
cpp
myprocess:myprocess.c
gcc $< -o $@
这是一行makefile中可能会用到的命令,意思就是将myprocess.c编译为myprocess。
实际上这行命令和我们在机器里主动输入的没有任何区别,我们会输入gcc myprocess.c -o myprocess最后形成myprocess这个可执行文件。
但现在就相当于可以简单输入make,将一切myprocess.c文件转化为myprocess,尽管实际上只能同时存在一个文件。
那我们如何完成批量化编译呢?
我们可以利用wildcard
cpp
SRCS=$(wildcard *.c)
EXES=$(SRCS:.c=)
all:$(EXES)
%:%.c
gcc $< -o $@
这一段代码必须解释一下:
wildcard匹配所有.c后缀的文件,存储到SRCS里
EXES是SRCS里所有.c后缀的文件替换为空(对应C文件转换为可执行文件)
all为目标,依赖于EXES
%为模式匹配,%:%.c的意思是匹配同一名字的.c后缀文件和可执行文件。
\<即依赖项的第一项,@即目标
所以如果我有myprocess.c文件,输入make就会变为:
cpp
SRCS=myprocess.c
EXES=myprocess
all:$(EXES)
myprocess:myprocess.c
gcc myprocess.c -o myprocess
如果目录里有myprocess.c等一众文件,就会经过一次make被编译为可执行文件,相当便捷。
二、伪目标
伪目标,在makefile文件里被写在.PHONY后面
为什么要有伪目标?
因为makefile里可以有多个目标,且可以随意命名(拼音都可以),难免会出现和目录某一文件发生冲突,这个时候我们一旦输入make+该目标,系统无法理解是make文件还是make该目标,所以我们使用伪目标来定义。
我们可能会遇到的伪目标:
cpp
.PHONY:clean
clean:
rm -rf myprocess.c
当我们输入make clean时,就会帮我们把myprocess.c删除了。
三、变量赋值
关于赋值,我们有两个方式。=以及:=
=是最简单的赋值,但是由于makefile在执行时会被展开,这可能导致所有与变量相关的赋值乱套,举个例子:
cpp
VIR_A = A
VIR_B = $(VIR_A) B
VIR_A = AA
这个时候VIR_B就变成AA B了而不是A B。
但如果使用:=
cpp
VIR_A := A
VIR_B := $(VIR_A) B
VIR_A := AA
就会根据当前位置直接复制,VIR_B=VIR_A。