1. 程式人生 > >【三】makefile中的變數

【三】makefile中的變數

一、變數賦值

  • 直接展開式 :=

特點:在定義時立即展開應用的變數

示例:

value1 := 5
value2 := $(value1) #value2會立即被賦值成5
value1 :=6
var-test:
    @echo "value2", $(value2)

輸出:

make var-test
value2, 5
  • 遞迴展開式 =

特點:定義變數時候其實相當於宣告,只有在實際引用時才展開

示例:

value1 = 5
value2 = $(value1) #此處只是宣告,不對value2賦值
value1 = 6

var-test:
    #此處對value1賦值給value2,此時value1=6
    @echo "value2", $(value2)

輸出:

make var-test
value2, 6
  • 直接展開式 ?=

特點:當變數為空時才賦值

示例:

value1 = 111
value1 ?= 000 #value1的值認為111
  • 追加賦值 += 

特點:追加賦值,使用空格分隔

value1 = a.cpp
value1 += b.cpp #value1的值為a.cpp b.cpp

相當於

value1 := $(value1) b.cpp

只是更簡潔了,需要注意追加賦值使用的立即展開,即:=,不是遞迴展開

  • 綜合示例

示例1:

VAR_A = abc
VAR_B = $(VAR_A) 222
#展開VAR_C的同時,引用了VAR_A,兩個變數都被賦值成abc
VAR_C := $(VAR_A)
VAR_A = def

var-test:
    @echo "VAR_A", $(VAR_A)
    @echo "VAR_B", $(VAR_B)
    @echo "VAR_C", $(VAR_C)

輸出:

VAR_A, def
VAR_B, def 222
VAR_C, abc

示例2:

VAR_A = abc
VAR_B = $(VAR_A) 222
VAR_C := $(VAR_A) #直接展開VAR_C = abc
VAR_A = def

VAR_A:=$(VAR_B) 222 #直接展開,引用VAR_B,VAR_B展開成def 222
VAR_B=$(VAR_A)

var-test:
    @echo "VAR_A", $(VAR_A)
    @echo "VAR_B", $(VAR_B)
    @echo "VAR_C", $(VAR_C)

輸出:

VAR_A, def 222 222
VAR_B, def 222 222
VAR_C, abc

示例3:定義一個空格變數

nullstring :=
space := $(nullstring) #end of the line
dir := /foo/bar # directory to put the frobs in

因為在操作符的右邊 是很難描述一個空格的,這裡先定義一個空變數nullstring,先用空變數nullstring來標明變數的值開始,而後面用“#”註釋符來表示變數定義的終止,這樣可以定義出其值是一個空格的變量了。

註釋符“#”的這種特性值得我們注意,例子中變數dir的值是“/foo/bar”,後面還跟了4個空格,如果我們使用這樣變數來指定別的目錄——“$(dir)/file”那麼就出錯了。

二、變數的高階用法

  • 多行變數

使用define關鍵字可以定義多行變數,語法:

define 變數名
...
....
endef

示例:

define echo_va
    echo v
    echo a
endef

  • 變數替換

語法:

$(var:a=b)
#或者
$(var:%a=%b)

變數var中包括多個字串,這些字串被空格或結束符分割,其中以a結尾的字串,會被改成以b結尾。

示例:

foo = a.o.o b.c.o d.o.e
bar = $(foo:.o=.c)
$(info bar)
far = $(foo:%.o=%.c)
$(info far)


all:
    @echo done

執行make all 輸出

a.o.o b.c.o d.o.e
a.o.c b.c.c d.o.e
a.o.c b.c.c d.o.e
done
  • 在make命令列中設定變數

語法:

make var=value

示例:

a_objects = a.o b.o c.o
1_objects = 1.o 2.o 3.o

#變數a1值決定編譯不同指令碼
source = $($(a1)_objects:%.o=%.c)

all:
    @echo $(source)

執行make a1=1,輸出

1.c 2.c 3.c

執行make a1=a,輸出

a.c b.c c.c
  • 把變數的值再當成變數

示例1:

a = b
b = c
#$(a)是b,這個值還是作為變數使用,所有d的值為c
d = $($(a))

示例2:

first_second = Hello a = first b = second all = $($a_$b) #all的值為“hello”
  • 引用環境變數

在make開始執行時會將系統環境變數載入到執行環境中,所以可以在makfile指令碼中引用環境變數, 這裡定義一個測試用的系統環境變數:

export demoPath=/usr/local/demo

在makefile便可以通過$符號引用:

DEMOPATH = ${demoPath} # 也可以直接應用$(demoPath)

系統環境變數使用全部大寫表示,區別普通的變數。如果makfile指令碼中定義了該環境變數,系統環境變數將會被覆蓋。

  • 目標變數

作用:目標變數只在目標編譯過程中有效,相當於c語言中區域性變數

示例:

prog : CFLAGS = -g 
prog : prog.o foo.o bar.o 
    $(CC) $(CFLAGS) prog.o foo.o bar.o 

prog.o : prog.c
 $(CC) $(CFLAGS) prog.c 

foo.o : foo.c 
    $(CC) $(CFLAGS) foo.c 

bar.o : bar.c 
    $(CC) $(CFLAGS) bar.c

無論全域性$(CFLAGS)是什麼值,在prog目標及其引發的目標中都會被變成debug模式。

  • 模式變數

作用:模式變數和目標變數類似,只不過目標是一個正則表示式。

示例:

%.o : CFLAGS= -o

二、常見的內建變數

CC = cc #c語言編譯器的名稱
CPP = $(cc) -E #c檔案前處理器的名稱
CFLAGS #C檔案的編譯選項
CPPFLAGS #C檔案預處理的編譯選項
CXXFLAGS #CPP檔案的編譯選項
LDFLAGS #連線的動態庫

CURDIR := /home/zxy/... #當前路徑
MAKEFLAGS = p #make命令選項
RM = rm -f

VPATH #檔案的搜尋路徑

列印環境變數和內建變數方法:

make -p