您好,登錄后才能下訂單哦!
我們在前面學習了 makefile 中的相關知識,今天我們來看看在 makefile 中變量值的替換。它的替換是指使用指定字符(串)替換變量值中的后綴字符(串),語法格式為:$(var:a=b) 或 ${var:a=b}。注意:a> 替換表達式中不能有任何的空格;b> make 中支持使用 ${ } 對變量進行取值。格式如下
還有種便是變量的模式替換是指使用 % 保留變量值中的指定字符,替換其他字符。語法格式為:$(var:a%b=x%y) 或 ${var:a%b=x%y}。注意:a> 替換表達式中不能有任何的空格;b> make 中支持使用 ${ } 對變量進行取值。格式如下
規則中的模式替換如下
它的意義是通過 target-pattern 從 targets 中匹配子目標;再通過 prereq-pattern 從子目標生成依賴;進而構成完整的規則。我們來看看規則中的模式替換示例如下
下來我們通過代碼來分析說明
src1 := a.cc b.cc c.cc obj1 := $(src1:cc=o) test1 : @echo "obj1 => $(obj1)" src2 := a11b.c a22b.c a33b.c obj2 := $(src2:a%b.c=x%y) test2 : @echo "obj2 => $(obj2)"
我們根據之前說的,在 obj1 中將會把 .cc 替換成 .o,把 obj2 中的 a11b.c a22b.c a33b.c 替換成 x11y x22y x33y。我們來看看編譯器效果
我們看到結果和我們分析的是一樣的。下來再來看看模式替換,將之前的 makefile 進行改編
CC := g++ TARGET := hello-makefile.out OBJS := func.o main.o $(TARGET) : $(OBJS) $(CC) -o $@ $^ $(OBJS) : %.o : %.c $(CC) -o $@ -c $^ .PHONY : rebuild clean all rebuild : clean all all : $(TARGET) clean : $(RM) *.o $(TARGET)
我們來看看編譯效果和之前的是一樣的嗎?
結果是一樣的,這樣的寫的意義在哪呢?在大型的工程項目中,.c源文件是成千上萬的。我們就可以利用模式替換來代替重復的工作,比如我們想添加一個 const.c 文件,便可以直接在第 3 行直接加上 const.o 就OK了。我們來試試看
const.c 源碼
const char* g_hello = "hello makefile";
func.c 源碼
#include "stdio.h" extern char* g_hello; void foo() { printf("void foo() : %s\n", g_hello); }
main.c 源碼
extern void foo(); int main() { foo(); return 0; }
我們來看看編譯效果
我們看到在編譯的時候自動加上了編譯 const.c 的命令,并最終正確打印出結果。這樣感覺是不是很方便哈。那么在 makefile 中變量值還可以嵌套引用,就是一個變量名之中可以包含對其它變量的引用,嵌套引用的本質是使用一個變量來表示另外一個變量。格式如下
下來我們來說說命令行變量,在運行 make 時直接在命令行定義變量。命令行變量默認覆蓋 makefile 中定義的變量,格式如下
那么命令行變量可以覆蓋 makefile 中定義的變量,如果我們不小心手誤覆蓋了呢?這時 override 關鍵字就登場了。它是用于指示 makefile 中定義的變量不能被覆蓋,變量的定義個賦值都需要使用 override 關鍵字。格式如下
下來我們來看看 makefile 中的 define 關鍵字,它是用于在 makefile 中定義多行變量,多行變量的定義從變量名開始帶 endef 結束。可使用 override 關鍵字防止變量被覆蓋,define 定義的變量等價于使用 = 定義的變量。格式入下
下來我們還是以代碼為例來進行說明
hm := hello makefile override var := override-test define foo I'm fool! endef override define cmd @echo "run cmd ls ..." @ls endef test : @echo "hm => $(hm)" @echo "var => $(var)" @echo "foo => $(foo)" ${cmd}
我們來編譯看看結果
我們看到在沒有被 override 關鍵字修飾的變量 hm 可以在命令行對它進行改寫,但是變量 cmd 因為被 override 修飾了,因此就在命令行里面的修改是無效的。下來我們還說說 makefile 中的環境變量(全局變量),在 makefile 中能夠直接使用環境變量的值。它是在定義了同名變量的話,環境變量將被覆蓋,運行 make 時指定“-e”選項,優先使用環境變量。那么為什么要在 makefile 中使用環境變量呢?它的優勢是環境變量可以在所有的 makefile 中使用,劣勢是過多的依賴于環境變量便會導致移植性降低。那么變量在不同的 makefile 支架的傳遞方式有哪些呢?a> 直接在外部定義環境變量進行傳遞;b> 使用 export 定義變量進行傳遞;c> 定義 make 命令進行傳遞(一般推薦使用這種)。
下來我們還是以代碼為例來進行分析
export var := D.T.Software new := TDelphi test : @echo "make another file ..." @$(MAKE) -f makefile.4 @$(MAKE) -f makefile.4 new:=$(new)
makefile.4 源碼
test : @echo "var => $(var)" @echo "new => $(new)"
我們來看看編譯結果
我們看到在第一次的時候 new 為空,在第二次的時候 new 為我們設置的字符串。兩次的 var 都傳遞過去了就是因為我們使用了 export 這個關鍵字。下來我們來看看目標變量(局部變量),其作用域只在指定目標及連帶規則中。格式如下
那么模式變量便是目標變量的擴展,其作用域只在符合模式的目標及連帶規則中。格式如下
下來還是以代碼為例來進行分析說明
var := D.T.Software new := TDelphi test : var := test-var %e : override new := test-new test : another @echo "test :" @echo "var => $(var)" @echo "new => $(new)" another : @echo "another :" @echo "var => $(var)" @echo "new => $(new)" rule : @echo "rule :" @echo "var => $(var)" @echo "new => $(new)"
我們來看看編譯結果
因為 %e 的匹配規則,所以在目標 rule 中,它的 new 為 test-new,凡是跟 test 目標相關的 var 都是 test-var。通過對 makefile 中變量的學習,總結如下:1、makefile 中的變量值能夠嵌套引用;2、命令行中定義的變量能夠覆蓋 makefile 中定義的變量;3、override 用于提示 makefile 中定義的變量不能被覆蓋;4、define 用于在 makefile 中定義值為多行的變量;5、makefile 中的三種變量:a> 全局變量是指 makefile 外部定義的環境變量;b> 文件變量是在 makefile 中定義的變量;c> 局部變量是指定目標的變量。
歡迎大家一起來學習 makefile,可以加我QQ:243343083。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。