天天看點

跟我一起寫 Makefile(十一)

make 的運作

——————

一般來說,最簡單的就是直接在指令行下輸入make指令,make指令會找目前目錄的makefile來執行,一切都是自動的。但也有時你也許隻想讓make重編譯某些檔案,而不是整個工程,而又有的時候你有幾套編譯規則,你想在不同的時候使用不同的編譯規則,等等。本章節就是講述如何使用make指令的。

一、make的退出碼

make指令執行後有三個退出碼:

    0 —— 表示成功執行。

    1 —— 如果make運作時出現任何錯誤,其傳回1。

    2 —— 如果你使用了make的“-q”選項,并且make使得一些目标不需要更新,那麼傳回2。

Make的相關參數我們會在後續章節中講述。

二、指定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執行。

三、指定目标

一般來說,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很專業(不是那種初學者的作品)。

四、檢查規則

有時候,我們不想讓我們的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被執行時的資訊(這個将在後面講述)。

五、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發現有未定義的變量,那麼就輸出警告資訊。

本文來自CSDN部落格,轉載請标明出處:

http://blog.csdn.net/haoel/archive/2004/02/25/2896.aspx