GNU make 支援內建函式以及使用者自訂函式. 函式調用 (function invocation) 看起來非常像變數參照 (variable), 不過前者包含了一個或多個被逗號隔開的參數. 大部分內建函式展開後多半會被賦值給一個變數或是傳遞給一個 subshell. 使用者自訂函式則儲存在變數或巨集中, 而且會接收呼叫者 (caller) 所傳來之一或多個參數.
使用者自訂函式 :
能夠將命令列儲存在變數裡, 讓我們得以在 makefile 中使用各種應用程式. 請參考下面例子 :
- AWK := gawk
- KILL := kill
- kill_test:
- @$(call kill-acroread,root)
- #$(kill-acroread)
- # filter out "username pid"
- define kill-acroread
- ps aux | \
- $(AWK) -F" " '{print $$1,$$2}' | \
- grep $1
- endef
在這個例子, 當使用者使用工作目標 kill_test, 則巨集 kill-acroread 則會被呼叫, 並傳入一個參數 "john". 而這個巨集的作用即是利用 ps 命令取出所有Process 訊息並透過 pipe 導給命令 gawk. 最後依據傳入參數來 grep 這些 Process. 這裡要特別提出來的是我們在 awk 命令稿中欄位參照會被依序寫成 $1, $2 等等. 如果我們沒有為 awk 加上引號, 這些東西將被視為 make 變數. 我們可以透過以 "額外之錢號 '$' 規避 $n中的錢號 (也就是 $$n)", 然後將之縮減成一個錢號, 並將之傳給 subshell.
你可以傳遞引數給變數與巨集, 這樣展開的結果就可以客製化, 巨集的參數在巨集的定義的主體可依序以 $1, $2 等進行參照. 因此在這裡我們使用了一個參數參照 $1 來取代 grep 搜尋樣式. 最後請注意巨集參數 $1 與命令 gawk 欄位參數 $$1 之間的些微差異. 記住 "哪個程式是變數參照的接受者" 是一件重要的事.
呼叫巨集 call :
call 是一個內建於 make 的函式, call 會展開它的第一個引數, 以及把其餘引數依序置換到 $1, $2.. 的地方. 而其語法如下定義 :
macro-name 可以是任何巨集或是變數的名稱. 巨集或變數的值甚至不必包含任何的 $n 參照, 如果是這樣使用 call 幾乎就沒什麼意義. macro-name 之後是巨集的引數, 並以逗號為分隔符. 請注意 call 的第一個引數是一個非展開式的變數名稱, 但如果你為 call 的第一個引數加上一個錢號以及小括號, 該引數就會像變數一樣被展開, 而它的值會被傳遞給 call.
call 的引數檢查機制非常簡單, 你可以為 call 指定任何數目的引數. 如果一個巨集參照了一個參數 $n, 但是調用它的 call 實例並未指定相應的引數, 那麼該變數就會變成空值. 如果 call實例所指定的引數比巨集的 $n 參照還多, 在巨集中並不會展開額外的引數. 如果你是從一個巨集來調用另一個巨集, 最好能夠知道 make 3.80 的一個奇怪特性. call 函式所定義的引數, 在展開動作期間, 會被視為一般的 make 變數. 如果一個巨集調用了另一個巨集, 被調用者(此為child)將可以在它的巨集展開期間看到調用者(此為 parent)的引數!
請參考下面範例 :
- define parent
- echo "parent has two parameters: $1 $2"
- $(call child,$1)
- endef
- define child
- echo "child has one parameter: $1"
- echo "but child can also see parent's second parameter: $2"
- endef
- scoping_issue:
- @$(call parent,one,two)
這個問題已經在 make 3.81 版解決, 所以 $2 會被展開成空白值.
補充說明 :
* GNU Make Doc
* [GNU Make] 變數與巨集 : 巨集
* [Linux命令] awk : 文字資料的進階處理
沒有留言:
張貼留言