1. 程式人生 > >makefile--隱式規則

makefile--隱式規則

1、makefile中出現同名目標時

  • 同名依賴:所有的依賴將合併在一起,成為目標的最終依賴
  • 同名命令:當多處出現同一目標的命令時,make發出警告;所有之前定義的命令被最後定義的命令取代 示例1–makefile中出現同名依賴
.PHONY : all

all : a.txt

all : b.txt

a.txt :
	@echo "this is [email protected]"

b.txt :
	@echo "this is [email protected]"

在這裡插入圖片描述 示例2–makefile中出現同名命令

.PHONY : all

all :
	@echo "command-1"

all : 
	@echo "command-2"

all :
	@echo "this is 
[email protected]
"

在這裡插入圖片描述 注意事項

  • 當使用include關鍵字包含其它檔案時,需要確保被包含檔案中的同名目標只有依賴,沒有命令;否則,同名目標的命令將會被最後定義的命令取代。

示例3–使用include關鍵字時,出現同名命令 makefile檔案與1.mk檔案位於同一個目錄下

makefile

.PHONY : all

all :
	@echo "this is [email protected]"

include 1.mk

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 [email protected] $^
	$(RM)
	@echo "Target ===> [email protected]"

makefile等價於下面的檔案

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

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

%.o : %.c
	@echo "rule"
	$(CC) -c -o [email protected] $^

在這裡插入圖片描述

從以上makefile執行結果可以看到,CC、RM、以及%.o : %.c 呼叫的$(CC) -c -o [email protected] $^,都是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 [email protected] $^
	$(RM)
	@echo "Target ===> [email protected]"	

%.o : %.c
	$(CC) -o [email protected] -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 [email protected] -c $^
-   在makefile中定義模式為空(如:%.o:%c)
%.o : %.p
    
  • 全域性禁用(用於命令列編譯)
    • make -r

小結

  • 隱式規則可能造成意想不到的編譯行為
  • 在實際工程專案中儘量不使用隱式規則