Makefile

Makefile

  • 工程只有一两个 C 文件,用GCC编译器还好,输入的命令不多,文件几十、上百就需要make工具

  • 描述哪些文件需要编译、哪些需要重新编译的文件就叫做 Makefile,Makefile 就跟脚本文件一样,Makefile 里面还可以执行系统命令,使用时只需make一下。

  • IDE集成开发环境(Integrated Development Environment),对Makefile进行了封装,使用时直接编译C文件就好。

  • Linux下,使用GCC编译器,需要懂Makefile,通过 Makefile 了解整个工程的处理过程。

    image-20231115160639028

如何编写Makefile

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

# 如果只修改了calcu.c 这个文件,只需要下面两条命令
gcc -c calcu.c
gcc main.o input.o calcu.o -o main

但是如果需要修改的文件较多,就需要满足下面的条件的工具:

1、如果工程没有编译过,那么工程中的所有.c 文件都要被编译并且链接成可执行程序。

2、如果工程中只有个别 C 文件被修改了,那么只编译这些被修改的 C 文件即可。

3、如果工程的头文件被修改了,那么我们需要编译所有引用这个头文件的 C 文件,并且链接成可执行文件。

写Makefiel 文档:

行首需要空格的话,使用TAB键,而非空格键。然后直接make执行就行。

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

最后一个规则目标是 clean,它没有依赖文件,因此会默认为依赖文件都是最新的,所以其对应的命令不会因为make而执行。

需要使用命令“make clean”,执行以后才会删除当前目录下所有的.o 文件以及 main。

总结:

1、make 命令会在当前目录下查找以 Makefile(makefile 其实也可以)命名的文件。

2、当找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件。

3、当发现目标文件不存在,或者目标所依赖的文件比目标文件新(也就是最后修改时间比目标文件晚)的话就会执行后面的命令来更新目标。

Makefile语法

1、规则格式

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

如果要更新目标,就必须先更新它的所有依赖文件,如果依赖文件中的任何一个有更新,那么目标也必须更新.

2、变量

#Makefile 变量的使用  objects

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

注释用 #, 变量的引用方法:$(变量名)

3、三种赋值符号

=

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

# output:curname:zuozhongkai,=可以将变量的真实值推到后面去定义
print:
	@echo curname: $(curname)

在 Makefile 要输出一串字符的话使用“echo”,在命令前面加上“@”的话就不会输出命令执行过程。

:=

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

# output:zzk,:=不会使用后面定义的变量,和=有区别
print:
	@echo curname: $(curname)

?=

curname ?= zuozhongkai

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

+=

objects = main.o inpiut.o
objects += calcu.o

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

4、模式规则

模式规则中,至少在规则的目标定定义中要包涵%,否则就是一般规则,目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串,比如“%.c”就是所有的以.c 结尾的文件,类似与通配符,a.%.c 就表示以 a.开头,以.c 结束的所有文件

main: $(objects)
gcc -o main $(objects)

%.o : %.c
	#命令

clean:
	rm *.o
 	rm main

5、Makefile自动化变量

image-20231115164150716

常用的三种:$@$<$^

6、伪目标

使用伪目标主要是为了避免 Makefile 中定义的执行命令的目标和工作目录下的实际文件出现名字冲突,有时候我们需要编写一个规则用来执行一些命令,但是这个规则不是用来创建文件的。

即当make clean时,只执行rm的两条指令。

clean:
	rm *.o
	rm main

如果工作目录中有clean文件,执行make clean时,不会执行后面的命令,清理工程的功能无法完成,为了避免该问题,可以将 clean 声明为伪目标,声明方式如下

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

.PHONY : clean

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

clean:
	 rm *.o
	 rm main

7、条件判断语句

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

条件关键字有:ifeq、ifneq、ifdef 和 ifndef

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

上面都是用来比较“参数 1”和“参数 2”是否相同,如果相同则为真,“参数 1”和“参数 2”可以为函数返回值。ifneq 的用法类似,只不过 ifneq 是用来了比较“参数 1”和“参数 2”是否不相等,如果不相等的话就为真。

8、函数

函数用法:

$(函数名 参数集合)
# 或者
${函数名 参数集合}
  • subst
# 将字符串<text>中的<from>内容替换为<to>,函数返回被替换以后的字符串
$(subst <from>,<to>,<text>)
  • patsubst
# 查找字符串<text>中的单词是否符合模式<pattern>,如果匹配就用<replacement>来替换掉,<pattern>可以使用通配符“%”,表示任意长度的字符串,函数返回值就是替换后的字符串
$(patsubst <pattern>,<replacement>,<text>)

# 将字符串“a.c b.c c.c”中的所有符合“%.c”的字符串,替换为“%.o”,替换完成以后的字符串为“a.o b.o c.o”。
$(patsubst %.c,%.o,a.c b.c c.c
  • dir
# 从文件名序列<names>中提取出目录部分,返回值是文件名序列<names>的目录部分
$(dir <names…>)

# 提取文件“/src/a.c”的目录部分,也就是“/src”。
$(dir </src/a.c>)
  • notdir
# 从文件名序列<names>中提取出文件名非目录部分
$(notdir <names…>)

# 提取文件“/src/a.c”中的非目录部分,也就是文件名“a.c”。
$(notdir </src/a.c>)
  • foreach
# 把参数<list>中的单词逐一取出来放到参数<var>中,然后再执行<text>所包含的表达式。每次<text>都会返回一个字符串,循环的过程中,<text>中所包含的每个字符串会以空格隔开,最后当整个循环结束时,<text>所返回的每个字符串所组成的整个字符串将会是函数 foreach 函数的返回值。
$(foreach <var>, <list>,<text>)
  • wildcard
# 通配符“%”只能用在规则中,只有在规则中它才会展开,如果在变量定义和函数使用时,通配符不会自动展开,这个时候就要用到函数 wildcard
$(wildcard PATTERN…)

# 获取当前目录下所有的.c 文件,类似“%”
$(wildcard *.c)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鬼才的凝视

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值