Makefile 易忘规则记录
主要用于记录一些Makefile中容易忘记的规则等
粗略规则
target... : prerequisites ...
[tab] command
...
易忘规则
伪目标声明
.PHONY: clean
clean:
[tab] rm ./*.o
自动推导
a.o 的缺省依赖 a.c
注释
Makefile 中只有行注释
p := /home/wangha #注释
当注释以上面方式时,要注意,p实际上为'/home/wangha ',后面是携带着空格的
命令
命令的执行必须以[TAB]开头,除非命令是紧跟在依赖规则的';'后面的
引用其他Makefile
include <filename1> <filename2> #允许使用通配符
-include <*.h> # 忽略无法读取的文件
指定目录搜寻头文件或依赖文件
VPATH = src:../others # src和../others
vpath的三种用法
-
vpath <pattern> <directories>
为符合pattern的文件在directories上也进行搜索
-
vpath <pattern>
清除符合pattern的文件的搜索目录
-
vpath
清除所有已被设置好的文件搜索目录
多目标中的$> $@
$> 表示多目标中对应的依赖
$@ 表示多目标中对应的目标
替换
source = foo.c bar.c
include $(source:.c=.d) # 转化为foo.d bar.d
include $(source:%.c=%.d) # 静态模式的转换
命令执行
exec:
[TAB] :cd /home/abc; pwd # 只有在一行时才会有效
exec2:
[TAB] : cd/home
[TAB] : pwd # 依旧是Makefile的目录下
忽略ERROR
方式一:
-command 加上'-'后,不管出错与否,继续执行
方式二:
全局忽略,make的参数中加'-i'或者'--ignore-errors'
嵌套执行的变量传递
export <var1 ...>;
仅仅局限于传递到下层的Makefile
如果传递所有变量 则只需要export即可
等于号
= 普通的定义变量,但存在着递归定义的问题
:= 修复了递归定义问题,但前面的变量不能使用后面的变量,如
a := $(b) a.o #a的实际值是a.o
b := b.o
?= 例如b?=bar
,如果b已经定义过了,则什么也不做
变量嵌套
x = $(y)
y = z
z = Hello
a := $($(x))
此处a应该为Hello,自行推导
override的使用
在make的时候,会指定一些参数,在Makefile中对这些变量赋值是会被忽略的,如果希望修改,则需要使用override,语法i如下
override <var1>; =<value>;
override <var1>; +=<more>;
override define foo
bar
endef
define的使用
define double-echo
echo abc
echo $(abc)
endef
局部变量
a := bar.c
tmp : a:=foo.c
tmp : $(a)
[TAB] gcc -o b.o $(a) #在tmp的范围内,a为foo.c
模式变量
%.o : CFLAGS = -O
使用时
a.o: a.c
[TAB] : $(CC) $(CFLAGS) a.o a.c
上述例子为,给所有的 .o 文件,在编译时候,自动添加-O
条件关键词
-
ifeq
ifeq (<arg1>, <arg2>) ifeq '<arg1>' '<arg2>' ifeq "<arg1>" "<arg2>" ifeq "<arg1>" '<arg2>' ifeq '<arg1>' "<arg2>"
-
ifneq
用法同上
-
ifdef
foo = ifdef foo frobozz = yes else frobozz = no endif
上述例子,由于foo没有赋值,故 frobozz为no
-
ifndef
用法同上
函数的调用
$(func-name argus)
例子:将空格全部转换为','
comma:= ,
empty:=
space:= $(empty) $(empty)
foo:= a b c
bar:= $(subst $(space),$(comma),$(foo))
foreach函数
$(foreach <var>,<list>,<text>)
功能:对list中的每一个赋值给var,并执行text
例子:
names := a b c d
files := $(foreach n,$(names), $(n).o)
files 的值为a.o b.o c.o d.o
if函数
$(if <condition>,<then-part>)
$(if <condition>,<then-part>,<else-part>)
返回值,如果 <condition>
为真(非空字符串),那个 <then-part>
会是整个函数的返回值,如果 <condition>
为假(空字符串),那么 <else-part>
会是整个函数的返回值。如果 <else-part>
没有被定义,那么,整个函数返回空字串。
call函数
$(call <expression>,<parm1>,<parm2>,...,<parmn>)
返回值: <expression>
的返回值就是 call 函数的返回值
例子 foo=a b
reverse = $(1) $(2)
foo = $(call reverse,a,b)
origin函数
$(origin <variable>)
功能:告诉你这个变量是哪里来
返回值:
undefined: 如果 <variable>
从来没有定义过
default: 如果 <variable>
是一个默认的定义,比如“CC”这个变量
environment: 如果 <variable>
是一个环境变量,并且当Makefile被执行时, -e
参数没有被打开。
file: 如果 <variable>
这个变量被定义在Makefile中。
command line: 如果 <variable>
这个变量是被命令行定义的。
override: 如果 <variable>
是被override指示符重新定义的。
automatic: 如果 <variable>
是一个命令运行中的自动化变量。
常用于 :判断当前的这个变量到底来自于哪里
例子:
ifdef bletch
ifeq "$(origin bletch)" "environment"
bletch = barf, gag, etc.
endif
endif
shell函数
调用/bin/sh来执行一些功能
contents := $(shell cat foo)
控制make的函数
$(error <text ...>)
$(warning <text ...>)
可用于检测Makefile运行时的信息,决定你继续执行OR报Error或者Warning和停止
例子,当发现有ERROR_001时,报错
ifdef ERROR_001
$(error error is $(ERROR_001))
endif
make的退出码
0-succeed
1-error
2-如果你使用了make的“-q”选项,并且make使得一些目标不需要更新
指定Makefile
make -f 123.mk
指定目标
推荐采取以下方式
.PHONY: all
all: prog1 prog2 prog3 prog4
makefile中的目标生成参照规则
- all:这个伪目标是所有目标的目标,其功能一般是编译所有的目标。
- clean:这个伪目标功能是删除所有被make创建的文件。
- install:这个伪目标功能是安装已编译好的程序,其实就是把目标执行文件拷贝到指定的目标中去。
- print:这个伪目标的功能是例出改变过的源文件。
- tar:这个伪目标功能是把源程序打包备份。也就是一个tar文件。
- dist:这个伪目标功能是创建一个压缩文件,一般是把tar文件压成Z文件。或是gz文件。
- TAGS:这个伪目标功能是更新所有的目标,以备完整地重编译使用。
- check和test:这两个伪目标一般用来测试makefile的流程。
检查规则
-n: 不执行参数,这些参数只是打印命令,不管目标是否更新,把规则和连带规则下的命令打印出来,但不执行,这些参数对于我们调试makefile很有用处。
-t: 这个参数的意思就是把目标文件的时间更新,但不更改目标文件。也就是说,make假装编译目标,但不是真正的编译目标,只是把目标变成已编译过的状态。
-q: 这个参数的行为是找目标的意思,也就是说,如果目标存在,那么其什么也不会输出,当然也不会执行编译,如果目标不存在,其会打印出一条出错信息。
-W <file>: 这个参数需要指定一个文件。一般是是源文件(或依赖文件),Make会根据规则推导来运行依赖于这个文件的命令,一般来说,可以和“-n”参数一同使用,来查看这个依赖文件所发生的规则命令。