跟我一起學Makefile

Makefile介紹:

      make命令屬於gnu工具(gcc,g++,gdb,make,cvs,patch,diff,binutils等),make命令會在當前目錄下按順序查找文件“Makefile”、“makefile”、“GNUmakefile”,也可以使用其他的名字來書寫Makefile,需要再make後面使用 “-f”、“-file”參數來指定文件名,如:make -f Make.Linux;每條規則中的命令和操作系統 Shell的命令行是一致的。make會一按順序一條一條的執行命令,每條命令的開頭必須以[Tab]鍵開頭,除非 命令是緊跟在依賴規則後面的分號後的。在命令行之間中的空格或是空行會被忽略,但是如果該空格或空行是以Tab鍵開頭的,那麼make會認爲其是一個空命令。

GNU的make工作時的執行步驟入下:(想來其它的make也是類似)
1)、讀入所有的Makefile。
2)、讀入被include的其它Makefile。
3)、初始化文件中的變量。
4)、推導隱晦規則,並分析所有規則。
5)、爲所有的目標文件創建依賴關係鏈。
6)、根據依賴關係,決定哪些目標要重新生成。
7)、執行生成命令。

一、自動化變量:

$^:代表所有依賴的文件

$@:代表目標

$<:代表第一個依賴的文件

       大多說的c/c++編譯器都支持一個”-M“的選項,即自動尋找文件中依賴的頭文件,如果使用的是GNU的c/c++編譯器,需要使用”-MM“參數,否則”-M“會將

標準庫的頭文件包含進來



二、靜態模式與多目標

<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>

targets定義了一系列的目標文件,可以有通配符。是目標的一個集合。
target-parrtern是指明瞭targets的模式,也就是的目標集模式。
prereq-parrterns是目標的依賴模式,它對target-parrtern形成的模式再進行一次依賴目標的定義。


例1:展開:

obj = foo.o bar.o foo.o:foo.c

all: $(obj) $(CC) -c $(CFLAGS) foo.c -o foo.o

$(obj): %.o : %.c => bar.o: bar.c

$(CC) -c $(CFLAGS) $< -o $@ $(CC) -c $(CFLAGS) bar.c -o bar.o

注:上面的例子中,指明瞭我們的目標從$object中獲取,“%.o”表明要所有以“.o”結尾的目標,也就是“foo.o bar.o”,也就是變量

$object集合的模式,而依賴模式“%.c”則取模式“%.o”的“%”,也就是“foo bar”,併爲其加下“.c”的後綴,於是,我們的依賴目標

就是“foo.c bar.c”。

例2:

files = foo.elc bar.o lose.o

$(filter %.o,$(files)): %.o :%.c

$(CC) -c $(CFLAGS) $< -o $@

$(filter %.elc,$(files)): %.elc:%.el

emacs -f batch-byte-compile

注:$(filter %.o,$(files))表示調用Makefile函數,過濾”$filter“集合,只要其中模式爲"%.o"的內容

三、 清空目標文件的規則:

每個Makefile中都應該有一個清空目標文件(.o)的規則,這不僅便於重新編譯,也很利於保持文件的清潔;

1、clean:

       rm  edit $(obj)

2、更爲穩健的方式

      .PHONY: clean

clean:

-rm edit $(obj)

      .PHONY表示clean是一個“僞目標”在行前面加上 “-”表示即使出問題,略過,仍要繼續後面的操作。clean 最好放在Makefile的最後。”make 

clean" 將清除所有被清除的文件。”cleanobj“ 和 ”cleandiff“這兩個僞目標有點像子程序。可以通過輸入”make cleanall“和 ”make cleanobj“以

及”makediff“來達到清除不同類文件的目的 

三、引用其他Makefile

  1)include <filename>    #filename  可以是當前操作系統Shell的文件模式(可以保含路徑和通配符)

 如: include foo.mk

    注:在include前面可以有一些空字符,但是絕不能是[Tab]鍵開始。

三、在規則中引用通配符

  和shell相同make支持“*”,“?”,“[...]”三個通配符。

  obj = *.o    #表示obj的值爲"*.o",並不是所有的 .o文件,如果想代表所有的.o文件則 obj = $(wildcard *.o)

  注:在Makefile中的命令,必須要以[Tab]鍵開始,Makefile第一次編譯的錯誤不會爲致命錯誤,會在整個

Makefile編譯結束,再次重新編譯錯誤位置,如果還未通過則生成致命錯誤

4、shell函數 (:來自 《跟我一起寫Makefile》)

     shell函數與其他函數不同,它的參數應該就是linux命令。shell函數把執行操作系統命令後的輸出作爲函數返回值。如:

   contents:=$(shell cat foo)     或者  files:=$(shell echo *.c)

   注意,這個函數會生成一個shell程序執行命令,所以你要注意其運行性能,如果在Makefile中有比較複雜的規則,並且大量使用該函數,那麼對於你的系統性能是有害的

特別的是Makefile的隱晦的規則可能會讓你的shell函數執行的次數比你想象的多得多。

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