1、makefile中出現(xiàn)同名目標(biāo)時
- 同名依賴:所有的依賴將合并在一起,成為目標(biāo)的最終依賴
- 同名命令:當(dāng)多處出現(xiàn)同一目標(biāo)的命令時,make發(fā)出警告;所有之前定義的命令被最后定義的命令取代
示例1--makefile中出現(xiàn)同名依賴
.PHONY : all
all : a.txt
all : b.txt
a.txt :
@echo "this is $@"
b.txt :
@echo "this is $@"
14--1.PNG
示例2--makefile中出現(xiàn)同名命令
.PHONY : all
all :
@echo "command-1"
all :
@echo "command-2"
all :
@echo "this is $@"
14-2.PNG
注意事項(xiàng)
- 當(dāng)使用include關(guān)鍵字包含其它文件時,需要確保被包含文件中的同名目標(biāo)只有依賴,沒有命令;否則,同名目標(biāo)的命令將會被最后定義的命令取代。
示例3--使用include關(guān)鍵字時,出現(xiàn)同名命令
makefile文件與1.mk文件位于同一個目錄下
makefile
.PHONY : all
all :
@echo "this is $@"
include 1.mk
1.mk
all :
@echo "this command from 1.mk"
14-3.PNG
2、隱式規(guī)則(build-in rules)
- make提供了一些常用的,例行的規(guī)則實(shí)現(xiàn)
- 當(dāng)相應(yīng)目標(biāo)的規(guī)則未提供時,make嘗試使用隱式規(guī)則
示例4--目標(biāo)的規(guī)則未提供,make使用隱式規(guī)則
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 $@ $^
14-4.PNG
從以上makefile執(zhí)行結(jié)果可以看到,CC、RM、以及%.o : %.c 調(diào)用的@ $^,都是make中默認(rèn)的隱式規(guī)則。
通過使用$(.VARIABLES)可以查看make中所有預(yù)定義的變量
隱式規(guī)則小結(jié)一
- 當(dāng)make發(fā)現(xiàn)目標(biāo)的依賴不存在時,
- 嘗試通過依賴名逐一查找隱式規(guī)則;
-
并且通過依賴名推導(dǎo)出可能需要的源文件。
隱式規(guī)則圖示.png
示例5--獲取makefile中的預(yù)定義變量
all :
@echo "$(.VARIABLES)"
14-5.PNG
示例6--改變預(yù)定義變量將改變隱式規(guī)則的行為
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 $^
14-6.PNG
隱式規(guī)則小結(jié)二
- make提供了生成目標(biāo)文件的隱式規(guī)則
- 隱式規(guī)則會使用預(yù)定義變量完成編譯工作
- 改變預(yù)定義變量將部分改變隱式規(guī)則的行為
- 當(dāng)存在自定義規(guī)則時,不再使用隱式規(guī)則
隱式規(guī)則副作用
- 編譯行為難以控制
- 大量使用隱式規(guī)則可能產(chǎn)生意想不到的編譯行為
- 編譯效率低下
- make從隱式規(guī)則和自定義規(guī)則中選擇最終使用的規(guī)則
- 隱式規(guī)則鏈
- 當(dāng)依賴的目標(biāo)不存在時,make會極力組合各種隱式規(guī)則對目標(biāo)進(jìn)行創(chuàng)建,進(jìn)而產(chǎn)生意料之外的編譯行為。例如:需要名為N.o的目標(biāo),隱式規(guī)則創(chuàng)建過程為:N.y=>N.c=>N.o
查看make的隱式規(guī)則
- 查看所有隱式規(guī)則:make -p
- 查看具體隱式規(guī)則:make -p | grep "XXX"
示例7,命令行輸入查看%.o默認(rèn)的所有隱式規(guī)則make -p | grep "%.o",隱式規(guī)則的查找從上往下依次進(jìn)行匹配
14-8.PNG
3、隱式規(guī)則的禁用
- 局部禁用(用于makefile文件內(nèi)部)
- 在makefile中自定義規(guī)則
%.o : %.c
$(CC) -o $@ -c $^
- 在makefile中定義模式為空(如:%.o:%c)
%.o : %.p
- 全局禁用(用于命令行編譯)
- make -r
小結(jié)
- 隱式規(guī)則可能造成意想不到的編譯行為
- 在實(shí)際工程項(xiàng)目中盡量不使用隱式規(guī)則
