make的隐式规则

问题

如果同一个目标的命令拆分写到不同地方,会发生什么?

下面的程序怎么执行?为什么?

make的隐式规则

makefile 中出现同名目标时

依赖:

  • 所有的依赖合并在一起,成为目标的最终依赖

命令:

  • 当多处出现同一目标的命令时,make 发出警告
  • 所有之前定义的命令被之后定义的命令取代

注意事项

当使用 include 关键字包含其他文件时,需要确定被包含文件中的同名目标只有依赖,没有命令;否则,同名目标的命令将被覆盖!

命令的拆分

makefile


.PHONY : all

var := test_var

all :
	@echo "this is $(var)"

include 1.mk

1.mk

.PHONY : all

all :
	@echo "this is command from 1.mk"

include 将 1.mk 文件内容包含进来后,当前 makefile 中 all 目标对应的命令定义在2个不同的地方,前面 all 所定义的命令会被后面定义的命令所取代。

执行结果如下所示:

make的隐式规则

 make 首先发出警告,随后执行后面定义的 all 的命令。

什么是隐式规则 (built-in rules)

make 提供了一些常用的,例行的规则实现

当相应目标的规则未提供时,make 尝试使用隐式规则

下面的 makefile 能编译成功吗?为什么?

make的隐式规则

初探隐式规则 

make 提供了生成目标文件的隐式规则

隐式规则会使用预定义变量完成编译工作

改变预定义变量将部分改变隐式规则的行为

当存在自定义规则时,不再使用隐式规则

初探隐式规则

makefile


SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
TARGET := app.out
CC := gcc

all :
	@echo "$(.VARIABLES)"

$(TARGET) : $(OBJS)
	$(CC) -o $@ $^
	$(RM) $^
	@echo "succsee target => $@"

%.o : %.c
	$(CC) -o $@ -c $^

在执行 make 的时候,make 发现我们并没有给 .VARIABLES 和 RM 变量赋值,所以 make 会通过隐式规则使用预定义变量完成编译工作。

深入理解隐式规则

当 make 发现目标的依赖不存在时

  • 尝试通过依赖名逐一查找隐式规则
  • 并且通过依赖名推导可能需要的源文件

make的隐式规则

隐式规则的副作用 

编译行为难以控制

  • 大量使用隐式规则可能产生意想不到的编译行为

编译效率低下

  • make 从隐式规则和自定义规则中选择最终使用的规则

隐式依赖链

当依赖的目标不存在时,make 会极力组合各种隐式规则对目标进行创建,进而产生意料之外的编译行为!

make的隐式规则

问题 

makefile 提供了多少隐式规则?如何查看隐式规则?

查看隐式规则

查看所有:make -p

查看具体规则:make -p | grep "XXX"

make的隐式规则

深入理解隐式规则 

makefile


app.out : main.o func.o
	$(CC) -lstdc++ -o $@ $^ 

当前目录下的文件如下所示:

make的隐式规则

app.out 依赖于 main.o 和 func.o,make 发现当前 makefile 中没有生成 main.o 和 func.o 的规则,所以 make 会使用隐式规则,尽力生成 main.o 和 func.o

执行结果如下所示:

make的隐式规则

 make 使用了隐式规则尽力去生成目标的依赖。

 

隐式规则的禁用

局部禁用

  • 在 makefile 中自定义规则
  • 在 makefile 中定义模式 (如:%.o:%.p)

全局禁用

  • make -r

后缀规则简介

后缀规则是旧式的 "模式规则"

可以通过后缀描述的方式自定义规则

make的隐式规则

双后缀规则 

定义一对文件后缀 (依赖文件后缀和目标文件后缀)

  • 如:.cpp.o <=> %.o : %.cpp

单后缀规则

定义单个文件后缀 (源文件后缀)

  • 如:.c <=> % : %.c

关于后缀表达式的注意事项

后缀规则中不允许有依赖

后缀规则必须有命令,否则无意义

后缀规则将逐步被模式规则取代

后缀规则初体验

makefile


app.out : main func.o
	 $(CC) -lstdc++ -o $@ $^

.c.o :
	@echo "my suffix rule"
	$(CC) -o $@ -c $^
	
.c :
	@echo "my suffix rule"
	$(CC) -o $@ -c $^

当前目录下的文件如下所示:

make的隐式规则

执行结果如下所示:

make的隐式规则

可以看出 main 是由当前 makefile 的后缀规则创建出来的,但是当前 makefile 没有生成 func.o 的规则,所以 make 使用隐式规则去生成 func.o。

上一篇:centos7 kafka安装


下一篇:k8s二进制安装-8,安装docker