第15课 - make的隐式规则(上)

1. 问题

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

执行make all

  

  这个实验表明了:如果同一个目标的命令拆分的写到不同地方,那么 make 会覆盖之前的目标对应的命令使用最新出现的目标对应的命令

 

makefile 中出现同名目标时

  — 依赖:

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

  — 命令:

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

注意事项:当使用 include 关键字包含其它文件时,需要确保被包含文件中的同名目标只有依赖没有命令;否则,同名目标的命令将被覆盖

     tar get 的下一行,以 tab 开头,该行也会被当做一条空命令

下面的示例代码就是当主makefile包含了其它makefile导致目标重名引发了 bug

  

运行结果:

  

 

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

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

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

 

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

    

 

对应的源文件如下:

main.c

#include <stdio.h>

extern void foo();

int main()
{
    foo();
    
    return 0;
}    

 

 

func.c

#include <stdio.h>

void foo()
{
    printf("void foo() : %s\n", "Hello World");
}

 

 

makefile.2

SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)

app.out : $(OBJS)
    $(CC) -o $@ $^
    $(RM) $^
    @echo "Target ==> $@"

 

 

执行 make app.out 成功得到 app.out 可执行程序。

  

这个 Makefile 中没有 .o 中间文件对应的规则也没有定义 CC 和 RM 变量,但是 make 成功执行并且生成了最终的 app.out 这个可执行程序。这表明了 make 调用了隐式规则中的 cc  -c  -o  xx.o  xx.c 以及 CC  RM 变量

 

修改上面的Makefile

SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)

app.out : $(OBJS)
    $(CC) -o $@ $^
    $(RM) $^
    @echo "Target ==> $@"

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

执行 make app.out 后的输出,这就验证了之前的隐式规则

  

 

修改上面的Makefile

SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)

CC := gcc

all :
    @echo "$(.VARIABLES)"

app.out : $(OBJS)
    $(CC) -o $@ $^
    $(RM) $^
    @echo "Target ==> $@"

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

 

执行 make all的运行结果:

  

 

 

cc代表的含义:

  

 

 

 

3. 初探隐式规则

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

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

  make 中的 .VARIABLES 预定义变量中包含了 make 的其它预定义变量

  echo  "$(.VARIABLES)"  

     

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

(4)当已经存在自定义规则时不再使用隐式规则

 

4. 小结

(1)当多处出现同一目标的命令时,只有最后定义的命令有效

(2)make 提供了一系列的隐式规则可使用

(3)当makefile中未定义相关规则时,make 尝试使用隐式规则

(4)隐式规则中可能使用make中的预定义变量

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

 

posted @ 2018-09-06 00:00  梦心之魂  阅读(257)  评论(0编辑  收藏  举报