标签:排版 联系 默认 就会 运算符 计算 command version rri
目录
语法:
targets : prerequisites
command
...
或
targets : prerequisites ; command
command
其中:
target为生成目标, 一般使用文件名或伪目标作为target, 多个target用空格分开,可使用通配符。 除了指定要生成的target, 其他target若没有被依赖则不会执行。要生成的target通过make target命令指定, 不指定则第一个target为默认target。
prerequisite可以是target、文件, 若prerequisite有同名的target, 会先按规则执行同名target下的command。
command 如果在新行必须以Tab
开头; 若一行有多条语句, 用分号;
分隔。(以Tab开头的都会被当做command, 所以Makefile其他语句前不能使用Tab, 排版应使用空格)
command结果只对当前行有效(每行command处于不同进程下)。例子:
exec:
cd /home/raina
pwd # 没有切换路径, 仍是当前目录
exec:
cd /home/raina; pwd # 成功切换到/home/raina
规则:
Makefile使用make
命令运行, 将Makefile文件名保存成Makefile或makefile, 然后在终端运行make
命令, 会寻找当前目录下的Makefile或makefile文件, 自动运行。
make -n
# 仅显示命令, 不执行命令
make -s
# 禁止所有命令语句本身的显示
make -f xxx
# 指定makefile文件为xxx
make -t
# 更新目标文件时间
make -q
# 寻找目标是否存在, 存在不会输出, 不存在打印错误信息
make -B
# 所有目标都需要重新编译
make -c dir
# 指定读取Makefile的目录
make -e
# 环境变量将覆盖Makefile内定义的变量
make -I dir
# 添加头文件查找路径
make -r
# 禁止make任何隐含规则
make -R
# 禁止make使用任何作用于变量上的规则
Makfile文件内容:
test : main.o
gcc -o test main.o
main.o : main.c
gcc -c -o main.o main.c
test
main.o
有对应的生成规则, 转去main.o:main.c
gcc -c -o main.o main.c
; 若main.o比main.c新, 下面给的command就不会执行gcc -o test main.o
, 否则不执行。在make的过程中,如果没有依赖的生成规则, 路径下也没有该依赖文件,或者command执行出错,make会直接退出。
单行注释: #
换行符: \
转义字符: \
(若要转义’\(‘符号, 需要用`\)$`表示)
通配符: Makefile支持shell的*
、?
、[...]
通配符;
模式匹配符: %
不显示命令: @
, 执行的command语句默认会被显示到中断, 若不希望make执行过程中显示某command, 则在前面添加@
符号:
all:
@echo hhhhhh
定义:
var = value
变量在声明时必须赋初值, Makefile没有数据类型, 变量的定义类似与C/C++的宏, 但是可以改变其值。
例子:
# 若当前目录下有a.o、b.o、c.o三个文件
objs = *.o
# objs的值就是*.o, 而不是通配符展开后的结果
Makefile变量定义的位置没有要求, 可以使用后面定义的变量。
变量的命名规则:
:
#
=
空字符
使用:
$var
$(var)
${var}
若使用没有定义的变量, 其值将为空。
若变量的值有多行, 使用define ... endef
来定义:
define var # var为变量名
val-part1 # var的值
val-part2
...
endef
在命令行定义变量:
make var=value
注意:
等号两边不能加空格;
若Makefile文件中有和命令行变量同名的变量, 在Makefile中改变该变量值的语句会被忽略(包括define的多行值的变量和目标变量);
在Makefile若要修改命令行变量的值, 需在前面添加override 提示符:
override var=value
自动化变量 | 说明 |
---|---|
$@ | 表示target |
$< | 表示第一个prerequisite |
$^ | 所有的prerequisite的集合, 空格分隔, 重复的prerequisite会合并 |
$+ | 所有的prerequisite, 空格分隔, 重复的prerequisite不合并 |
$? | 所有比target新的prerequisite的集合, 以空格分隔 |
模式变量: 包含%
的变量。
使用:
类似与shell的*
通配符:
%.o : CFLAG = -o # 定义一个目标变量, 作用于以’.o‘结尾的target
Makefile静态模式规则:
%.o: %.c # %.c中%的值为target与%.o匹配到的%的值
gcc -c $< -o $@
OBJS = a.o b.o
all: $(OBJS) c.o
# 仅对OBJS内的元素有效, c.o不会匹配此规则
$(OBJS): %.o: %.c # a.o的依赖为a.c, b.o的依赖为b.c
gcc -c $< -o $@
目标变量仅在作用的target范围内有效, 类似于局部变量。
定义目标变量只需在变量定义前加其作用的target和冒号:
main : CFLAGS = -o # 仅在main目标范围内有效
main.o : CFLAGS = -c -o # 仅在main.o目标范围内有效
main : main.o
gcc $(CFLAGS) main main.o # gcc -o main main.o
main.o : main.c
gcc $(CFLAGS) main.o main.c # gcc -c -o main main.o
$(CURDIR)
: 当前所在路径
$(MAKE_VERSION)
: make的版本号
=
基本的赋值, 若变量后面被重新赋值, 会被覆盖
x = 1
y = $(x)
all:
echo $(y) # 2
x = 2
:=
若右值含变量, 则使用当前位置该变量的值(而不是整个Makefile展开后的值)
x = 1
y := $(x)
all:
echo $(y) # 1
x = 2
+=
追加变量的值(会用空格分隔)
var = a
var += b
all:
echo $(var) # a b
.PHONY
用于标记伪目标, 被标记为伪目标的target, 即使当前路径下target已经存在且为最新, 也会执行下面的command。即伪目标一经调用, 一定执行。
例子:
.PHONY: clean cleanobj # 标记clean和cleanobj为伪目标
clean: cleanobj
rm -f main
cleanobj:
rm -f *.o
常见伪目标:
判断已定义:
ifdef var-name # var-name为变量名, 不加$
... # 不能用Tab锁紧, 只能使用空格
else # else分支可以没有
...
endif
判断未定义:
ifndef var-name
...
else
...
endif
判断相等:
ifeq (arg1, arg2)
# 或 ifeq 'arg1' 'arg2'
# 或 ifeq "arg1" "arg2"
...
else
...
endif
判断不相等:
ifneq (arg1, arg2)
# 或 ifneq 'arg1' 'arg2'
# 或 ifneq "arg1" "arg2"
...
else
...
endif
注意: make 是在读取 Makefile 时就计算条件表达式的值, 并根据条件表达式的值来选择语句, 所以, 最好不要把自动化变量(如“$@”等)放入条件表达式中, 因为自动化变量是在运行时才有的。
使用方法:
$(func args)
或
${func args}
常用函数:
$(subset from, to, text)
# 功能: 把字串text中的from字符串替换成to
# 返回值: 被替换后的字符串
$(patsubst pattern, replacement, text)
# 功能: 把text中符合pattern的元素替换成replacement
# 返回值: 被替换后的字符串
$(dir paths)
# 功能: 取出每个path的所在目录(最后一个/及之前的内容, 没有/为当前目录)
# 多个path用空格分开
# 返回值: 返回所在目录, 当前目录返回./
$(notdir paths)
# 功能: 取出每个path的文件命名
# 返回值: 取到的文件名
此文原创禁止转载,转载文章请联系博主并注明来源和出处,谢谢!
作者: Raina_RLN https://www.cnblogs.com/raina/
标签:排版 联系 默认 就会 运算符 计算 command version rri
原文地址:https://www.cnblogs.com/raina/p/12342043.html