一、最简单的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