1. 程式人生 > 其它 >make使用總結(4)-Makefile語法

make使用總結(4)-Makefile語法

技術標籤:make使用總結make常用函式

make使用總結(4)-Makefile語法

函式

為了方便Makefile的編寫,make已經為我們定義了多個常用函式。make函式的呼叫格式與變數引用相似,基本格式如下:$(function arguments)${function arguments}.arguments為函式的引數,引數以,進行分割。函式處理引數時,若引數中存在其它變數或函式的引用,則先展開引數再進行函式處理,展開順序與引數的先後順序一致。函式中的引數不能直接出現逗號和空格,前導空格會被忽略,若需要使用逗號和空格則需要將它們賦值給變數。下面一一介紹。

文字替換函式

函式subst,patsubst以字串中的單詞為單位。

  1. subst函式
    1. format:$(subst FROM,TO,TEXT)
    2. 將字串TEXT中的FROM單詞替換為TO
  2. patsubst函式
    1. format:$(patsubst PATTERN,REPLACEMENT,TEXT)
    2. 查詢TEXT字串中的單詞(單詞以“空格”、“Tab”或“回車”“換行”分隔)是否符合模式PATTERN,如果匹配的話,則以REPLACEMENT替換。這裡,PATTERN可以包括萬用字元%,表示任意長度的字串。如果REPLACEMENT中也包含%,那麼REPLACEMENT中的這個%將是PATTERN中的那個%所代表的字串。(可以用“\”來轉義,以“%”來表示真實含義的“%”字元).
  3. strip函式
    1. format:$(strip STRING)
    2. 簡化字串中的空格,將多個連續空格合併成一個

使用例程如下:

#test function subst patsubst strip 

.PHONY:raw sub patsub

str_a := a.o b.o c.o f.o.o abcdefg
str_b := $(subst .o,.c,$(str_a))

str_c := $(patsubst %.o,%.c,$(str_a))
str_d := $(patsubst .o,.c,$(str_a))
str_e := $(patsubst a.o,a.c,$(str_a))

str_1 := "      a      b         c        "
str_2 := $(strip $(str_1))

sub:raw
	@echo "str_b=" $(str_b) #replace all match char for per word

patsub:raw
	@echo "str_c=" $(str_c) #replace match pattern
	@echo "str_d=" $(str_d) #replace nothing
	@echo "str_e=" $(str_e) #replace all-match word

strip:
	@echo "str_1=" $(str_1) #looks like auto strip by make4.1
	@echo "str_2=" $(str_2)

raw:
	@echo "str_a=" $(str_a)

字串處理函式

  1. findstring函式
    1. format:$(findstring FIND,IN)
    2. 在字串IN中查詢字串FIND,若存在返回字串,否則返回空.
  2. filter函式
    1. $(filter PATTERN…,TEXT)
    2. 去除字串TEXT中指定模式的字串.
  3. filter-out函式
    1. format:$(filter-out PATTERN…,TEXT)
    2. 保留指定模式的字串,去除其它字串
  4. sort函式
    1. format:$(sort LIST)
    2. 按首字母順序進行排序
  5. word函式
    1. format:$(word N,TEXT)
    2. 獲取第N個單詞
  6. wordlist函式
    1. format:$(wordlist S,E,TEXT)
    2. 獲取從S位置到E位置的單詞
  7. words函式
    1. format:$(words TEXT)
    2. 統計字串中的單詞數量
  8. firstword函式
    1. format:$(firstword NAMES…)
    2. 獲取第一個單詞
  9. join函式
    1. format:$(join LIST1,LIST2)
    2. 將LIST1和LIST2中的單詞按順序逐個連線
    3. eg:
    str_a := cxx.o n.o fxx.o
    str_join := ./dira/ ./dirb/ ./dirc/
    str_n := $(join $(str_join),$(str_a))
    # 連結結果
    # str_n= ./dira/cxx.o ./dirb/n.o ./dirc/fxx.o
    
  10. call函式
    1. format:$(call VARIABLE,PARAM,PARAM,…)
    2. 此函式用於使用者對自定義函式的引用。

使用例程如下:

#test wrods related function

.PHONY:raw find filt filt_out sort word word_list first_word words join call

str_a := cxx.o n.o fxx.o xy.c fab.o zy.py jor.py abc.o 
str_b := $(findstring xx,$(str_a)) #make sure if xx include in str_a
str_c := $(findstring .o x,$(str_a)) #even can include space char
str_d := $(findstring nothing,$(str_a)) #search no-exist words

str_e := $(filter %.py,$(str_a)) #filster
str_f := $(filter-out %.py,$(str_a)) #filter-out

str_g := $(sort $(str_a)) #sort according first char,if same then next char

str_h := $(word 3,$(str_a)) # get the 3rd word
str_i := $(word 99,$(str_a)) # out of range

