makefile
转载自: http://www.cnblogs.com/wang_yb/p/3990952.html
通配符
* 表示任意一个或多个字符 ? 表示任意一个字符 [...] [abcd] 表示 a,b,c,d 中任意一个字符, [^abcd]表示除 a,b,c,d 以外的字符, [0-9]表示 0~9 中任意一个数字 ~ 表示用户的 home 目录
搜索路径
当前目录中找不到文件时, 按顺序从 src 目录 ../parent-dir 目录中查找文件
VPATH src:../parent-dir
.h 结尾的文件都从 ./header 目录中查找
VPATH %.h ./header
清除 .h 文件设置的规则
VPATH %.h
清除所有 VPATH 的设置
VPATH
变量
OBJS = programA.o programB.o OBJS-ADD = $(OBJS) programC.o
或者
OBJS := programA.o programB.o OBJS-ADD := $(OBJS) programC.o
其中 = 和 := 的区别在于, := 只能使用前面定义好的变量, = 可以使用后面定义的变量
变量追加
SRCS := programA.c programB.c programC.c SRCS += programD.c
变量替换
SRCS := programA.c programB.c programC.c OBJS := $(SRCS:%.c=%.o) all: @echo "SRCS: " $(SRCS) @echo "OBJS: " $(OBJS)
? make
SRCS: programA.c programB.c programC.c OBJS: programA.o programB.o programC.o
override
SRCS := programA.c programB.c programC.c all: @echo "SRCS: " $(SRCS)
? make SRCS=nothing
SRCS: programA.c programB.c programC.c
override SRCS := programA.c programB.c programC.c all: @echo "SRCS: " $(SRCS)
? make SRCS=nothing
SRCS: programA.c programB.c programC.c
目标变量
作用是使变量的作用域仅限于这个目标(target)
SRCS := programA.c programB.c programC.c target1: TARGET1-SRCS := programD.c target1: @echo "SRCS: " $(SRCS) @echo "SRCS: " $(TARGET1-SRCS) target2: @echo "SRCS: " $(SRCS) @echo "SRCS: " $(TARGET1-SRCS)
? make target1
SRCS: programA.c programB.c programC.c SRCS: programD.c
? make target2
SRCS: programA.c programB.c programC.c SRCS:
命令前缀
不用前缀 输出 执行的命令内容 + 命令执行的结果, 出错的话停止执行 前缀 @ 只输出命令执行的结果 (不输出命令内容), 出错的话停止执行 前缀 - 命令执行有错的话, 忽略错误, 继续执行
伪目标
.PHONY: clean (这句没有也行, 但是最好加上) clean: -rm -f *.o
约定的伪目标
伪目标 | 含义 |
---|---|
all | 所有目标的目标,其功能一般是编译所有的目标 |
clean | 删除所有被 make 创建的文件 |
install | 安装已编译好的程序,其实就是把目标可执行文件拷贝到指定的目录中去 |
列出改变过的源文件 | |
tar | 把源程序打包备份. 也就是一个 tar 文件 |
dist | 创建一个压缩文件, 一般是把 tar 文件压成 Z 文件. 或是 gz 文件 |
TAGS | 更新所有的目标, 以备完整地重编译使用 |
check 或 test | 一般用来测试 makefile 的流程 |
include
include PATH_TO/OTHER_FILE # 包含另外一个 makefile, 会自动执行一个 target
当前的 makefile 内容
var = abc.o def.o include test/makefile
test/makefile
abc: @echo $(var)
var
变量可以直接传递给 include
的文件, 正确的说法是 include
指令是把文件的内容引进当前
修改当前的 makefile 内容为
all: cd test && make
var
变量无法直接传递给 include
的文件
c 文件的依赖
gcc -MM kvm_main.c
kvm_main.o: kvm_main.c iodev.h coalesced_mmio.h async_pf.h <-- 这句就可以加到 Makefile 中作为编译 kvm_main.o 的依赖关系
自动推导
main : main.o gcc -o main main.o
会自动变为:
main : main.o gcc -o main main.o main.o: main.c # main.o 这个目标是推导生成的 gcc -c main.c
也可以简写为
main: main.o
默认的变量
变量名 | 含义 |
---|---|
RM | rm -f |
AR | ar |
CC | cc |
CXX | g++ |
ARFLAGS | AR 命令的参数 |
CFLAGS | C 语言编译器的参数 |
CXXFLAGS | C++语言编译器的参数 |
make CFLAGS=-Wall
那么在 makefile 里面就会变成
cc -Wall -c -o test.o test.c
自动变量
$@ | 目标集合 |
$% | 当目标是函数库文件时, 表示其中的目标文件名 |
$< | 第一个依赖目标. 如果依赖目标是多个, 逐个表示依赖目标 |
$? | 比目标新的依赖目标的集合 |
$^ | 所有依赖目标的集合, 会去除重复的依赖目标 |
$+ | 所有依赖目标的集合, 不会去除重复的依赖目标 |
$* | 这个是 GNU make 特有的, 其它的 make 不一定支持 |