Makefile中的變量使用注意點

一個變量是在GNU Makefile定義爲文本字符串,稱爲變量的值。這些值被顯式替換爲目標,依賴條件,命令和Makefile的其他部分。而在的其他make版本中,變量也被稱爲宏,所以本質上我們可以把Makefile中的變量展開等價於宏定義的展開。
變量可以表示文件名列表,傳遞給編譯器的選項,要運行的程序,要查找源文件的目錄,要在其中寫入輸出的目錄或可以想象的任何其他內容。
變量名稱區分大小寫。名字fooFOO是指不同的變量。

變量引用

要替換變量的值,在括號或大括號前面寫一個美元符號,後跟該變量的名稱: $(foo)或者${foo}是對變量foo的有效引用。
變量引用可以在任何上下文中使用:目標,前提條件,命令,大多數指令和新的變量值。這是一個常見情況的示例,其中變量保存程序中所有目標文件的名稱:

objects = program.o foo.o utils.o
program : $(objects)
        cc -o program $(objects)

$(objects) : defs.h

變量引用通過嚴格的文本替換來工作。因此,規則:

foo = c
prog.o : prog.$(foo)
        $(foo)$(foo) -$(foo) prog.$(foo)

可用於編譯C程序prog.c中。由於變量值之前的變量值之前的空格會被忽略,因此的值替換變量後正好是prog.c

shell變量的區別

Makefile中在對一些簡單變量的引用,我們也可以不使用(){}來標記變量名,而直接使用$x的格式來實現,此種用法僅限於變量名爲單字符的情況。另外自動化變量也使用這種格式。對於一般多字符變量的引用必須使用括號了標記,否則make將把變量名的首字母作爲作爲變量而不是整個字符串($PATHMakefile中實際上是$(P)ATH)。這一點和shell中變量的引用方式不同:shell中變量的引用可以是${xx}或者$xx格式。但在Makefile中多字符變量名的引用只能是$(xx)或者${xx}格式。

Makefile中所有以$打頭的單詞都會被解釋成Makefile中的變量。如果你需要調用shell中的變量,需要加兩個$符號($$)。而最大的區別也是最容易犯的錯誤是:Makefile中的變量展開等價於宏定義的展開(不會去掉""或者''),而shell中的變量展開是字符串展開(會自動去掉""或者''),比如下面的例子:

PATH="test"

all:
    echo ${PATH}       /*Makefile中變量,展開後是"test"*/
    echo $$PATH        /*shell中的環境變量*/

例子中的第一個${PATH}引用的是Makefile中的變量,而且變量展開後是有""的,後者引用的是Shell中的PATH環境變量。

覆蓋變量

如果命令行使用了一個=來指定變量值的參數:比如v=x將變量v的值設置爲x,這樣就會忽略makefile中相同變量的所有普通賦值。我們稱之爲該變量被命令行參數覆蓋。

使用此功能的最常見方法是將額外的標誌傳遞給編譯器。例如,在一個makefile中,變量CFLAGS包含在運行C編譯器的每個命令中,命令將對文件foo.c進行如下編譯:

cc -c $(CFLAGS) foo.c

makefile可能會指定的通常值CFLAGS,如下所示:

CFLAGS=-g

每次運行時make,你都可以覆蓋此值。例如,你可以在shell中運行 make CFLAGS='-g -O',那麼Makefile中每個C編譯將擴展爲 cc -c -g -O 編譯命令。

自動變量

假設你正在編寫模式規則來編譯 .c 歸檔到 .o 文件:你怎麼寫的cc命令,以便對正確的源文件名進行操作?makefile中的自動變量可以幫到你,這些變量具有根據規則的目標和前提條件爲所執行的每個規則重新計算的值。針對這個問題,使用$@作爲目標文件名,以及$<作爲源文件名。下面是常用的自動變量表:

變量 含義
$@ 規則目標的文件名。如果目標是歸檔成員,則$@是存檔文件的名稱。
$% 如果目標是歸檔成員,則該變量表示目標的歸檔成員名稱。
$< 第一個依賴條件的名稱。
$? 比目標更新的所有依賴條件的名稱,它們之間有空格。
$^ 所有依賴條件的名稱,它們之間有空格。
$+ 所有的依賴文件,以空格分開,並以出現的先後爲序,可能包含重複的依賴文件
$* 不包含擴展名的目標文件名稱

下面是一個自動變量的例子:

objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@

命令中的$<$@是自動化變量,$<表示依賴條件集合(也就是“foo.c bar.c”),$@表示目標集(也就是“foo.o bar.o”)。

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