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