gcc编译
基本规则
预处理、编译、汇编、链接
gcc -o test a.c b.c #生成test可执行文件
先预处理、编译、汇编,再链接
gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -o test a.o b.o
命令
-MF -MD
:将依赖写入到指定文件
gcc -c -o c.o c.c -MF -MD c.d #编译c.o, 并将c.c的依赖写入到c.d
-CFLAGS
:编译参数,[-D]添加宏定义,[-Werror]将编译警告转为报错,[-I]指定默认头文件路径
CFLAGS:-DDEF -IINC -Werror
gcc -o test a.c a.o -CFLAGS
makefile基本语法
基本规则
若依赖文件比目标文件新,或者目标文件不存在,则执行命令
若make后不加参数,默认执行第一个目标
目标文件:依赖文件
命令
test:a.o b.o
gcc -o test a.o a.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
gcc -o test $^
%.o:%.c
gcc -o -c $@ $<
假想目标
若当前路径下存在名字为clean
的文件,执行make clean
命令时,根据makefile规则只有当文件不存在时才会执行,因此若没有使用假想目标,makefile就不会执行clean
对应的命令,所以需要假想目标
.PHONY:clean
clean:
rm *.o test
变量
A := xxx #A的值在定义时即确定
A = xxx #A的值会在使用的时候才确定,即A的值时对文件中所有对A值处理后的结果
A ?= xxx #如果之前没有定义过当前赋值才起作用,相当于默认值
A += xxx #在原来基础上追加
函数
A = $(foreach f, $(list), opt) #遍历list的值到f,对每个f值做opt操作
B = $(filter %t, $(list)) #从list列表中,取出不符合t格式的变量
C = $(filter-out %t, $(list)) #从list列表中,取出不符合t格式的变量
D = $(wildcard *.t) #找出当前路径中.t格式的文件
E = $(patsubst %t, %replace, $(list)) #从list列表中,将符合t格式的变量替换成replace格式
实例分析
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