str_j := $(wordlist 3,5,$(str_a)) #list 3rd to 5rd words
str_k := $(wordlist 3,99,$(str_a)) #list our of range

str_l := $(firstword $(str_a)) #first word

str_m := $(words $(str_a)) #cacu words num

str_join := ./dira/ ./dirb/ ./dirc/ ./dird/ ./dire/ ./dirf/
str_n := $(join $(str_join),$(str_a))

part_rev = $(4) $(3) $(2) $(1)
str_o = $(call part_rev,a,b,c,d,e,f,g) #must use "=" 

raw:
	@echo "str_a=" $(str_a)

find:raw
	@echo "str_b=" $(str_b)
	@echo "str_c=" $(str_c)
	@echo "str_d=" $(str_d)

filt:raw
	@echo "str_e=" $(str_e)

filt_out:raw
	@echo "str_f=" $(str_f)

sort:raw
	@echo "str_g=" $(str_g)

word:raw
	@echo "str_h=" $(str_h)
	@echo "str_i=" $(str_i)

word_list:raw
	@echo "str_j=" $(str_j)
	@echo "str_k=" $(str_k)

first_word:raw
	@echo "str_l=" $(str_l)

words:raw
	@echo "str_m=" $(str_m)

join:raw
	@echo "str_join=" $(str_join)
	@echo "str_n=" $(str_n)

call:
	@echo "str_o=" $(str_o)

檔名處理相關的函式

  1. dir函式
    1. format:$(dir NAMES…)
    2. 獲取目錄
  2. notdir函式
    1. format:$(notdir NAMES…)
    2. 獲取檔名
  3. suffix函式
    1. format:$(suffix NAMES…)
    2. 獲取檔名的字尾
  4. basename函式
    1. format:$(basename NAMES…)
    2. 獲取檔名的字首
  5. addsuffix函式
    1. format:$(addsuffix SUFFIX,NAMES…)
    2. 增加字尾
  6. addprefix函式
    1. format:$(addprefix PREFIX,NAMES…)
    2. 增加字首
  7. wildcard函式
    1. format:$(wildcard PATTERN)
    2. 萬用字元使用。在Makefile規則中,萬用字元會被自動展開。但在變數定義和函式引用時,萬用字元將失效。但可以使用wildcard()函式來完成萬用字元的使用。在Makefile中,它被展開為已經存在的、使用空格分開的、匹配此模式的所有檔案列表.如果不存在任何符合此模式的檔案,函式會忽略模式字元並返回空。
.PHONY:init clean dir notdir base suffix addprefix addsuffix wildcard

