make 是一个工具程序,通过读取 Makefile 文件,实现自动化软件构建。虽然现代软件开发中,集成开发环境已经取代了 make,但在 Unix 环境中,make 仍然被广泛用来协助软件开发。make 不仅仅用来编译 C/C++ 程序,还可以用来实现任何输入文件和结果文件的转化。
Makefile 语法
Makefile 文件由一组 rules (规则)构成,每个 rule 有如下形式:
targets : prerequisities
recipe
recipe
recipe
- targets:目标是文件名或操作名(也称为“伪目标”,phony target)。目标通常是一个,多个目标之间用空格分隔。
- prerequisities:前置条件定义了构建目标文件的依赖。多个依赖文件(也可以是伪目标)用空格分隔。
- recipe:每一行配方的起首是 tab 键,而不是空格。
如果存在 targets 同名的文件,make 不会执行。这是需要加上 .PHONY
.PHONY: clean
clean:
rm *.o temp
1. 变量
可以在 Makefile 中使用变量。引用变量的方法是:$(变量名)
files = file1 file2
some_file: $(files)
echo "Look at this variable: " $(files)
赋值运算符可以是:=,=:,?=,
- = 只有在命令使用到该变量时,才执行赋值操作。在此之前,变量会原封不动地记录赋值语句右边的表达式。(recursively-expanded variable)
- =: 赋值语句立刻执行。如果该赋值语句右边表达式中含有变量,则该变量只有定义在赋值语句之前才会被应用。(simply-expanded variable)
- ?= 赋值前会检查变量是否已经被赋值。如果已赋值则不执行此次赋值,否则执行
# Recursively expanded variable. This will print "later" below
one = one $(later_variable)
# Simply expanded variable. This will not print "later" below
two := two $(later_variable)
later_variable = later
.PHONY: all
all:
echo $(one)
echo $(two)
one = hello
one ?= will not be set
two ?= will be set
.PHONY: all
all:
echo $(one)
echo $(two)
2. 指令
include
include 指令会使 make 程序停在当前 makefile 文件读取位置,而先去读取指定文件,再继续读。
-include 同 include,但文件不存在时不会报错
include Makefile.common
控制流指令
ifeq 如果相等
ifneq 如果不相等
ifeq ($(CC), gcc)
libs=$(libs_for_gcc)
else
libs=$(normal_libs)
endif
3. Recipes
回声(echoing)
make 默认会在执行前,打印这一行 recipe 后执行。但如果 recipe 是 @ 开头,则不会打印
.PHONY: assets
assets:
@echo ">> writing assets"
4. 函数
字符操作函数
# firstword
# 打印 foo
$(firstword foo bar)
# word N
# 打印 bar
$(word 2, foo bar baz)
# wildcard FILENAMES
# 打印所有 markdown 文件,用空格隔开
$(wildcard *.md)
shell 函数
shell 函数执行 shell 后面跟着的参数,并把执行结果作为返回(command expansion)
go = $(shell go version)
.PHONY: all
all:
echo $(go)
5. 参考文档
阮一峰:Make 命令教程
GNU Make Manual