1、makefile中出现同名目标时
- 同名依赖:所有的依赖将合并在一起,成为目标的最终依赖
- 同名命令:当多处出现同一目标的命令时,make发出警告;所有之前定义的命令被最后定义的命令取代
示例1–makefile中出现同名依赖
.PHONY : all
all : a.txt
all : b.txt
a.txt :
@echo "this is $@"
b.txt :
@echo "this is $@"
示例2–makefile中出现同名命令
.PHONY : all
all :
@echo "command-1"
all :
@echo "command-2"
all :
@echo "this is $@"
注意事项
- 当使用include关键字包含其它文件时,需要确保被包含文件中的同名目标只有依赖,没有命令;否则,同名目标的命令将会被最后定义的命令取代。
示例3–使用include关键字时,出现同名命令
makefile文件与1.mk文件位于同一个目录下
makefile
.PHONY : all
all :
@echo "this is $@"
include 1.mk
all :
@echo "this command from 1.mk"
2、隐式规则(build-in rules)
- make提供了一些常用的,例行的规则实现
- 当相应目标的规则未提供时,make尝试使用隐式规则
示例4–目标的规则未提供,make使用隐式规则
func.h
#ifndef FUNC_H
#define FUNC_H
#define HELLO "hello world"
void foo();
#endif
func.c
#include "stdio.h"
#include "func.h"
void foo()
{
printf("void foo():%s\n",HELLO);
}
main.c
#include "stdio.h"
#include "func.h"
extern void foo();
int main()
{
foo();
return 0;
}
makefile
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
app.out : $(OBJS)
$(CC) -o $@ $^
$(RM)
@echo "Target ===> $@"
makefile等价于下面的文件
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
app.out : $(OBJS)
$(CC) -o $@ $^
$(RM)
@echo "Target ===> $@"
%.o : %.c
@echo "rule"
$(CC) -c -o $@ $^
从以上makefile执行结果可以看到,CC、RM、以及%.o : %.c 调用的$(CC) -c -o $@ $^,都是make中默认的隐式规则。
通过使用$(.VARIABLES)可以查看make中所有预定义的变量
隐式规则小结一
- 当make发现目标的依赖不存在时,
- 尝试通过依赖名逐一查找隐式规则;
- 并且通过依赖名推导出可能需要的源文件。
示例5–获取makefile中的预定义变量
all :
@echo "$(.VARIABLES)"
示例6–改变预定义变量将改变隐式规则的行为
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
CC := gcc
RM := rm -rf *.o
app.out : $(OBJS)
$(CC) -o $@ $^
$(RM)
@echo "Target ===> $@"
%.o : %.c
$(CC) -o $@ -c $^
隐式规则小结二
- make提供了生成目标文件的隐式规则
- 隐式规则会使用预定义变量完成编译工作
- 改变预定义变量将部分改变隐式规则的行为
- 当存在自定义规则时,不再使用隐式规则
隐式规则副作用
- 编译行为难以控制
- 大量使用隐式规则可能产生意想不到的编译行为
- 编译效率低下
- make从隐式规则和自定义规则中选择最终使用的规则
- 隐式规则链
- 当依赖的目标不存在时,make会极力组合各种隐式规则对目标进行创建,进而产生意料之外的编译行为。例如:需要名为N.o的目标,隐式规则创建过程为:N.y=>N.c=>N.o
查看make的隐式规则
- 查看所有隐式规则:make -p
- 查看具体隐式规则:make -p | grep “XXX”
示例7,命令行输入查看%.o默认的所有隐式规则make -p | grep “%.o”,隐式规则的查找从上往下依次进行匹配
3、隐式规则的禁用
- 局部禁用(用于makefile文件内部)
- 在makefile中自定义规则
%.o : %.c
$(CC) -o $@ -c $^
- 在makefile中定义模式为空(如:%.o:%c)
%.o : %.p
- 全局禁用(用于命令行编译)
- make -r
小结
- 隐式规则可能造成意想不到的编译行为
- 在实际工程项目中尽量不使用隐式规则