makefile學習筆記(二)

2020-08-12 23:17:27

makefille中特殊變數

$(MAKE)   當前make直譯器的檔名

$(MAKECMDGOALS) 命令列中指定的目標名

$(MAKEFILE_LIST) make所需處理的makefile檔案列表,當前makefile的檔名總是位於列表的最後,檔名之間以空格進行分隔

 

test :

$(MAKE) first

$(MAKE) second

$(MAKE) third

目標first second third可以爲其他檔案的僞目標,用來關聯多個makefile檔案

 

$(MAKE_VERSION) 當前make直譯器的版本號

$(CURDIR) 當前make直譯器的工作目錄

$(.VARIABLES) 所有已定義的變數名列表(預定義變數和自定義變數)

 

 

變數值的替換

使用指定字元(串)替換變數值中的後綴字元(串)

語法格式:$(var:a=b)或${var:a=b}

 

變數的模式替換

使用%保留變數值中的指定字元,替代其他字元

語法格式:$(var:a%b=x%y)或${var:a%b=x%y}

 

規則中的模式替換

targets : target-pattern : prerequisite-pattern

command1\

command2\

意義:通過target-pattern從targets中匹配子目標,再通過prereq-pattern從子目標生成依賴,進而構成完成的規則

 

OBJS := fun.o main.o

 

$(OBJS) : %.o : %.c

gcc -o $@ -c $^

 

變數值的巢狀參照

x := y

y := z

a := $($(x))

 

執行make時,在命令列定義變數,命令列變數預設覆蓋makefile中定義的變數

 

Override關鍵字用於指示makefile中定於的變數不能背覆蓋

 

hm := hello makefile

 

override var := override-test

 

test :

@echo "hm => $(hm)"

@echo "var => $(var)"

@echo "fool => $(fool)"

 

make hm=123

 

make var=eee

 

make fool=aaaa

 

Define關鍵字用於makefile中定義多行變數,多行變數的定義從變數名開始到ended結束,常用於生成命令

例如

define foo

I am good!

endef

 

makefile中能夠直接使用環境變數,定義了同名變數,環境變數將會被覆蓋,通過make - e選項優先使用環境變數

 

變數在不同的makefile檔案中傳遞

1.採用環境變數

2.使用export定義變數進行傳遞

3.定義make命令列變數進行傳遞(推薦)

 

JAVEA_HOEME := java home

export var := qqq

new := huang

 

//makefile

test :

@echo 「JAVEA_HOEME => $(JAVEA_HOEME)」

@$(MAKE) -f makefile1 new:=$(new)

 

make test

make -e test

 

//makefile1

test :

@echo 「JAVEA_HOEME => $(JAVEA_HOEME)」

@echo 「var = $(var)」

@echo 「new = $(new)」

  

目標變數爲區域性變數,作用域只在指定目標及連帶規則中

 

模式變數是目標變數的擴充套件

 

var := 123

 

test : var:= test-var

 

test :

@echo "var => $(var)"

 

var => test-var

 

//

var := 123

 

test : var:= test-var

 

test :

@echo "var => $(var)"

 

another :

@echo "var => $(var)"

 

make another

 

var => 123

 

//

new := qqq

 

%e : override new := awe

 

test :

@echo "new = $(new)"

 

rule :

 

@echo "new = $(new)"

 

 

make test rule

 

new = qqq

new = awe

 

條件判斷語句,依據條件的至來決定make的執行,只能控制make實際執行的語句,但是不能控制規則中命令的執行

If (arg1, arg2) //括號可以用單雙引號代替

 

else

 

endif

 

條件判斷關鍵字 ifeq infer ifdef ifndef

.PHONY : test

 

var1 := A

var2 := $(var1)

var3 :=

 

test :

ifeq ($(var1), $(var2))

@echo "var1 == var2"

else

@echo "var1 != var2"

endif

 

ifneq ($(var2), )

@echo "var2 is not empty"

else

@echo "var2 is empty"

endif

 

ifdef var2

@echo "var2 is not empty"

else

@echo "var2 is empty"

endif

 

ifndef var3

@echo "var3 is empty"

else

