8、shell函數shell
shell函數也不像其它的函數。顧名思義,它的參數應該就是操做系統Shell的命令。它和反引號「`」是相同的功能。這就是 說,shell函數把執行操做系統命令後的輸出做爲函數返回。因而,咱們能夠用操做系統命令以及字符串處理命令awk,sed等等命令來生成一個變量, 如:ide
contents := $(shell cat foo)函數
files := $(shell echo *.c)性能
注意,這個函數會新生成一個Shell程序來執行命令,因此你要注意其運行性能,若是你的Makefile中有一些比較複雜的規則,並大量使用了這 個函數,那麼對於你的系統性能是有害的。特別是Makefile的隱晦的規則可能會讓你的shell函數執行的次數比你想像的多得多。測試
9、控制make的函數ui
make提供了一些函數來控制make的運行。一般,你須要檢測一些運行Makefile時的運行時信息,而且根據這些信息來決定,你是讓make繼續執行,仍是中止。spa
$(error <text ...> )操作系統
產生一個致命的錯誤,<text ...>是錯誤信息。注意,error函數不會在一被使用就會產生錯誤信息,因此若是你把其定義在某個變量中,並在後續的腳本中使用這個變量,那麼也是能夠的。例如:命令行
示例一:debug
ifdef ERROR_001
$(error error is $(ERROR_001))
endif
示例二:
ERR = $(error found an error!)
.PHONY: err
err: ; $(ERR)
示例一會在變量ERROR_001定義了後執行時產生error調用,而示例二則在目錄err被執行時才發生error調用。
$(warning <text ...> )
這個函數很像error函數,只是它並不會讓make退出,只是輸出一段警告信息,而make繼續執行。
make 的運行
——————
通常來講,最簡單的就是直接在命令行下輸入make命令,make命令會找當前目錄的makefile來執行,一切都是自動的。但也有時你也許只想 讓make重編譯某些文件,而不是整個工程,而又有的時候你有幾套編譯規則,你想在不一樣的時候使用不一樣的編譯規則,等等。本章節就是講述如何使用make 命令的。
1、make的退出碼
make命令執行後有三個退出碼:
0 —— 表示成功執行。
1 —— 若是make運行時出現任何錯誤,其返回1。
2 —— 若是你使用了make的「-q」選項,而且make使得一些目標不須要更新,那麼返回2。
Make的相關參數咱們會在後續章節中講述。
2、指定Makefile
前面咱們說過,GNU make找尋默認的Makefile的規則是在當前目錄下依次找三個文件——「GNUmakefile」、「makefile」和「Makefile」。其按順序找這三個文件,一旦找到,就開始讀取這個文件並執行。
當前,咱們也能夠給make命令指定一個特殊名字的Makefile。要達到這個功能,咱們要使用make的「-f」或是「--file」參數 (「--makefile」參數也行)。例如,咱們有個makefile的名字是「hchen.mk」,那麼,咱們能夠這樣來讓make來執行這個文件:
make –f hchen.mk
若是在make的命令行是,你不僅一次地使用了「-f」參數,那麼,全部指定的makefile將會被連在一塊兒傳遞給make執行。
3、指定目標
通常來講,make的最終目標是makefile中的第一個目標,而其它目標通常是由這個目標連帶出來的。這是make的默認行爲。固然,通常來 說,你的makefile中的第一個目標是由許多個目標組成,你能夠指示make,讓其完成你所指定的目標。要達到這一目的很簡單,需在make命令後直 接跟目標的名字就能夠完成(如前面提到的「make clean」形式)
任何在makefile中的目標均可以被指定成終極目標,可是除了以「-」打頭,或是包含了「=」的目標,由於有這些字符的目標,會被解析成命令行 參數或是變量。甚至沒有被咱們明確寫出來的目標也能夠成爲make的終極目標,也就是說,只要make能夠找到其隱含規則推導規則,那麼這個隱含目標一樣 能夠被指定成終極目標。
有一個make的環境變量叫「MAKECMDGOALS」,這個變量中會存放你所指定的終極目標的列表,若是在命令行上,你沒有指定目標,那麼,這個變量是空值。這個變量可讓你使用在一些比較特殊的情形下。好比下面的例子:
sources = foo.c bar.c
ifneq ( $(MAKECMDGOALS),clean)
include $(sources:.c=.d)
endif
基於上面的這個例子,只要咱們輸入的命令不是「make clean」,那麼makefile會自動包含「foo.d」和「bar.d」這兩個makefile。
使用指定終極目標的方法能夠很方便地讓咱們編譯咱們的程序,例以下面這個例子:
.PHONY: all
all: prog1 prog2 prog3 prog4
從這個例子中,咱們能夠看到,這個makefile中有四個須要編譯的程序——「prog1」, 「prog2」, 「prog3」和 「prog4」,咱們可使用「make all」命令來編譯全部的目標(若是把all置成第一個目標,那麼只需執行「make」),咱們也可使用「make prog2」來單獨編譯目標「prog2」。
即然make能夠指定全部makefile中的目標,那麼也包括「僞目標」,因而咱們能夠根據這種性質來讓咱們的makefile根據指定的不一樣的 目標來完成不一樣的事。在Unix世界中,軟件發佈時,特別是GNU這種開源軟件的發佈時,其makefile都包含了編譯、安裝、打包等功能。咱們能夠參 照這種規則來書寫咱們的makefile中的目標。
「all」
這個僞目標是全部目標的目標,其功能通常是編譯全部的目標。
「clean」
這個僞目標功能是刪除全部被make建立的文件。
「install」
這個僞目標功能是安裝已編譯好的程序,其實就是把目標執行文件拷貝到指定的目標中去。
「print」
這個僞目標的功能是例出改變過的源文件。
「tar」
這個僞目標功能是把源程序打包備份。也就是一個tar文件。
「dist」
這個僞目標功能是建立一個壓縮文件,通常是把tar文件壓成Z文件。或是gz文件。
「TAGS」
這個僞目標功能是更新全部的目標,以備完整地重編譯使用。
「check」和「test」
這兩個僞目標通常用來測試makefile的流程。
固然一個項目的makefile中也不必定要書寫這樣的目標,這些東西都是GNU的東西,可是我想,GNU搞出這些東西必定有其可取之處(等你的 UNIX下的程序文件一多時你就會發現這些功能頗有用了),這裏只不過是說明了,若是你要書寫這種功能,最好使用這種名字命名你的目標,這樣規範一些,規 範的好處就是——不用解釋,你們都明白。並且若是你的makefile中有這些功能,一是很實用,二是能夠顯得你的makefile很專業(不是那種初學 者的做品)。
4、檢查規則
有時候,咱們不想讓咱們的makefile中的規則執行起來,咱們只想檢查一下咱們的命令,或是執行的序列。因而咱們可使用make命令的下述參數:
「-n」
「--just-print」
「--dry-run」
「--recon」
不執行參數,這些參數只是打印命令,無論目標是否更新,把規則和連帶規則下的命令打印出來,但不執行,這些參數對於咱們調試makefile頗有用處。
「-t」
「--touch」
這個參數的意思就是把目標文件的時間更新,但不更改目標文件。也就是說,make僞裝編譯目標,但不是真正的編譯目標,只是把目標變成已編譯過的狀態。
「-q」
「--question」
這個參數的行爲是找目標的意思,也就是說,若是目標存在,那麼其什麼也不會輸出,固然也不會執行編譯,若是目標不存在,其會打印出一條出錯信息。
「-W <file>」
「--what-if=<file>」
「--assume-new=<file>」
「--new-file=<file>」
這個參數須要指定一個文件。通常是是源文件(或依賴文件),Make會根據規則推導來運行依賴於這個文件的命令,通常來講,能夠和「-n」參數一同使用,來查看這個依賴文件所發生的規則命令。
另一個頗有意思的用法是結合「-p」和「-v」來輸出makefile被執行時的信息(這個將在後面講述)。
5、make的參數
下面列舉了全部GNU make 3.80版的參數定義。其它版本和產商的make大同小異,不過其它產商的make的具體參數仍是請參考各自的產品文檔。
「-b」
「-m」
這兩個參數的做用是忽略和其它版本make的兼容性。
「-B」
「--always-make」
認爲全部的目標都須要更新(重編譯)。
「-C <dir>」
「--directory=<dir>」
指定讀取makefile的目錄。若是有多個「-C」參數,make的解釋是後面的路徑之前面的做爲相對路徑,並以最後的目錄做爲被指定目錄。如:「make –C ~hchen/test –C prog」等價於「make –C ~hchen/test/prog」。
「—debug[=<options>]」
輸出make的調試信息。它有幾種不一樣的級別可供選擇,若是沒有參數,那就是輸出最簡單的調試信息。下面是<options>的取值:
a —— 也就是all,輸出全部的調試信息。(會很是的多)
b —— 也就是basic,只輸出簡單的調試信息。即輸出不須要重編譯的目標。
v —— 也就是verbose,在b選項的級別之上。輸出的信息包括哪一個makefile被解析,不須要被重編譯的依賴文件(或是依賴目標)等。
i —— 也就是implicit,輸出因此的隱含規則。
j —— 也就是jobs,輸出執行規則中命令的詳細信息,如命令的PID、返回碼等。
m —— 也就是makefile,輸出make讀取makefile,更新makefile,執行makefile的信息。
「-d」
至關於「--debug=a」。
「-e」
「--environment-overrides」
指明環境變量的值覆蓋makefile中定義的變量的值。
「-f=<file>」
「--file=<file>」
「--makefile=<file>」
指定須要執行的makefile。
「-h」
「--help」
顯示幫助信息。
「-i」
「--ignore-errors」
在執行時忽略全部的錯誤。
「-I <dir>」
「--include-dir=<dir>」
指定一個被包含makefile的搜索目標。可使用多個「-I」參數來指定多個目錄。
「-j [<jobsnum>]」
「--jobs[=<jobsnum>]」
指同時運行命令的個數。若是沒有這個參數,make運行命令時能運行多少就運行多少。若是有一個以上的「-j」參數,那麼僅最後一個「-j」纔是有效的。(注意這個參數在MS-DOS中是無用的)
「-k」
「--keep-going」
出錯也不中止運行。若是生成一個目標失敗了,那麼依賴於其上的目標就不會被執行了。
「-l <load>」
「--load-average[=<load]」
「—max-load[=<load>]」
指定make運行命令的負載。
「-n」
「--just-print」
「--dry-run」
「--recon」
僅輸出執行過程當中的命令序列,但並不執行。
「-o <file>」
「--old-file=<file>」
「--assume-old=<file>」
不從新生成的指定的<file>,即便這個目標的依賴文件新於它。
「-p」
「--print-data-base」
輸出makefile中的全部數據,包括全部的規則和變量。這個參數會讓一個簡單 的makefile都會輸出一堆信息。若是你只是想輸出信息而不想執行makefile,你可使用「make -qp」命令。若是你想查看執行makefile前的預設變量和規則,你可使用「make –p –f /dev/null」。這個參數輸出的信息會包含着你的makefile文件的文件名和行號,因此,用這個參數來調試你的makefile會是頗有用的, 特別是當你的環境變量很複雜的時候。
「-q」
「--question」
不運行命令,也不輸出。僅僅是檢查所指定的目標是否須要更新。若是是0則說明要更新,若是是2則說明有錯誤發生。
「-r」
「--no-builtin-rules」
禁止make使用任何隱含規則。
「-R」
「--no-builtin-variabes」
禁止make使用任何做用於變量上的隱含規則。
「-s」
「--silent」
「--quiet」
在命令運行時不輸出命令的輸出。
「-S」
「--no-keep-going」
「--stop」
取消「-k」選項的做用。由於有些時候,make的選項是從環境變量「MAKEFLAGS」中繼承下來的。因此你能夠在命令行中使用這個參數來讓環境變量中的「-k」選項失效。
「-t」
「--touch」
至關於UNIX的touch命令,只是把目標的修改日期變成最新的,也就是阻止生成目標的命令運行。
「-v」
「--version」
輸出make程序的版本、版權等關於make的信息。
「-w」
「--print-directory」
輸出運行makefile以前和以後的信息。這個參數對於跟蹤嵌套式調用make時頗有用。
「--no-print-directory」
禁止「-w」選項。
「-W <file>」
「--what-if=<file>」
「--new-file=<file>」
「--assume-file=<file>」
假定目標<file>須要更新,若是和「-n」選項使用,那麼這個參數會輸出該目標更新時的運行動做。若是沒有「-n」那麼就像運行UNIX的「touch」命令同樣,使得<file>的修改時間爲當前時間。
「--warn-undefined-variables」 只要make發現有未定義的變量,那麼就輸出警告信息。