包含 最重要概念、函数、方法等的 make 备忘单。 初学者的完整快速参考。
a.txt: b.txt c.txt
cat b.txt c.txt > a.txt
Makefile
。include
的其它 Makefile
。文件会以 GNUmakefile
(不推荐使用)、Makefile
、makefile
查找目录下的名称。
$ make target -f NAME
我们可以使用 -f NAME
来指定需要编译的文件名
如果文件夹中没有 makefile 文件,只有 main.c 源文件,那么我们可以使用 make main.o
隐式生成链接文件
$ make main.o
# 实际执行: cc -c -o main.o main.c
TARGET: PREREQUISITES
COMMAMD
...
target
: 规则的目标。目标可以是规则的动作(如 clean
等),也可以是目标文件或者最后的可执行文件。prerequisites
: 规则的依赖。生成规则目标文件所需要的文件名列表(通常一个目标依赖于一个或者多个文件)。command
: 规则的命令行。规则要执行的动作(任意的 shell 命令或者在 shell 下执行的程序)。命令需要以 tab 键开头$ make [TARGET ...]
$ make # 没有参数首先运行 TARGET
$ make help # 显示可用目标
$ make dist # 从当前目录制作一个发布存档
$ make check # 无需安装的单元测试
.PHONY: clean
clean:
rm *.o temp
.PHONY
内置命令将排除 clean 文件,不会因为当前目录中因为有 clean 文件而不会不执行 clean 伪目标
clean 从来都是放在文件的最后
makefile 文件的注释与 bash 脚本一致
# 这是一个注释
main.o : main.c
cc -c main.c
\
# 这是一个注释
main.o : main.c
cc -c \
main.c
include
关键字可以把别的 Makefile 包含进来。这样使用 make 运行的时候就会
# makefile
include foo.make
如果你想让 make 不理那些无法读取的文件,并且继续执行。
-include <filename>
VARIABLE = value
可以防止递归,并且只能引用之前声明过的变量
VARIABLE := value
VARIABLE ?= value
VARIABLE += value
如果变量前不指定 override
,那么命令行中指定的变量可以对 Makefile 中的变量重新定义。
# 不会重新定义
override VARIABLE = value
override VARIABLE := value
override VARIABLE ?= value
override VARIABLE += value
override define
#...
endef
需要使用 $()
或者 ${}
对变量进行引用
file = main.c
run:
clang -o hello ${file}
# 这样会使变量陷入无穷递归
A = $(B)
B = $(A)
x := foo
y := $(x) bar
x := later
# 等价于
# x = later
# y = foo bar
如果要使用 Shell 变量,需要在之前加上 $
run:
echo $$HOME
define foo
echo foo
echo bar
endef
run:
${foo}
$@
$@
:指代当前目标,即 Make 命令当前构建的那个目标
foo:
touch $@
$ make foo
# $@ 就是指的这里的 foo
$<
$<
指代第一个前置条件。比如,规则为 t: p1 p2,那么 $<
就指代 p1
a.md: b.md c.md
cp $< $@
使用 make a.md
,相当于以下写法
a.md: b.md c.md
cp b.md a.md
$^
$^
指代所有的前置条件,去除重复项
a.md: b.md c.md
echo $^
$+
$^
指代所有的前置条件,不会去除重复项
a.md: b.md c.md c.md
echo $+
$?
$?
指代更新的依赖,只有最近更新过的依赖才会引用
a.md: b.md c.md c.md
cat $? > a.md
$*
$*
指代匹配符匹配的部分
main.o: main.c
clang -o $* $*.c
$ make main
# 此时 cc main.c -o main
$%
$%
: 仅当目标是函数库文件中,表示规则中的目标成员名
.lib
文件.a
文件这些变量都是相关下面的命令的参数。如果没有指明其默认值,那么其默认值都是空。
:- | :- |
---|---|
ARFLAGS | 函数库打包程序AR命令的参数。默认值是 rv |
ASFLAGS | 汇编语言编译器参数。(当明显地调用 .s 或 .S 文件时) |
CFLAGS | C 语言编译器参数。 |
CXXFLAGS | C++ 语言编译器参数。 |
COFLAGS | RCS 命令参数。 |
CPPFLAGS | C 预处理器参数。( C 和 Fortran 编译器也会用到)。 |
FFLAGS | Fortran 语言编译器参数。 |
GFLAGS | SCCS get 程序参数。 |
LDFLAGS | 链接器参数。(如:ld ) |
PFLAGS | Pascal 语言编译器参数。 |
LFLAGS | Lex 文法分析器参数。 |
RFLAGS | Ratfor 程序的 Fortran 编译器参数。 |
YFLAGS | Yacc 文法分析器参数。 |
:- | :- |
---|---|
AR | 函数库打包程序。默认命令是 ar |
AS | 汇编语言编译程序。默认命令是 as |
CC | C 语言编译程序。默认命令是 cc |
CXX | C++ 语言编译程序。默认命令是 g++ |
CO | 从 RCS 文件中扩展文件程序。默认命令是 co |
CPP | C 程序的预处理器(输出是标准输出设备)。默认命令是 $(CC) –E |
FC | Fortran 和 Ratfor 的编译器和预处理程序。默认命令是 f77 |
GET | 从 SCCS 文件中扩展文件的程序。默认命令是 get |
LEX | Lex 方法分析器程序(针对于 C 或 Ratfor)。默认命令是 lex |
PC | Pascal 语言编译程序。默认命令是 pc |
YACC | Yacc 文法分析器(针对于 C 程序)。默认命令是 yacc |
YACCR | Yacc 文法分析器(针对于 Ratfor 程序)。默认命令是 yacc –r |
MAKEINFO | 转换 Texinfo 源文件(.texi)到 Info 文件程序。默认命令是 makeinfo |
TEX | 从 TeX 源文件创建TeX DVI文件的程序。默认命令是 tex |
TEXI2DVI | 从 Texinfo 源文件创建 TeX DVI 文件的程序。默认命令是 texi2dvi |
WEAVE | 转换 Web 到 TeX 的程序。默认命令是 weave |
CWEAVE | 转换 C Web 到 TeX 的程序。默认命令是 cweave |
TANGLE | 转换 Web 到 Pascal 语言的程序。默认命令是 tangle |
CTANGLE | 转换 C Web 到 C。默认命令是 ctangle |
RM | 删除文件命令。默认命令是 rm –f |
run:
${CC} -o main main.c
*
*
:与 linux 系统下的一样
# 清除所有 .o 结尾的文件
clean:
rm -f *.o
~
~
:在 linux 或 mac 下表示用户目录,win 下表示 HOME
环境变量
run:
ls ~
?
?
: 与在 linux 等类似,可以匹配单个字符
run:
ls -ll packag?.json
vpath
)如果没有指定 vpath 变量,make 只会在当前的目录中去寻找依赖文件和目标文件。否则,如果当前目录没有,就会到指定的目录中去寻找
:- | :- |
---|---|
vpath <pattern> <directories> | 为符合模式 <pattern> 的文件指定搜索目录 <directories> |
vpath <pattern> | 清除符合模式 |
vpath | 清除所有已被设置好了的文件搜索目录 |
%
%
字符。%
的意思是匹配零或若干字符vpath %.c dist
TARGET = hello
OBJ = bar.o foo.o
$(TARGET): $(OBJ)
$(CC) -o $@ $^
%.o: $.c
$(CC) -o $< -o #@
TARGET: PREREQUISITES :PREREQUISITES
COMMAMD
#...
target
定义了一系列的目标文件prerequisites
是指明了 target 的模式,也就是的目标集模式。prerequisites
是目标的依赖模式,它对第一个 prerequisites
形成的模式再进行一次依赖目标的定义objects = foo.o main.o
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
相当于:
foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
main.o : main.c
$(CC) -c $(CFLAGS) main.c -o main.o
.PHONY
来显式地指明目标是 伪目标
.PHONY : clean
clean :
rm *.o temp
@
)正常情况下,make会打印每条命令,然后再执行,这就叫做回声(echoing)
all:
# 会有命令执行显示
echo Hello, world
all:
# 不会有命令执行的显示
@echo Hello, world
如果我们只希望显示命令,而不希望执行命令,可以使用 -n
或者 --just-print
$ make all --just-print
$ make all -n
-s
或 --silent
或 --quiet
与 @
一样,用于禁止回声
$ make all -s
使用 tab 及换行
exec:
cd /home/hchen
pwd
使用 ;
exec:
cd /home/hchen; pwd