侧边栏壁纸
博主头像
thinkTV博主等级

喜爱动漫的二刺螈一枚,摩托车云爱好者(快要有车了)。 懂一点技术的在读生物医学工程研究生( •̀ ω •́ )✧,多多指教。

  • 累计撰写 128 篇文章
  • 累计创建 18 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

make工具和Makefile

thinkTV
2023-08-05 / 0 评论 / 0 点赞 / 590 阅读 / 2,005 字 / 正在检测是否收录...

1. make工具和Makefile文件的引入

当源码文件比较多的时候就不适合通过直接输入gcc命令来编译,这时候就需要一个自动化的编译工具.

  • make:一般说GNU Make,是一个软件,用于将源代码文件编译为可执行的二进制文件,make工具主要用于完成自动化编译。make工具编译的时候需要Makefile文件提供编译文件。
  • Makefile:make工具所使用的文件,Makefile指明了编译规则。

2. Makefile 语法

2.1 Makefile 规则格式

Makefile 里面是由一系列的规则组成的,这些规则格式如下:

目标…... : 依赖文件集合……
	命令 1
	命令 2
	……

例如:

main : main.o input.o calcu.o
	gcc -o main main.o input.o calcu.o

这条规则的目标是 main,main.o、input.o 和 calcu.o 是生成 main 的依赖文件,如果要更新目标 main,就必须先更新它的所有依赖文件,如果依赖文件中的任何一个有更新,那么目标也必须更新,“更新”就是执行一遍规则中的命令列表。

命令列表中的每条命令必须以 TAB 键开始,不能使用空格!
make 命令会为 Makefile 中的每个以 TAB 开始的命令创建一个 Shell 进程去执行

总结一下 Make 的执行过程:

  1. make 命令会在当前目录下查找以 Makefile(makefile 其实也可以)命名的文件。
  2. 找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件。
  3. 当发现目标文件不存在,或者目标所依赖的文件比目标文件新(也就是最后修改时间比目标文件晚)的话就会执行后面的命令来更新目标

图片-1691301987508

2.2 Makefile 变量

Makefile 中的变量都是字符串,类似 C 语言中的宏

#Makefile 变量的使用
objects = main.o input.o calcu.o
main: $(objects)
gcc -o main $(objects)

“$(objects)”就是使用变量 objects。

Makefile 赋值符

1. 赋值符“=”

使用“=”在给变量的赋值的时候,不一定要用已经定义好的值,也可以使用后面定义的值

name = zzk
curname = $(name)
name = zuozhongkai

print:
	@echo curname: $(curname)

结果:

图片-1691302951711

赋值符= :变量的真实值取决于它所引用的变量的最后一次有效值。

2. 赋值符“:=”

赋值符:=不会使用后面定义的变量,只能使用前面已经定义好的

3. 赋值符“?=”

curname ?= zuozhongkai

如果变量 curname 前面没有被赋值,那么此变量就是“zuozhongkai”,如果前面已经赋过值了,那么就使用前面赋的值。

4. 变量追加“+=”

给前面已经定义好的变量添加一些字符串进
去,此时就要使用到符号+=

2.3 Makefile 模式规则

  • 模式规则中,至少在规则的目标定定义中要包涵“%”,否则就是一般规则
  • 目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串,比如“%.c”就是所有的以.c 结尾的文件,类似与通配符,a.%.c 就表示以 a.开头,以.c 结束的所有文件。
  • 当“%”出现在目标中的时候,目标中“%”所代表的值决定了依赖中的“%”值
%.o : %.c
	命令

2.4 Makefile 自动化变量

图片-1691314690707
图片-1691314707966

例子:

main: main.o input.o calcu.o
	gcc -o main main.o input.o calcu.o
main.o: main.c
	gcc -c main.c
input.o: input.c
	gcc -c input.c
calcu.o: calcu.c
	gcc -c calcu.c

clean:
	rm *.o
	rm main

改为:

objects = main.o input.o calcu.o
main: $(objects)
	gcc -o main $(objects)

%.o : %.c
	gcc -c $<

clean:
	rm *.o
	rm main

2.5 Makefile 伪目标

  • 一般的目标名都是要生成的文件,而伪目标不代表真正的目标名,在执行 make 命令的时候通过指定这个伪目标来执行其所在规则的定义的命令。
  • 使用伪目标的主要是为了避免 Makefile 中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,有时候我们需要编写一个规则用来执行一些命令,但是这个规则不是用来创建文件的

声明方式如下:

.PHONY : clean

2.6 Makefile 条件判断

语法有两种如下:

<条件关键字>
	<条件为真时执行的语句>
endif
<条件关键字>
	<条件为真时执行的语句>
else
	<条件为假时执行的语句>
endif

其中条件关键字有 4 个:ifeq、ifneq、ifdef 和 ifndef

ifeq 用来判断是否相等,ifneq 就是判断是否不相等:

ifeq (<参数 1>, <参数 2>)
ifeq ‘<参数 1 >’,‘ <参数 2>’
ifeq “<参数 1>”, “<参数 2>”
ifeq “<参数 1>”, ‘<参数 2>’
ifeq ‘<参数 1>’, “<参数 2>”

ifdef 和 ifndef :如果“变量名”的值非空,那么表示表达式为真,否则表达式为假。“变量名”同样可以是一个函数的返回值。ifndef 用法类似,但是含义用户 ifdef 相反

ifdef <变量名>

2.7 Makefile 函数使用

Makefile 中的函数是已经定义好的,不支持我们自定义函数。

$(函数名 参数集合)
#或者
${函数名 参数集合}

1. 函数 subst

函数 subst 用来完成字符串替换,调用形式如下:

$(subst <from>,<to>,<text>)
//是将字符串<text>中的<from>内容替换为<to>,函数返回被替换以后的字符
串

2. 函数 patsubst

函数 patsubst 用来完成模式字符串替换,使用方法如下:

$(patsubst <pattern>,<replacement>,<text>)

此函数查找字符串<text>中的单词是否符合模式<pattern>,如果匹配就用<replacement>来替换掉,<pattern>可以使用包括通配符“%”,表示任意长度的字符串,函数返回值就是替换后的字符串。如果<replacement>中也包涵“%”,那么<replacement>中的“%”将是<pattern>中的那个“%”所代表的字符串

3. 函数 dir

函数 dir 用来获取目录

$(dir <names…>)

此函数用来从文件名序列<names>中提取出目录部分,返回值是文件名序列<names>的目录部分

4. 函数 notdir

去除文件中的目录部分,也就是提取文件名

$(notdir <names…>)

此函数用与从文件名序列<names>中提取出文件名非目录部分

5. 函数 foreach

foreach 函数用来完成循环

$(foreach <var>, <list>,<text>)

把参数<list>中的单词逐一取出来放到参数<var>中,然后再执行<text>所包含的表达式。每次<text>都会返回一个字符串,循环的过程中,<text>中所包含的每个字符串会以空格隔开,最后当整个循环结束时,<text>所返回的每个字符串所组成的整个字符串将会是函数 foreach 函数的返回值

6. 函数 wildcard

通配符“%”只能用在规则中,只有在规则中它才会展开,如果在变量定义和函数使用时,通配符不会自动展开,这个时候就要用到函数 wildcard

$(wildcard PATTERN…)
0

评论区