Makefile学习

·


什么是Makefile

一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,Makefile 文件定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 Makefile 文件就像一个 Shell 脚本一样,也可以执行操作系统的命令。

Makefile 带来的好处就是“自动化编译” ,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。make 是一个命令工具,是一个解释 Makefile 文件中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,比如 Delphi 的 make,Visual C++ 的 nmake,Linux 下 GNU 的 make。


一、Makefile 文件命名和规则

文件命名:makefile 或者 Makefile

Makefile 规则

  1. 一个 Makefile 文件中可以有一个或者多个规则

目标 …: 依赖 …
命令(Shell 命令)

目标:最终要生成的文件(伪目标除外)
依赖:生成目标所需要的文件或是目标
命令:通过执行命令对依赖操作生成目标(命令前必须 Tab 缩进)

  1. Makefile 中的其它规则一般都是为第一条规则服务的

示例:实现一个加减乘除的项目管理
通过指令vim Makefile来创建Makefile文件

app:sub.c add.c mult.c div.c main.c
	gcc sub.c add.c mult.c div.c main.c -o app

使用make指令执行文件自动编译。

二、Makefile工作原理

1.检查依赖

◼命令在执行之前,需要先检查规则中的依赖是否存在
如果存在,执行命令;
如果不存在,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的,如果找到了,则执行该规则中的命令。

优化后的Makefile文件如下所示,这样做的好处是当修改其中一处文件时,只需要编译经过修改后的文件即可,效率较之前提高了不少。

app:sub.o add.o mult.o div.o main.o
	gcc sub.o add.o mult.o div.o main.o -o app

sub.o:sub.c
	gcc -c sub.c -o sub.o

add.o:add.c
	gcc -c add.c -o add.o

mult.o:mult.c
	gcc -c mult.c -o mult.o

div.o:div.c
	gcc -c div.c -o div.o

main.o:main.c
	gcc -c main.c -o main.o

生成app这个目标,需要先获得依赖sub.o add.o mult.o div.o main.o,如果没有就会找下面的命令生成这些依赖。

2.检测更新

◼ 检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间
如果依赖的时间比目标的时间晚,需要重新生成目标;
如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行。

当修改main.c文件后,make命令会进行一个更新操作

在这里插入图片描述


三、变量

  1. 自定义变量
    变量名= 变量值
    var=hello
  2. 预定义变量
    AR : 归档维护程序的名称,默认值为 ar
    CC : C 编译器的名称,默认值为 cc
    CXX : C++ 编译器的名称,默认值为 g++
    $@ : 目标的完整名称
    $< : 第一个依赖文件的名称
    $^ : 所有的依赖文件
  3. 获取变量的值
    $(变量名 )
    $(var )
    使用方法:
    app:main.c a.c b.c
        gcc -c main.c a.c b.c
        
#自动变量只能在规则的命令中使用

    app:main.c a.c b.c
        $(CC) -c $^ -o $@

使用变量之后的Makefile文件如下所示

#定义变量
src=sub.o add.o mult.o div.o main.o
target=app
$(target):$(src)
	$(CC) $^ -o $@
sub.o:sub.c
	gcc -c sub.c -o sub.o
add.o:add.c
	gcc -c add.c -o add.o
div.o:div.c
	gcc -c div.c -o div.o
mult.o:mult.c
	gcc -c mult.c -o mult.o
main.o:main.c
	gcc -c main.c -o main.o

四、模式匹配

%.o:%.c

  • %: 通配符,匹配一个字符串
  • 两个%匹配的是同一个字符串
    %.o:%.c
    gcc -c $< -o $@

使用模式匹配之后的Makefile文件如下所示,较之前省去了大段的规则。

#定义变量
src=sub.o add.o mult.o div.o main.o
target=app
$(target):$(src)
	$(CC) $^ -o $@
%.o:%.c
	$(CC) -c $< -o $@

五、函数

$(wildcard PATTERN...)

功能:获取指定目录下指定类型的文件列表
参数:PATTERN 指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔
返回:得到的若干个文件的文件列表,文件名之间使用空格间隔
示例:
$(wildcard *.c ./sub/*.c)
返回值格式: a.c b.c c.c d.c e.c f.c

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

功能:查找 <text> 中的单词 ( 单词以“空格”、“ Tab ”或“回车”“换行”分隔 ) 是否符合模式<pattern> ,如果匹配的话,则以 <replacement> 替换。
<pattern> 可以包括通配符 % ,表示任意长度的字串。如果 <replacement>中也包含 % ,那么,<replacement>中的这个 % 将是 <pattern> 中的那个 %所代表的字串。 ( 可以用 \ 来转义,以 \% 来表示真实含义的 % 字符 )
返回:函数返回被替换过后的字符串
示例:
$(patsubst %.c, %.o, x.c bar.c)
返回值格式: x.o bar.o

使用函数之后的Makefile文件如下

src=$(wildcard ./*.c)
objs=$(patsubst %.c, %.o, $(src))
target=app
$(target):$(objs)
	$(CC) $^ -o $@
%.o:%.c
	$(CC) -c $< -o $@

六、clean功能

.PHONY:clean
clean:
	rm $(objs) -f

可以用来清除中间文件,比如我们有a.c,b.c,main.c先生成a.o,b.o,mian.o,再链接生成app,这个时候a.o,b.o,main.o就没有用了,我们可以在Makefile文件末尾添加上述代码执行rm指令用来删除中间文件。但是不是添加了这三行代码就可以删除,需要在shell中执行make clean来调用clean指令。

PHONY:clean这一行的代码的作用是生成clean伪目标,不写这一行代码的话会生成名为clean的文件,如果已经有了clean文件就不会被更新,make clean的话就不会实现我们想要的功能。添加了本行代码的话,不用建立文件,实现clean功能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值