Makefile 作用
Makefile的作用为实现自动化编译,主要为了解决以下问题:
- 有很多源文件需要编译时
- 当存在很多源文件时,只修改了个别源文件,这时只需要编译修改过的文件即可,而无需整个项目都编译一遍。
- 当多个源文件存在依赖关系时,需要先编译一些文件,后编译一些文件
Makefile安装
要使用MakeFile,首先要按照make工具
在ubuntu18.0.4系统下,安装命令为:
sudo apt install build-essential
该命令会同时安装gcc/g++/make等工具
Makefile文件命名和规则
文件命名
makefile或Makefile
Makefile 规则
一个 Makefile 文件中可以有一个或者多个规则
1 | 目标 ... : 依赖 ... |
目标:最终要生成的文件(伪目标除外)
依赖:生成目标所需要的文件或是目标
命令:通过执行命令对依赖操作生成目标(命令前必须 Tab 缩进)
Makefile 中的其它规则一般都是为第一条规则服务的。
基本原理
1.命令在执行之前,需要先检查规则中的依赖是否存在
a.如果存在,执行命令
b.如果不存在,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的,如果找到了,则执行该规则中的命令
2.检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间
a.如果依赖的时间比目标的时间晚,需要重新生成目标
b.如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行
变量
自定义变量
变量名=变量值
1 | var=hello |
预定义变量
AR : 归档维护程序的名称,默认值为 ar
CC : C 编译器的名称,默认值为 cc
CXX : C++ 编译器的名称,默认值为 g++
$@ : 目标的完整名称
$< : 第一个依赖文件的名称
$^ : 所有的依赖文件
1 | app:main.c a.c b.c |
模式匹配
1 | add.o:add.c |
%.o:%.c
%: 通配符,匹配一个字符串
两个%匹配的是同一个字符串
%.o:%.c
gcc -c $< -o $@
函数
$(wildcard PATTERN…)
功能:获取指定目录下指定类型的文件列表
参数:PATTERN 指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔
返回:得到的若干个文件的文件列表,文件名之间使用空格间隔
示例:获取 当前目录下和sub目录中所有的 c 源文件。
$(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>中的那个%所代表的字串。(可以用\
来转义,以\%
来表示真实含义的 % 字符)返回:函数返回被替换过后的字符串列表,不更改任何文件
示例:将当前目录前所有的 .c 文件都替换为 .o 文件返回,
$(patsubst %.c, %.o, x.c bar.c)
返回值格式: x.o bar.o
Makefile实战
源文件
├── add.c
├── main.c
├── math.h
└── subtract.c
文件内容分别为:
main.c
1 |
|
自定义头文件
math.h
1 |
|
头文件里两个函数的实现:
add.c
1 |
|
subtract.c
1 |
|
不用Makefile
如果要生成可执行文件,需要编译main.c add.c subtract.c
编译命令为:
gcc main.c add.c subtract.c -o app
用Makefile
第一版Makefile
1 | app:main.c add.c subtract.c |
第二版Makefile
1 | app:main.o add.o subtract.o |
第三版Makefile
#定义变量
1 | src=subtract.o add.o main.o |
第四版Makefile
1 | #定义变量 |
第五版Makefile
1 | src=$(wildcard ./*.c) |