makefile--隱式規(guī)則


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)用的(CC) -c -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ī)則
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容