@echo "var2 is not empty"

endif

 

make

 

var1 == var2

var2 is not empty

var2 is not empty

var3 is empty

 

條件判斷語句之前可以有空格,但是不能有tab字元(‘\t’)

 

在條件語句中不要使用自動變數($@, $^, $<)

 

一條完整的條件語句必須位於同一個makefile中

 

條件判斷語句類似於c語言中的宏,預處理階段有效,執行階段無效

Make在載入makefile時,根據判斷語句的表達式決定執行的內容

.PHONY : test

 

var1 :=

var2 := $(var1)

 

var3 =

var4 = $(var3)

 

test :

ifdef var1

@echo "var1 is defined"

else

@echo "var1 is not defined"

endif

 

ifdef var2

@echo "var2 is defined"

else

@echo "var2 is not defined"

endif

 

ifdef var3

@echo "var3 is defined"

else

@echo "var3 is not defined"

endif

 

ifdef var4

@echo "var4 is defined"

else

@echo "var4 is not defined"

endif

 

make

 

var1 is not defined

var2 is not defined

var3 is not defined

var4 is defined

 

遞回複製,make直譯器無法解析var4是否定義,預設爲已定義

 

 

函數的定義及呼叫

1.make直譯器提供了一系列函數供makefile呼叫

2.通過define關鍵字實現自定義函數

 

//定義

define fun1

@echo 「My name is $(0).」

@echo 「Param => $(1)」

endef

 

//呼叫

test :

$(call func1)

 

自定義函數是一個多行命令,無法直接呼叫,是一種過程呼叫,沒有任何的返回值

自定義函數是make直譯器在預定義時call函數在呼叫時將參數傳遞給多行變數

.PHONY : test

 

define func1

@echo "My name is $(0)."

@echo "Param => $(1)"

endef

 

var := $(call func1)

new := $(func1)

 

test :

@echo "var => $(var)"

@echo "new => $(new)"

$(call func1, hello)

 

var => @echo My name is func1

new => @echo My name is

My name is func1.

Param =>  hello

 

//

.PHONY : test

 

define func1

@echo "My name is $(0)."

endef

 

func2 := @echo "My name is $(0)."

 

 

test :

$(call func1)

$(call func2)

 

make

 

My name is func1.

My name is .

 

原因是call只能處理多行變數

 

變數與函數的綜合範例

$(wildcard _pattern)   獲取當前工作目錄滿足_pattern的檔案或目錄列表

$(addprefix _prefix, names) 給名字列表_names中的每一個名字增加字首_prefix

 

SRCS := $(wildcard *.c)   自動獲取當前目錄下的原始檔列表

OBJS := $(SRCS:.c = .o )   替換變數值,將.c替換爲.o檔案

OBJS := $(addprefix path/, $(OBJS))    對每一個目標檔案列表加上路徑字首

 

%.c用於模式匹配當前目錄下的檔案列表

%.o : %.c

gcc -o $@ -c $^

 

CC := gcc

MKDIR := mkdir

RM := rm -fr

 

DIR_OBJS := objs

DIR_TARGET := target

 

DIRS := $(DIR_OBJS) $(DIR_TARGET)

 

TARGET := $(DIR_TARGET)/hello-makefile.out

 

# main.c const.c fun.c

SRCS := $(wildcard *.c)

# main.o const.o fun.o

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

# objs/main.o objs/const.o objs/fun.o

OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))

 

.PHONY : rebuild clean all

 

$(TARGET) : $(DIRS) $(OBJS)

$(CC) -o $@ $(OBJS)

@echo "Target file ==> $@"

 

$(DIRS) :

$(MKDIR) $@

 

$(DIR_OBJS)/%.o : %.c

$(CC) -o $@ -c $^

 

rebuild : clean all

 

all : $(TARGET)

 

clean :

$(RM) $(DIRS)

 

make all

 

mkdir objs

mkdir target

gcc -o objs/const.o -c const.c

gcc -o objs/fun.o -c fun.c

gcc -o objs/main.o -c main.c

gcc -o target/hello-makefile.out objs/const.o objs/fun.o objs/main.o

Target file ==> target/hello-makefile.out