一、makefile规则
目标文件:依赖
<tab>命令
当“依赖”比“目标文件”新,执行命令
命令被执行的 2 个条件:1)依赖文件比目标文件新;2)目标文件还没生成
test:a.o b.o //test是目标,a.o,b.o为依赖
gcc -o test a.o b.o //生成a.o,b.o的命令
a.o:a.c
gcc -c -o a.c
b.o:b.c
gcc -c -o b.c
touch a.c b.c
//touch命令可以更新a.c、b.c的时间戳
二、makefile的语法
通配符:%.o
$@:表示目标文件
$<:表示第一个依赖文件
$^:表示所有依赖文件
$(CFLAGS)表示引用变量CFLAGS
%.o : %.c
gcc $(CFLAGS) -c -o $@ $< -MD -MF .$@.d
三、使用makefile
make [目标] 如make clean
若无目标,默认执行第一个目标
如果当前目录下恰好有名为“clean”的文件,那么执行“make clean”时它就不会执行那些删除命
令。这时我们需要把“clean”这个目标,设置为“假想目标”,这样可以确保执行“make clean”时那些
删除命令肯定可以得到执行。
.PHONY:clean
四、变量
简单变量(即时变量)
A := xxx //A的值在定义时就已经确定
延时变量
B = xxx //B的值使用时才确定
1):= //即时变量
2)= //延时变量
3)?= //延时变量,如果是第一次定义时才有效,在前面已经定义则忽略
4)D += yyy // 如果 D 在前面是延时变量,那么现在它还是延时变量
// 如果 D 在前面是立即变量,那么现在它还是立即变量
A=123
B:=abc
all:
echo A=$(A)
echo B=$(B)
$(变量名)表示引用变量,若不想显示命令,可以用@echo A=$(A)
五、依赖文件的写入
gcc -M c.c //打印出依赖
gcc -M -MF c.d c.c //把依赖写入文件c.d
gcc -c -o c.o c.c -MD -MF c.d //编译c.o,把依赖写入文件c.d
六、支持查询头文件的makefile
# 定义目标文件
objds := main.o sub.o
# 获取依赖文件列表
objds_yilai := $(foreach f,$(objds),.$(f).d) //注意不要将文件名搞错
objds_yilai := $(wildcard $(objds_yilai))
CFLAGS = -Werror -Iinclude
# 主目标
test : $(objds)
gcc -o test $^
# 包含依赖文件
ifneq ($(objds_yilai),)
include $(objds_yilai)
endif
# 规则:生成.o文件并生成依赖文件
%.o : %.c
gcc $(CFLAGS) -c -o $@ $< -MD -MF .$@.d
# 清理目标
clean:
rm -f *.o test $(objds_yilai)
.PHONY: clean
CFLAGS指编译选项,将所有编译参数都放到CFLAGS变量,方便阅读
-Werror 指将所有警告都当做错误,-Iinclude 将头文件目录指定为include
七、make命令的使用
执行 make 命令时,它会去当前目录下查找名为“Makefile”的文件,并根据它的指示去执行操
作,生成第一个目标。
可以使用“-f”选项指定文件,不再使用名为“Makefile”的文件,比如:
make -f Makefile.build
可以使用“-C”选项指定目录,切换到其他目录里去,比如:
make -C a/ -f Makefile.build //指定a目录
可以指定目标,不再默认生成第一个目标
make -C a/ -f Makefile.build other_target
八、变量的导出
在编译程序时,我们会不断地使用“make -C dir”切换到其他目录,执行其他目录里的
Makefile。如果想让某个变量的值在所有目录中都可见,要把它export 出来。
CC = $(CROSS_COMPILE)gcc
如上,这个 CC 变量表示编译器,在整个过程中都是一样的。定义它之后,要使用“export
CC”把它导出来。
九、Makefile 中可以使用 shell 命令:
TOPDIR := $(shell pwd)
这是个立即变量,TOPDIR 等于 shell 命令 pwd 的结果。