Makefile 好範例

自動化變量

$@	表示規則中的目標。
$<	表示規則中的第一個條件。
$?	表示規則中所有比目標新的條件,組成一個列表,以空格分隔。
$^	表示規則中的所有條件,組成一個列表,以空格分隔。

###示例1

main: main.o stack.o maze.o
    gcc main.o stack.o maze.o -o main

可以改寫成:

main: main.o stack.o maze.o
    gcc $^ -o $@

###示例2

有時候希望只對更新過的條件進行操作,例如有一個庫文件libsome.a依賴於幾個目標文件:

libsome.a: foo.o bar.o lose.o win.o 
    ar r libsome.a $?
    ranlib libsome.a

##常用變量

變量名          說明
AR              靜態庫打包命令的名字,缺省值是ar。
ARFLAGS         靜態庫打包命令的選項,缺省值是rv。
AS              彙編器的名字,缺省值是as。
ASFLAGS         彙編器的選項,沒有定義。
CC              C編譯器的名字,缺省值是cc。
CFLAGS          C編譯器的選項,沒有定義。
CXX             C++編譯器的名字,缺省值是g++。
CXXFLAGS        C++編譯器的選項,沒有定義。
CPP             C預處理器的名字,缺省值是$(CC) -E。
CPPFLAGS        C預處理器的選項,沒有定義。
LD              鏈接器的名字,缺省值是ld。
LDFLAGS         鏈接器的選項,沒有定義。
TARGET          _ARCH 和目標平臺相關的命令行選項,沒有定義。
OUTPUT          _OPTION 輸出的命令行選項,缺省值是-o $@。
LINK.o          把.o文件鏈接在一起的命令行,缺省值是$(CC) $(LDFLAGS) $(TARGET_ARCH)。
LINK.c          把.c文件鏈接在一起的命令行,缺省值是$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)。
LINK.cc         把.cc文件(C++源文件)鏈接在一起的命令行,缺省值是$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)。
COMPILE.c       編譯.c文件的命令行,缺省值是$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c。
COMPILE.cc      編譯.cc文件的命令行,缺省值是$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c。
RM              刪除命令的名字,缺省值是rm -f。

##函數 ###函數的調用語法 函數調用,很像變量的使用,也是以“$”來標識的,其語法如下:

$(<function> <arguments>)

或是

${<function> <arguments>}

這裡,<function>就是函數名,make 支持的函數不多。<arguments>是函數的參數,參數間以逗號“,”分隔,而函數名和參數之間以“空格”分隔。函數調用以 “$” 開頭,以 圓括號或花括號 把函數名和參數括起。感覺很像一個變量,是不是?函數中的參數可以使用變量,為了風格的統一,函數和變量的括號最好一樣,如使用 $(subst a,b,$(x)) 這樣的形式,而不是 $(subst a,b,${x})的形式。因為統一會更清楚,也會減少一些不必要的麻煩。

還是來看一個示例:

comma:= ,
empty:=
space:= $(empty) $(empty)
foo:= a b c
bar:= $(subst $(space),$(comma),$(foo))

在這個示例中,$(comma)的值是一個逗號。$(space)使用了$(empty)定義了一個空格,$(foo)的值是“a b c”,$(bar)的定義用,調用了函數“subst”,這是一個替換函數,這個函數有三個參數,第一個參數是被替換字串,第二個參數是替換字串,第三個參數是替換操作作用的字串。這個函數也就是把$(foo)中的空格替換成逗號,所以$(bar)的值是“a,b,c”。

###字符串處理函數 ####subst

$(subst <from>,<to>,<text>)
  • 名稱:字符串替換函數——subst。
  • 功能:把字串 中的 字符串替換成
  • 返回:函數返回被替換過後的字符串。
  • 示例: $(subst ee,EE,feet on the street) 把“feet on the street”中的“ee”替換成“EE”,返回結果是“fEEt on the strEEt”。

patsubst

$(patsubst <pattern>,<replacement>,<text>)
  • 名稱:模式字符串替換函數——patsubst。

  • 功能:查找<text>中的單詞(單詞以“空格”、“Tab”或“回車”“換行”分隔)是否符合模式<pattern>,如果匹配的話,則以<replacement>替換。這裡,<pattern>可以包括通配符%,表示任意長度的字串。如果<replacement>中也包含%,那麼,<replacement>中的這個%<pattern>中的那個%所代表的字串。(可以用“\”來轉義,以%來表示真實含義的%字符)

  • 返回:函數返回被替換過後的字符串。

  • 示例:$(patsubst %.c,%.o,x.c.c bar.c) 把字串“x.c.c bar.c”符合模式[%.c]的單詞替換成[%.o],返回結果是“x.c.o bar.o”

  • 備註: 這和我們前面“變量章節”說過的相關知識有點相似。

如:

$(var:<pattern>=<replacement>) 相當於 (patsubst <pattern>,<replacement>,$(var))

$(var: <suffix>=<replacement>) 則相當於 $(patsubst %<suffix>,%<replacement>,$(var))

例如有: objects = foo.o bar.o baz.

那麼, $(objects:.o.c)=$(patsubst %.o,%.c,$(objects)) 是一樣的。

strip

$(strip <string>)
  • 名稱:去空格函數——strip。
  • 功能:去掉<string>字串中開頭和結尾的空字符。
  • 返回:返回被去掉空格的字符串值。
  • 例: $(strip a b c ) 把字串“a b c ”去到開頭和結尾的空格,

findstring

$(findstring <find>,<in>)
  • 名稱:查找字符串函數——findstring。
  • 功能:在字串 中查找 字串。
  • 返回:如果找到,那麼返回 ,否則返回空字符串。
  • 示例:
$(findstring a,a b c)
$(findstring a,b c)
第一個函數返回“a”字符串,第二個返回“”字符串(空字符串)

filter

$(filter <pattern...>,<text>)
  • 名稱:過濾函數——filter。
  • 功能:以<pattern>模式過濾<text>字符串中的單詞, 保留 符合模式<pattern>的單詞。可以有多個模式。
  • 返回:返回符合模式<pattern>的字串。
  • 示例:

书籍推荐