makefile函數

函數

GNUmake支持內置函數和用戶自定義函數。函數調用看起來像是變量引用,只不過多了用逗號隔開的參數而已。所有的函數都具有相同的形式:$(function-namearg1[, argn])$之後是函數的名稱,接着是函數的參數,參數之間以逗號隔開。

內置函數

內置函數是內嵌於make程序內的函數,可以直接使用。

字符串函數

  • $(filterpattern ..., text)

filter函數將text視爲一系列以空格隔開的單詞,與pattern比較之後,返回符合的單詞(模式必須與單詞相匹配,而不能只匹配一部分)。模式可以有多個,只要符合其中一個就會被匹配。模式中採用%作爲通配符,當有多個%出現在一個模式中,只有第一個作爲通配符,其他的作爲字面值。

  • $(filter-outpattern ..., text)

filter-out函數剛好與filter相反,用來選出與模式不相符的每個單詞

text = apple pear banana watermelon orange pineapple
filtered = $(filter %apple pear %ge,$(text))
not_filtered = $(filter-out %apple pear %.ge, $(text))

all :
    @echo $(filtered)
    @echo $(not_filtered)

$ make
apple pear orange pineapple
banana watermelon orange
  • $(findstringstring...,text)

此函數將會從text裏搜索string。如果找到了就返回該字符串,否則返回空string沒有模式匹配功能。

  • $(subst search-string,replace-string,text)

這是一個不具有模式匹配的搜索替換函數search-stringreplace-string不必是整個單詞。

  • $(patsubst search-string,replace-string,text)

這個替換函數具有模式匹配功能。同樣的,只能用一個%

sources = hello.c lib.c main.c tom_hello.c tom_lib.c
objects = $(subst .c,.o, $(sources))
has_main.c = $(findstring main.c, $(sources))
has_main = $(findstring main, $(sources))
no_domain = $(findstring domain, $(sources))
patsubsted = $(patsubst tom%,jerry%, $(sources))

all:
    @echo $(objects)
    @echo $(has_main.c)
    @echo $(has_main)
    @echo $(no_domain)
    @echo $(patsubsted)

$ make
hello.o lib.o main.o tom_hello.o tom_lib.o
main.c
main

hello.c lib.c main.c jerry_hello.c jerry_lib.c
  • $(wordstext)

此函數返回text中單詞的數量。

  • $(wordn,text)

此函數返回text中的第n個單詞。第一個單詞編號爲1,如果n的值大於單詞的總數,返回空值。

  • $(firstwordtext)

返回text中的第一個單詞。等效與$(word 1,text)

  • $(wordlist start,end,text)

此函數返回text中範圍從start(含)到end(含)的單詞。

  • $(sort list)

sort函數會排序它的list參數並且移除重複的單詞。此函數會返回按照字典順序的不重複的單詞列表,以空格分隔。而且,sort還會刪除前導和結尾的空格。這裏的sortmake內部實現的函數,不是shell裏的程序。

  • $(shellcommand)

shell的參數會被擴展(就像所有其他參數)並且傳遞給subshell執行。然後make讀取command的標準輸出,並將之作爲函數的返回值。輸出中所出現的一系列換行符會被縮減成單一的空格,任何末尾的換行被刪除。標準錯誤並不會被返回。

  • $(wildcardpattern...)

wildcard的參數是一個模式列表,他會對每個模式進行擴展。如果擴展的模式找不到符合的文件,返回空字符串。該模式爲shell的glob匹配
如果想要判斷某個文件是否存在,就可以使用wildcard
dot-emacs-exists := $(wildcard ~/.emacs)

  • $(dirlist...)

dir函數返回list中每個單詞的目錄部分。

  • $(notdirname...)

返回每個單詞的文件名部分。

  • $(suffixname...)

返回由每個單詞的擴展名構成的單詞列表

  • $(basenamename...)

返回由每個單詞的非擴展名部分組成的單詞列表

  • $(addsuffix, suffix,name...)

返回由name單詞列表中的每個單詞前加上suffix前綴構成的新的單詞表。

  • $(addprefix,prefix,name...)

  • $(joinprefix-list,suffix-list)

join函數把prefix-list的第i個單詞與suffix-list的第i個單詞連在一起構成新序列的第i個單詞。

流程控制函數

  • $(ifcondition,then-part,else-part)

if函數(可不是條件指令ifne,ifeq,ifdef等)會根據條件表達式的求值結果,從兩個宏中選擇一個進行擴展。
如果condition擴展之後包含任何字符(包括空格),求值結果爲真,會對then-part進行擴展;否則,如果condition擴展之後爲空,會對else-part進行擴展。
makecondition求值時,首先會移除前導及末尾的空格。

  • $(errortext)

error函數會使make輸出text錯誤信息和當前makefile的名稱行號之後以2這個狀態結束運行。

  • $(warntext)
    error類似,輸出text的內容,但並不退出。擴展結果爲空串。

  • $(foreach variable,list,body)
    foreach函數執行的時候,它將list中的每個單詞作爲body中的variable進行操作,返回操作的結果。

sources = fat32.c format.c alloca.c main.c
dirs = src bin inc
objects = $(foreach var,$(sources), $(subst .c,.o, $(var)))
full_path = $(foreach var, $(sources), $(addprefix src/, $(var)))
do_mkdirs = $(foreach var, $(dirs), $(shell mkdir -p $(var)))

all:
    @echo $(objects)
    @echo $(full_path)
    @echo $(do_mkdirs)

$ make
fat32.o format.o alloca.o main.o
src/fat32.c src/format.c src/alloca.c src/main.c
                #產生了三個文件夾

eval函數

  • $(evalcontents)

這個函數很重要。它用來將它後面的文本直接放入make解析器。

首先make會掃描eval的參數並對其中的變量進行擴展,然後make會解析文本進行求值的動作(這裏也包含了一次擴展動作,因爲普通的在makefile中的文本也會擴展一次),就好像它是輸入的文本一樣。

eval函數經常用與含有多行文本的宏的展開。一個解析器頂層的宏被擴展成多行文本是不合法的,但是用eval函數可以將展開後的宏直接當做輸入的文本,再展開一次之後就放入數據庫中了。而eval函數本身的展開結果爲空。

注意:定義複雜的宏時要考慮二次展開的問題,然後用eval函數引用這個宏。

用戶自定義函數

可以用define定義一個自定義的宏:

define macor-name
    contents
endef

用戶自定義函數是帶有參數的宏,宏定義中的$1$2...是函數的形參,宏的定義就是函數的定義。

調用一個自定義函數的形式是:

  • $(callmacro-name[,param1 ...])

call是一個內置函數,call擴展它的第一個參數並把其他參數依次替換到宏定義中的$1$2...的地方。macro-name之後是宏的參數,以逗號隔開。在函數的內部可以使用$0來訪問函數名。

call的參數傳遞機制很簡單。調用時可以爲call指定任意個參數。如果宏定義內引用了$n,但是調用時並未指定相應的參數,那麼該變量就爲空值。如果call的參數比宏的$n引用還多,則被忽略。

注意使用函數是不要隨意加前導空格,否則可能回產生難以排查的錯誤。(但降低了可讀性)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章