前言
格式:编译工具链 -o 可执行文件名 待编译文件名 -编译选项
例:gcc -o test test.c
或:编译工具链 待编译文件名 -o 可执行文件名 -编译选项
例:arm-linux-gnueabihf-gcc server.c -o server -pthread
每次编译时都需要打一长串是很麻烦的,尤其是当待编译文件众多时。此时需要制作Makefile文件,只需make 一下即可。MakeFile文件的写作等级大致分为五级,级别越高越难理解,此处仅做入门教学。
第一层 显式规则
将上述格式直接照搬,执行后只会编译已更新内容
目标:依赖
[TAB缩进]上述格式
示例说明:将main.c 与hello.c (依赖)编译成名为test的可执行文件(目标)。
注意目标为可执行文件时依赖需为.o文件,目标为.o文件时依赖才为.c文件。
执行make clean可将所有编译生成文件清除,clean文件实际不存在,故利用.PHONY声明clean为伪目标。
test:hello.o main.o #此符号为注释
gcc hello.o main.o -o test
hello.o:hello.c
gcc -c hello.c -o hello.o
main.o:main.c
gcc -c main.c -o main.o
.PHONY
clear:
rm -rf main.o hello.o test
第二层 变量替换
类似于C语言中的宏定义,以简略字符替换经常使用的变量,方便移植和修改
变量赋值:
:= 即时变量
= 延时变量
?= 延时变量,仅第一次定义才有效,如果前边有同名定义则忽略此句
+= 附加变量,是即时变量还是延时变量取决于前面定义
调用:$(变量)
CC:=gcc
OBJ:=main.o hello.o
TAR:=test
$(TAR):$(OBJ)
$(CC) $(OBJ) -o $(TAR)
main.o:main.c
$(CC) -c main.c -o main.o
hello.o:hello.c
$(CC) -c hello.c -o hello.o
.PHONY
clear:
rm -rf main.o hello.o test
第三层 隐式规则
将所有文件名省略,以 *、% 模糊代替,除了宏定义其他地方不会出现文件名,更易于维护
%c, %o:任意的.c和.o,对应的.c生成对应的.o,此条可能会多次执行,取决于OBJ个数
*.c *.o:所有的.c和.o,常用于clear语句
CC:=gcc
OBJ:=main.o hello.o
TAR:=test
$(TAR):$(OBJ)
$(CC) $(OBJ) -o $(TAR)
%.o:%.c
$(CC) -c %.c -o %.o
.PHONY
clear:
rm -rf *.o $(TAR)
第四层 通配符
进一步省略,此处列举少量通配符
$^ :所有的依赖文件
$@:所有目标文件
$< :所有的依赖文件的第一个文件
CC:=arm-linux-gnueabihf-gcc -pthread
TAR:=main
OBJ:=main.o init.o send.o recv.o
$(TAR):$(OBJ)
$(CC) -o $@ $^ # $^表示所有依赖
%.o:%.c //符合此格式的上述依赖都会代入
$(CC) -c -o $@ $^ # $@表示目标%.o,$<表示第一个依赖%.c
.PHONY:
clean:
rm -rf *.o $(TAR) # make clean清除所有.o文件
第五层 函数
非专业基本不会用到,但作用超多,此处仅举例说明
$(foreach var,list,text) #对于list的每一个值,都执行text操作
$(filter pattern...,text) #在text中提取符合pattern格式的值
$(filter-out pattern...,text) #与上函数相反,提取不符合该格式的字符
$(wildcard pattern) #pattern定义了文件名的格式,wildcard取出其中存在的文件
$(patsubst pattern,replacement,text)#在列表中将pattern格式替换为replacement格式
对应示例:
A = a b c
B = $(foreach f,$(A),$(f).o) #将A中所有加上.o后缀
all:
@echo B = $(B) #输出结果B = a.o b.o c.o
C = a b c d/
D = $(filter %/,$(C)) #将符合%/格式的字符挑选出来
E = $(filter-out %/,$(C)) #将不符合的挑选出来
all:
@echo D = $(D)
@echo E = $(E) #D = d/ E = a b c
files = @(wildcard *.c)
all:
@echo files = $(files) #将所有符合.c格式的文件提取出来,利用此函数取出真实存在的文件
file2 = a.c b.c c.c e.c
file3 = $(wildcard $(files2))
all:
@echo files2 = $(files3) #由于e.c并不存在,故只有前三项打印出来
file = a.c b.c c.c e.c abc
dep_files = $(patsubst %.c,%.d,$(files)
all:
@echo dep_files = $(dep_files) #dep_files = a.d b.d c.d e.d abc abc不符合格式不替换
抛砖引玉,欢迎纠错补充。