這個章節主要講解的是在 makefile 中巢狀執行 make。我們都知道在乙個大的工程檔案中,不同的檔案按照功能被劃分到不同的模組中,也就說很多的原始檔被放置在了不同的目錄下。每個模組可能都會有自己的編譯順序和規則,如果在乙個 makefile 檔案中描述所有模組的編譯規則,就會很亂,執行時也會不方便,所以就需要在不同的模組中分別對它們的規則進行描述,也就是每乙個模組都編寫乙個 makefile 檔案,這樣不僅方便管理,而且可以迅速發現模組中的問題。這樣我們只需要控制其他模組中的 makefile 就可以實現總體的控制,這就是 make 的巢狀執行。
如何來使用呢?舉例說明如下:
subsystem:
cd subdir && $(make)
這個例子可以這樣來理解,在當前目錄下有乙個目錄檔案 subdir 和乙個 makefile 檔案,子目錄 subdir 檔案下還有乙個 makefile 檔案,這個檔案是用來描述這個子目錄檔案的編譯規則。使用時只需要在最外層的目錄中執行 make 命令,當命令執行到上述的規則時,程式會進入到子目錄中執行 make。這就是巢狀執行 make,我們把最外層的 makefile 稱為是總控 makefile。
上述的規則也可以換成另外一種寫法:
subsystem
$(make) -c subdir
在 make 的巢狀執行中,我們需要了解乙個變數 "curdir",此變數代表 make 的工作目錄。當使用 make 的選項 "-c" 的時候,命令就會進入指定的目錄中,然後此變數就會被重新賦值。總之,如果在 makefile 中沒有對此變數進行顯式的賦值操作,那麼它就表示 make 的工作目錄。我們也可以在 makefile 中為這個變數賦乙個新的值,當然重新賦值後這個變數將不再代表 make 的工作目錄。
export的使用
使用 make 巢狀執行的時候,變數是否傳遞也是我們需要注意的。如果需要變數的傳遞,那麼可以這樣來使用:
export
如果不需要那麼可以這樣來寫:
unexport
是變數的名字,不需要使用 "$" 這個字元。如果所有的變數都需要傳遞,那麼只需要使用 "export" 就可以,不需要新增變數的名字。
makefile 中還有兩個變數不管是不是使用關鍵字 "export" 宣告,它們總會傳遞到下層的 makefile 中。這兩個變數分別是 shell 和 makeflags,特別是 makeflags 變數,包含了 make 的引數資訊。如果執行總控 makefile 時,make 命令帶有引數或者在上層的 makefile 中定義了這個變數,那麼 makeflags 變數的值將會是 make 命令傳遞的引數,並且會傳遞到下層的 makefile 中,這是乙個系統級別的環境變數。
make 命令中有幾個引數選項並不傳遞,它們是:"-c"、"-f"、"-o"、"-h" 和 "-w"。如果我們不想傳遞 makeflags 變數的值,在 makefile 中可以這樣來寫:
subsystem:
cd subdir && $(make) makeflags=
makefile 中 "巢狀執行 make" 大部分是在大的工程專案中使用的,那麼我們就通過乙個大的專案工程來詳細的分析一下如何巢狀執行 make。
假設有乙個 *** player 的應用程式,它可以被劃分為若干個元件:使用者介面(ui)、編解碼器(codec)以及資料管理庫(db)。它們分別可以用三個程式庫來表示:libui.a、libcodec.a 和 libdb.a。將這些元件緊湊的放到一起就可以組成這個應用程式。具體的檔案結構展示為(我們展示的只是目錄檔案,沒有展示詳細的原始檔):
├──makefile //最外層的makefile檔案,不是目錄檔案。
├──include //編譯的時候需要鏈結的庫檔案
│ ├──codec 庫檔案所在的目錄
│ ├──db 庫檔案所在的目錄
│ ├──ui 庫檔案所在的目錄
lib_codec := lib/codeclib_db := lib/db
lib_ui := lib/ui
libraries := $(lib_codec) $(lib_db) $(lib_ui)
.phony : all $(player) $(libraries)
all : $(player)
$(player) $(libraries) :
$(make) -c $@
我們可以看到在 "總控 makefile" 中,乙個規則在工作目標上列出了所有的子目錄,它對每乙個子目錄的 makefile 呼叫的**是:
$(player) $(libraries) :
$(make) -c $@
$(player) : $(libraries)
$(lib_ui) : $(lib_db) $(lib_codec)
all : a b c
all : d e f
如果不存在其他的依存關係,這6個必要條件的更新動作可以是任何次序,不過gnu make將會以從左向右的次序來更新出現在同一行的必要條件,這會產生如下的更新次序:"a b c d e f" 或 "d e f a b c"。
注意:不要因為之前這麼做更新的次序是對的,就以為每次這麼做都是對的,而忘了提供完整的依存資訊。
最後,依存分析可能會產生不同的次序而引發一些問題。所以,如果有一組工作目標需要以特定的次序進行更新時,就必須提供適當的必要條件來實現正確的次序。
當我們在最外層執行 make 的時候我們會看到l輸出的資訊:
makefile檔案編寫教程
1.make介紹 2.makefile檔案的命名 3.makefile中的規則 makefile中的規則組成 目標,依賴,命令,具體格式如下 目標 依賴 tab縮排 命令 makefile中由一條或多條規則組成!4.makefile的編寫 依賴存在,判斷是否需要更新 第二個版本的缺點 makefil...
Makefile教程 三 Makefile 總述
makefile裡主要包含了五個東西 顯式規則 隱晦規則 變數定義 檔案指示和注釋。顯式規則說明了,如何生成乙個或多的的目標檔案。這是由makefile的書寫者明顯指出,要生成的檔案,檔案的依賴檔案,生成的命令。由於我們的make有自動推導的功能,所以隱晦的規則可以讓我們比較粗糙地簡略地書寫make...
Makefile教程 六 MakeFile使用函式
一 if函式 if函式很像gnu的make所支援的條件語句 ifeq,if函式的語法是 if 或是 if 可見,if函式可以包含 else 部分,或是不含。即if函式的引數可以是兩個,也可以是三個。引數是if的表示式,如果其返回的為非空字串,那麼這個表示式就相當於返回真,於是,會被計算,否則會被計算...