dirs := dir_a
files := file_a.c file_b.s file_c.o #each file under per dir
files_a := $(foreach each,$(files),$(dirs)"/"$(each)) #get all files under a dir by foreach & word func
all_files := $(files_a)
detect_files := $(foreach each,$(dirs),$(wildcard $(each)/*))
detect_files := $(foreach each,$(detect_files),$(PWD)"/"$(each))
show := $(patsubst %,"\n"%,$(detect_files)) #add '\n' for view

vari_dir := $(dir $(detect_files))
show_dir := $(patsubst %,"\n"%,$(vari_dir))

vari_files := $(notdir $(detect_files))

vari_base := $(basename $(detect_files))
show_base := $(patsubst %,"\n"%,$(vari_base))

vari_suffix := $(suffix $(detect_files))

vari_addprefix := $(addprefix "full name:",$(detect_files))
show_addprefix := $(patsubst %,"\n"%,$(vari_addprefix))

vari_addsuffix := $(addsuffix ".text",$(detect_files))
show_addsuffix := $(patsubst %,"\n"%,$(vari_addsuffix))

test:
	@echo "detected files:" $(vari_addprefix)

init:
	@mkdir $(dirs);\
	touch $(all_files);\
	tree

dir:
	@echo "detected files:" $(show)
	@echo "get dir:" $(show_dir)

notdir:
	@echo "detected files:" $(show)
	@echo "get files:"
	@echo $(vari_files)

base:
	@echo "detected files:" $(show)
	@echo "file base name:" $(show_base)

suffix:
	@echo "detected files:" $(show)
	@echo "file suffix:" $(vari_suffix)

addprefix:
	@echo "detected files:" $(show)
	@echo "file add prefix:" $(show_addprefix)

addsuffix:
	@echo "detected files:" $(show)
	@echo "file add suffix:" $(show_addsuffix)

clean:
	@rm -rf $(dirs)

控制和變數相關的函式

  1. shell函式
    1. format:$(shell CMD…)
    2. 呼叫shell並傳入CMD作為引數。我們在除了規則以外的地方使用shell命令時就要用此函式來呼叫shell命令。
  2. foreach函式
    1. format:$(foreach VAR,LIST,TEXT)
    2. 把LIST字串中的單詞依次賦給VAR,並執行TEXT中的表示式
  3. if條件函式
    1. format:$(if CONDITION,THEN-PART[,ELSE-PART])
    2. 如果滿足CONDITION條件,執行THEN-PART語句,否則執行ELSE-PART語句
  4. error函式
    1. format:$(error TEXT…)
    2. 產生致命錯誤並以TEXT內容進行提示
  5. warning函式
    1. format:$(warning TEXT…)
    2. 產生警告並以TEXT內容進行提示
  6. value函式
    1. format:$(value VARIABLE)
    2. 返回VARIABLE未展開前的定義值,即makefile中定義變數時所書寫的字串。
  7. origin函式
    1. format:$(value VARIABLE)
    2. 返回變數的初始定義方式,包括:undefined,default,environment,environment override,file,command line,override,automatic
  8. eval函式

makefile1

.PHONY:init clean for_loop if_cond err warn shell

dirs := dir_a dir_b dir_c dir_d #each dir
files := file_a file_b file_c #each file under per dir
files_a := $(foreach each,$(files),$(word 1,$(dirs))"/"$(each)) #get all files under a dir by foreach & word func
files_b := $(foreach each,$(files),$(word 2,$(dirs))"/"$(each))
files_c := $(foreach each,$(files),$(word 3,$(dirs))"/"$(each))
files_d := $(foreach each,$(files),$(word 4,$(dirs))"/"$(each))
all_files := $(files_a)
all_files += $(files_b)
all_files += $(files_c)
all_files += $(files_d)
detect_files := $(foreach each,$(dirs),$(wildcard $(each)/*))
detect_files := $(patsubst %,"\n"%,$(detect_files)) #add '\n' for view

vari_a :=
vari_b := b
vari_c := $(if $(vari_a),"vari_a has value:"$(vari_a),"vari_a has no value")
vari_d := $(if $(vari_b),"vari_b has value:"$(vari_b),"vari_b has no value")

err_exit := $(if $(vari_e),$(error "you generate a error!"),"no error defined") #define vari_e to enable error
warn_go := $(if $(vari_f),$(warning "you generate a warning!"),"no warning defined") #define vari_f to enalbe warning

shell_cmd := $(shell date)

init:
	@mkdir $(dirs);\
	touch $(all_files);\
	tree

for_loop:
	@echo "files=" $(detect_files)

if_cond:
	@echo "vari_a=" $(vari_a)
	@echo "vari_b=" $(vari_b)
	@echo "vari_c=" $(vari_c)
	@echo "vari_d=" $(vari_d)

warn:
	@echo $(warn_go)

err:
	@echo $(err_exit)

shell:
	@echo $(shell_cmd)

clean:
	@rm -rf $(dirs)

makefile2

#this is a eval func test

PROGRAMS = server client
server_OBJS = server.o server_pri.o server_access.o
server_LIBS = priv protocol

client_OBJS = client.o client_api.o client_mem.o
client_LIBS = protocol

.PHONY:all

define PROGRAM_template
$(1):
	touch $$($(1)_OBJS) $$($(1)_LIBS)
	@echo [email protected] " build finished!"
endef

$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))

$(PROGRAMS):

clean:
	$(RM) *.o $(server_LIBS) $(client_LIBS)

makefile3

.PHONY:value origin

vari_a = abc
vari_b = $(vari_a)
vari_c = $(vari_a) "+" $(vari_b)
override vari_d = vari_a
vari_e = $($(vari_d))

vari_1 = $(value vari_a)
vari_2 = $(value vari_b)
vari_3 = $(value vari_c)
vari_4 = $(value vari_d)
vari_5 = $(value vari_e)

FOO=$PATH
all:
	@echo $(FOO)
	@echo $(value FOO)

value:
	@echo "vari_1=" '$(vari_1)'
	@echo "vari_2=" '$(vari_2)'
	@echo "vari_3=" '$(vari_3)'
	@echo "vari_4=" '$(vari_4)'
	@echo "vari_5=" '$(vari_5)'

origin:
	@echo "origin vari_a:" $(origin vari_a)
	@echo "origin vari_b:" $(origin vari_b)
	@echo "origin vari_c:" $(origin vari_c)
	@echo "origin vari_d:" $(origin vari_d)
	@echo "origin vari_e:" $(origin vari_e)
	@echo 'origin [email protected]:' $(origin @)
	@echo "origin vari_f:" $(origin vari_f)
	@echo "origin PATH:" $(origin PATH)
	@echo "origin MAKE:" $(origin MAKE)

自定義函式

除此之外,我們還可以自定義一些函式。使用下面的格式定義函式:

define DELFILE
	$(Q) if exist $1 (del /f /q $1)
endef

其中$1~$9表示函式輸入的引數。呼叫自定義函式需要使用make已經定義好的call函式。如$(call DELFILE, Make.dep).


關於技術交流

此處後的文字已經和題目內容無關,可以不看。
qq群:825695030
微信公眾號:嵌入式的日常
如果上面的文章對你有用,歡迎打賞、點贊、評論。二維碼