目录
一 、makefile规则
1.1 makefile文件名
默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件,可使用make -f 文件名或 make --file 文件名 查找运行特定makefile文件。
1.2 规则格式
Target(目标) : prerequisites(依赖)
(TAB)Command(命令)
Target: 是一个目标文件,可以是Object File,也可以是执行文件,还可以是一个标签(Label)。
Prerequisites: 是要生成那个target所需要的文件或是目标。
Command: 是make需要执行的命令。
app:main.o led.o lcd.o key.o
gcc main.o led.o lcd.o key.o -o app
main.o:main.c
gcc -c main.c -o main.o
led.o:led.c
gcc -c led.c -o led.o
key.o:key.c
gcc -c key.c -o key.o
lcd.o:lcd.c
gcc -c lcd.c -o lcd.o
规则执行顺序:main.o led.o lcd.o key.o app
注意:1)命令行前必须用TAB(每行)
2)第一条规则为终极目标
3)除第一条规则外其余规则之间无必然的顺序
4)每一个规则中的目标,不一定要有依赖
5)每一个规则,不一定非得有命令列表
6)每个规则中可以有多条命令规则
二、makefile组成元素
Makefile主要有五部分组成:显式规则、隐晦规则、变量定义、文件指示和注释。
2.1 显式规则
显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。
app:main.o led.o lcd.o key.o
gcc main.o led.o lcd.o key.o -o app
main.o:main.c
gcc -c main.c -o main.o
led.o:led.c
gcc -c led.c -o led.o
key.o:key.c
gcc -c key.c -o key.o
lcd.o:lcd.c
gcc -c lcd.c -o lcd.o
2.2 变量
在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
变量在声明时需要给予初值,而在使用时,需要给在变量名前加上“$”符号,用小括号“()”或是大括号“{}”把变量给包括起来。如果要使用真实的“$”字符,需要用“$$”来表示。变量类型为字符串
inc=./
A=123
ABC=456
all:
#输出./
echo $(inc)
#123
echo $A
#456
echo $(ABC)
#456
echo ${ABC}
2.3 运算符的使用
运算符 | 功能 | 举例 |
= | 延迟展开赋值:最后进行赋值 | ABC=$(A) A=123 all: echo $A echo $(ABC) echo ${ABC} 用时再取值 |
:= | 立即展开赋值 | ABC:=$(A) A=123 all: echo $A echo $(ABC) echo ${ABC} ABC:=$(A)时必须赋值 没有即为空 |
?= | 条件赋值:如果运算符前的变量没有被赋值,则把运算符后的值赋给该变量 (经常出现在make传参) | B=999 A=123 B?=$A all: echo $A echo $(B) echo ${B} |
+= | 追加赋值:把运算符后的值追加到变量上 | B:=123 B+=456 B+=789 all: echo $(B) echo ${B |
2.4 特殊变量/符号
变量 | 功能 |
$@ | 当前这条规则的“目标名” |
$^ | 当前规则中所有 “依赖” |
$< | 规则的第一个依赖文件名。如果是一个目标文件使用隐含规则来重建,则它代表由隐含规则加入的第一个依赖文件。 |
$$ | 代表当前执行的进程的进程编号 |
@ | 告诉make在执行命令前不要将命令显示在标准输出上 |
app:main.o led.o
gcc $^ -o $@
main.o:main.c
gcc -c $^ -o $@
led.o:led.c
gcc -c $^ -o $@
2.5 条件判断语句
关键字 | 功能 |
ifeq | 判断参数是否相等,相等为true,否则为false |
ifneq | 判断参数是否不相等,不相等为true,否则为false |
ifdef | 判断变量是否有值,有值则为ture,否则为false |
ifndef | 判断变量是否没有值,没有值则为ture,否则为false |
条件判断语句使用情况
1)判断语句不在规则中变量赋值
AAA=100
BBB=101
ifeq (${AAA},${BBB})
CCC=888
else
CCC=999
endif
all:
echo $(CCC)
2)标签在判断语句中
AAA=100
BBB=101
ifeq (${AAA},${BBB})
all:
echo "AAAA"
else
all:
echo "BBBB"
endif
3)判断语句在命令行中
AAA=100
BBB=101
all:
ifeq (${AAA},${BBB})
echo "AAAA"
else
echo "BBBB"
endif
如果条件语句不是出现在命令规则中,则不能使用相关命令,只能做赋值处理,例如情况1。
2.6 隐晦规则
由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。
使用模式规则来定义一个隐含规则。一个模式规则就好像一个一般的规则,只是在规则中,目标的定义需要有"%"字符。"%"的意思是表示一个或多个任意字符。在依赖目标中同样可以使用"%",只是依赖目标中的"%"的取值,取决于其目标。"%"的展开发生在变量和函数的展开之后,变量和函数的展开发生在make载入Makefile时,而模式规则中的"%"则发生在运行时。
CC=gcc
inc=../inc/
app:main.o led.o 可以添加路径(./src/mian.o) main.o等同于当前目录下main.o
$(CC) $^ -o $@ -I $(inc)
# %.o等同于main.o led.o %.c等同于main.c led.c
%.o:%.c
$(CC) -c $< -o $@ -I $(inc)
伪目标
伪目标:不是一个真正的目标,仅仅是为了执行其规则下的命令,使用 .PHONY:来声明,
执行:make 标签名,例:make clean
CC=gcc
inc=../inc/
app:main.o led.o lcd.o key.o
$(CC) $^ -o $@ -I $(inc)
%.o:%.c
$(CC) -c $^ -o $@ -I $(inc)
clean:
rm *.o app
.PHONY:clean
2.7 文件指示
①是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;
②是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;
③定义一个多行的命令。在Makefile使用include关键字可以把别的Makefile包含进来,被包含的文件会原模原样的放在当前文件的包含位置。
如果有文件没有找到的话,make会生成一条警告信息,但不会马上出现致命错误。它会继续载入其它的文件,一旦完成makefile的读取,make会再重试这些没有找到,或是不能读取的文件,如果还是不行,make才会出现一条致命信息。如果你想让make不理那些无法读取的文件,而继续执行,你可以在include前加一个减号“-”。如:-include<filename>
include 1.mk
CC=gcc
app:main.o led.o
$(CC) $^ -o $@
%.o:%.c
$(CC) -c $^ -o $@
2.8 注释
Makefile中只有行注释,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果要在Makefile中使用“#”字符,可以用反斜框进行转义,如:“\#”。
三 、makefile函数
3.1 匹配具体目录下的文件函数:wildcard函数
格式:sources= $(wildcard *.c) 返回值:<具体目录下文件>匹配当前目录下 所有.c文件 ; 也可以自定具体目录 |
#遍历出指定目录下所有文件 #allsrc = $(wildcard ./*.c) allsrc = $(wildcard *.c) #终极规则 all: echo ${allsrc} |
3.2 取文件名函数:notdir函数
格式:$(notdir NAMES) 函数功能:从文件名序列“NAMES”中取出非目录部分。目录部分是指最后一个斜线( “/”) (包括斜线)之前的部分。删除所有文件名中的目录部分,只保留非目录部分。 返回值:文件名序列“NAMES”中每一个文件的非目录部分。 |
#遍历出指定目录下所有文件 allsrc = $(wildcard ./src/*.c) #去除路径部分的文件名 notdirsrc = $(notdir ${allsrc}) #终极规则 all: echo $(allsrc) echo ${notdirsrc} |
3.3 模式替换函数:patsubst函数
格式:obj=$(patsubst <pattern>,<replacement>,<text>) 函数功能:查找text中的单词,如果匹配pattern,那么就用replacement的内容替换 返回值为:生成的所有replacement文件名; |
#遍历出指定目录下所有文件 allsrc = $(wildcard ./src/*.c) #去除路径部分的文件名 notdirsrc = $(notdir ${allsrc}) #模式匹配 objsrc=$(patsubst %.c,%.o,${notdirsrc}) #终极规则 all: echo $(allsrc) echo ${notdirsrc} echo $(objsrc) |
3.4 反过滤函数:filter-out函数
格式:$(filter-out <pattern...>,<text> ) 功能:以<pattern>模式过滤<text>字符串中的单词,去除符合模式<pattern>的单词。可以有多个模式。存在多个模式时,模式表达式之间使用空格分割。 返回:返回不符合模式<pattern>的字串。 |
#遍历出指定目录下所有文件 allsrc = $(wildcard ./src/*.c) #去除路径部分的文件名 notdirsrc = $(notdir ${allsrc}) #过滤掉指定源文件 #filter-out改为filter,则为过滤函数,功能为保留符合模式的单词 filterfilename=$(filter-out key.c,${notdirsrc}) #终极规则 all: echo ${filterfilename} |