makefile #
make 不带参数,只会执行 makefile 中第一条 target 声明
(带冒号的语句)
简介 #
Makefile 用于定义如何创建目标文件,比如如何从源码到可执行文件。 创建这一工具的目标是 减少不必要的编译或者任务。 传说 Stuart Feldman 在 1976 年花了一个周末写出来的, 而今仍然使用广泛,特别是在 Unix 和 Linux 系统上。
基础 #
语法 #
- 注释:
#
- 文件名: 必须是
Makefile
- 区分大小写
make <target>
生成 target- 重命名:
make -f "filename" <target>
- 重命名:
- 只认识
TAB
,不认识空格- 但是在 GNU Make 3.82 之后, 可以通过设置参数
.RECIPEPREFIX
进行修改
- 但是在 GNU Make 3.82 之后, 可以通过设置参数
- shell 符号
@
:不把命令打印到 stdout-
:发生错误了也没关系
$$
$
是 make 变量$$
是 shell 变量
target 声明 #
- 创建一个
target
:targets : prerequisites recipe
prerequisites
(依赖) 是可选的,recipe
(做法) 也可以多个或者不给- 没有给 prerequisites, 只会在目标文件文件不存在时执行
- targets 和 prerequisites 都可以是多个, 以空格分割
file2.txt file3.txt: file0.txt file1.txt touch file2.txt touch file3.txt
- target 的声明顺序不重要
- 上面的依赖可以下面再声明
- 如果声明重复的
target
,make 会给一个 warning,后面会覆盖前面的- 但是如果不定义任何 recipe, 就不会冲突, 只是多了依赖关系
file2.txt: file0.txt file3.txt
- 但是如果不定义任何 recipe, 就不会冲突, 只是多了依赖关系
Phony
(假的) Targets- 意思是 tagets 并不是文件, 可以想象成一个任务的名字而已
- 因为不是文件, 无法比对是否有更新, 所以每次
make
都会执行 - 依赖于 phony target 的 target 也会每次 make 都执行, 即使 target 是文件
.PHONY
- 如果定义的 phony target 与文件名重名, 可以用 .PHONY 显式地指明哪些 targets 是 phony
常用 phony target #
all
clean
install
uninstall
变量与通配符 #
$^
: 代表 prerequisites# 即便分开定义依赖, $^ 依然能拿到 process: file*.txt # 非常智能的, ex1.txt 会被找到, file0.txt 会被去重 process: ex1.txt file0.txt @echo $^
$@
: 代表 target, 如果 target 为多个,$@
代表当前执行的那个$<
: prerequisite 中的第一个$?
: 需要更新的 prerequisite 文件列表$+
: 所有依赖, 包括重复的$|
: 竖线后面的order-only prerequisites
$*
:target
%
那部分, 包括路径a.%.b: # $* match 的target % 那部分, 包括路径, 比如 `make dir/a.foo.b` 会打出 `dir/foo` @echo $*
模式匹配 #
- make 会找到最具体的匹配
make small/foo.png
则会匹配下面这个规则(在这之前要先有 small/foo.svg 这个文件)%.png: %.svg inkscape --export-png $^ small/%.png: %.svg inkscape --export-png --export-dpi 30 $^
- make 已经有一些内置的规则, 比如从 _.c 到 _.o
竖线 #
- 竖线左边为:正常前提目标(
Normal Prerequisites
)- 当正常前提目标变化时,target 重新生成
- 可以为空
- 竖线右边为:命令前提目标(
order-only Prerequisites
)- 当命令前提目标变化时,target 不重新生成
process: file*.txt | dir/a.foo.b
变量 #
-
变量都是字符串类型
# 这俩是一样一样的 name = Ted name2="Sarah"
-
设置变量,按以下顺序由高到低:
- 命令行参数. 比如试试
make echo name3=JICHAO
- Makefile 里面的
- shell 中的环境变量
- make 预设的一些变量
- 命令行参数. 比如试试
-
?=
# 如果 name 被设置过了, 就不设置了 name ?= Jean
-
override
# 用 override 可以防止命令行参数设置的覆盖 override name = David ``
-
+
# 用加号可以连接 (中间用空格分割) name4 +=grey
-
内置的变量
echo_inbuilt: echo $(CC) echo ${CXX)} echo $(FC) echo ${CFLAGS)} echo $(CPPFLAGS) echo ${CXXFLAGS} echo $(LDFLAGS) echo ${LDLIBS}
-
:=
- 等号声明时 recursively expanded 递归扩展
- 加个冒号可以声明 Simply expanded variables 即时扩展变量, 即只在声明时扩展一次
# var3 声明时找不到 var4, var3 会扩展成 `and good luck`,直接忽视 var4 var3 := $(var4) and good luck # var5 是正常的,扩展为 `good night and good luck` var5 = $(var4) and good luck var4 := good night
函数 #
-
函数调用格式
$(func arg0,arg1,arg2...)
-
wildcard:将后面的通配符变成一串文件路径
-
patsubst:做替换
# 把所有 markdown 后缀的文件重命名为 md 后缀 substitue: * @echo $(patsubst %.markdown,%.md,$* $^)
指令 #
- include:引入别的 Makefile 文件
- 流程控制语句顶格写
sport = tennis # 流程控制语句 (如if else 等等) 顶格写 report: ifeq ($(sport),tennis) @echo 'game, set, match' else @echo "They think it's all over; it is now" endif
叶王 © 2013-2024 版权所有。如果本文档对你有所帮助,可以请作者喝饮料。