共计 2473 个字符,预计需要花费 7 分钟才能阅读完成。
一、最简单的 Makefile
test : a.o b.o
gcc -o test a.o b.o
a.o : a.c
gcc -c -o a.o a.c
b.o : b.c
gcc -c -o b.o b.c
- 要生成 test 依赖 a.o b.o
- a.o 生成依赖于 a.c
gcc -c -o a.o a.c
- b.o 生成依赖于 b.c
gcc -c -o b.o b.c
二、简单的 Makefile 语法
使用通配符
- 可以匹配任意个 c 文件
$@
:表示目标文件 $<
:表示第一个依赖文件$^
:表示 所有的 依赖文件
test : a.o b.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $<
清除文件
test : a.o b.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $<
clean:
rm *.o test
.PHONY: clean
make clean
:指定执行 clean,不指定默认执行第一个目标.PHONY
:不加的话如果有同名目标文件就无法执行
变量
A := xxx
:A 的值即可确定B = xxx
:B 的值使用到时才确定?=
:延时变量,如果是第一次定义才有效,如果之前定义过则忽略+=
:附加,延时变量还是即时变量取决于前面@
:不显示命令本身make D=1234
:给变量传递值
A := $(C)
B = $(C)
#C = abc
D = first
D ?= Second
all:
@echo $(A)
@echo $(B)
@echo $(D)
C = abc
输出
root@ubuntu_armv4:~/mini2440_v2/makefile# make
root@ubuntu_armv4:~/mini2440_v2/makefile# make
abc
first
- 可以看出 A 为空,B 为 abc
- C 的前后顺序没有影响
- ?= 第一次定义才有效
函数
$(foreach var,list,text)
:遍历 list,每个值为 var
A = a b c
B = $(foreach f, $(A), $(f).o)
all:
@echo B = $(B)
输出:B = a.o b.o c.o
$(filter pattern...,text)
:在 text 中选出匹配 pattern 的项$(filter-out pattern...,text)
:在 text 中选出除了匹配 pattern 的项
C = a b c d/
D = $(filter %/, $(C))
E = $(filter-out %/, $(C))
all:
@echo $(D)
@echo $(E)
root@ubuntu_armv4:~/mini2440_v2/makefile# make
d/
a b c
$(wildcard pattern...)
:寻找当前目录下符合 pattern 的文件
files = $(wildcard *.c)
files2 = a.c b.c e.c g.c
files3 = $(wildcard $(files2))
all:
@echo files = $(files)
@echo files3 = $(files3)
输出
files = a.c b.c
files3 = a.c b.c
file3= 从 file2 中选出当前目录存在的文件
$(patsubst pattern,replacement,text)
:在 text 中符合 pattern 的值替换成 replacement
files = a.c b.c e.c g.c
dep_files = $(patsubst %.c, %.d, $(files))
all:
@echo dep_files = $(dep_files)
输出dep_files = a.d b.d e.d g.d
三、Makefile 实例分析
gcc -M c.c
:可以看到 c.c 的依赖
# 输出
root@ubuntu_armv4:~/mini2440_v2/makefile# gcc -M c.c
c.o: c.c /usr/include/stdc-predef.h /usr/include/stdio.h \
/usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
/usr/include/x86_64-linux-gnu/bits/wordsize.h \
/usr/include/x86_64-linux-gnu/gnu/stubs.h \
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h \
/usr/include/x86_64-linux-gnu/bits/types.h \
/usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h \
/usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
/usr/include/x86_64-linux-gnu/bits/sys_errlist.h c.h
gcc -M -MF c.d c.c
:把 c.c 的依赖写入 c.dgcc -c -o c.o c.c -MD -MF c.d
:把 c.c 的依赖写入 c.d 同时编译 c.cCFLAGS = -Werror
:编译选项,把所有警告当作错误 CFLAGS = -Iinclude
:指定当前目录 include 文件夹为编译器默认头文件目录
代码
objs = a.o b.o c.o
dep_files := $(patsubst %, .%.d, $(objs))
dep_files := $(wildcard $(dep_files))
CFLAGS = -Werror -Iinclude
test : $(objs)
gcc -o test $^
ifneq ($(dep_files),)
include $(dep_files)
endif
%.o : %.c
gcc $(CFLAGS) -c -o $@ $< -MD -MF .$@.d
clean:
rm *.o test
distclean:
rm $(dep_files)
.PHONY: clean