在前面的文章徹底掌握Makefile(一)當中,我們簡要的介紹了一些常見的makefile使用方法,在本篇文章當中我們將繼續介紹一些makefile當中的常見用法。
我們在寫makefile的時候常常會有通過if語句進行判斷的需求,比如說根據不同的檔案設定不同的編譯器等等。
cc=g++
main: demo.c
echo $(cc)
ifeq ($(cc), gcc)
echo $(cc) = 相等的語句執行了
else
echo $(cc) != 不相等的語句執行了
endif
上面的makeifle的執行結果如下:
在上面的makefile當中定義了一個變數cc,他的值為gcc。在上面的makefile當中ifeq
表示如果後邊的表示式成立的話,也就是$(cc)
的值等於gcc
那麼就執行後面的語句,否則執行else後面的語句。根據上面makefile的執行結果來看,$(cc)和gcc不相等,因此和我們的期待的結果是一致的。
我們修改上面的makefile檔案如下:
cc=g++
main: demo.c
echo $(cc)
ifneq ($(cc), gcc)
echo $(cc) != gcc
else
echo $(cc) = gcc
endif
執行上面的makefile檔案輸出的結果如下:
在上面的makefile當中ifneq
的含義表示如果不相等,因為g++不等於gcc,因此這個滿足條件,程式執行的結果滿足條件。
關於make的輸出問題,當makefile執行到echo $(cc) != gcc
的時候,首先這條命令會被make輸出,然後make會執行這條命令,而這條命令是輸出g++ != gcc
,因此才會有上面的輸出。echo g++ != gcc
,而執行這條命令還會輸出g++ != gcc
,看到這應該能夠理解上面的makefile的輸出結果了。
前面兩個關鍵字的語法如下所示:
ifeq (<arg1>, <arg2>)
ifeq '<arg1>' '<arg2>'
ifeq "<arg1>" "<arg2>"
ifeq "<arg1>" '<arg2>'
ifeq '<arg1>' "<arg2>"
ifneq (<arg1>, <arg2>)
ifneq '<arg1>' '<arg2>'
ifneq "<arg1>" "<arg2>"
ifneq "<arg1>" '<arg2>'
ifneq '<arg1>' "<arg2>"
除了上面的兩個關鍵字之外,make還給我們提供了另外兩個關鍵字ifdef
和ifndef
。
ifdef
和ifndef
用於判斷表示式是否定義過,或者是否為空:
foo = 1
main: demo.c
echo demo
ifdef foo
echo define foo
else
echo not define foo
endif
上面的makefile的輸出結果如下:
在上面的makefile當中我們定義了foo,因此ifdef
判斷正確,輸出define foo
,現在修改上面的makefile如下所示說:
main: demo.c
echo demo
ifdef foo
echo define foo
else
echo not define foo
endif
在上面的makefile當中我們沒有定義foo
,因此在上面的makefile當中會輸出not define foot
。
我們在來看一個結果比較令人疑惑的makefile:
foo =
main: demo.c
echo demo
ifdef foo
echo define foo
else
echo not define foo
endif
在上面的makefile當中我們定義了foo,但是他沒有值,我們看一下這個makefile的輸出結果:
上面makefile的輸出表示foo
沒有被定義,因此當我們定義一個空變數的時候和不定義的效果是一樣的。
bar =
foo = $(bar)
main: demo.c
echo demo
ifdef foo
echo define foo
else
echo not define foo
endif
在上面的makefile當中我們定義了一個空的變數bar
但是我們令foot=$(bar)
我們看一下上面的makefile檔案的輸出:
可以看出是定義了foo的雖然foo的真實的值也為空,從這裡也可以看出ifdef
和ifndef
在進行判斷的時候並不會將變數直接展開,而是直接判斷成不為空。
在makefile當中除了能夠使用條件表示式之外我們還可以使用函數,在makefile當中函數的使用規則如下:
$(<函數名> <函數引數>)
或者
將()替換為{}
函數的呼叫規則如上圖所示,函數引數用,隔開。
$(subst <from>,<to>,<text>)
s = ii am learning makefile
ss = $(subst ii, you, $(s))
main: demo.c
echo demo
echo $(s)
echo $(ss)
上面的makefile執行結果如下圖所示:
從上面的結果我們可以看出,確實將字串s當中的ii替換成了you!
$(patsubst <pattern>,<replacement>,<text>)
這個函數也是一個字串替換函數,但是與上面的函數不同的是這是一個模式替換。我們直接根據例子來進行分析:
s = a.c b.c d.c abc.c abo.c
ss = $(patsubst %.c, %.o, $(s))
main: demo.c
echo demo
echo $(s)
echo $(ss)
執行make命令上面的makefile的輸出結果如下圖所示:
從上面的結果我們可以看出,patsubst函數將所有的.c檔案的字尾都變成了.o。
在上面的makefile當中首先會將$(s)當中的字串按照回車換行、空格以及tab鍵將$(s)當中的進行分割,然後一個一個進行patsubst操作,然後將得到結果合併起來。
在上面的patsubst函數當中%符號是一個萬用字元,他匹配了.c前面的所有符號。
在pattern當中的符號為"%.c",這個表示用%匹配了.c前面的所有的字元。
在replacement當中的字串為"%.o",這個%用於表示在pattern當中匹配到的字串,比如對於abo.c來說%就代表了abo,因此被替換的字串就是abo.o。
你如果你對Python有所瞭解的話,那麼上面的替換程式碼等價的Python程式碼如下所示:
$(strip <string>)
$(findstring <find>,<text>)
filter
$(filter <pattern...>,<text>)
這是一個過濾函數,這個函數執行時,首先會根據空格或者tab鍵或者回車換行符進行分割,然後一一的進行filter函數的操作。然後遍歷每一個被分割出來的字元,如果不滿足pattern的規則的話對應的字元就會被過濾掉。
s = a.c abo.c s.o s.y x.o x.y
ss = $(filter %.c %.o, $(s))
main: demo.c
echo $(ss)
上面的makefile執行之後輸出的結果如下圖所示:
可以看過濾掉了不是以.c和.o結尾的檔案。
上面的過濾函數對應的Python程式碼如下所示:
filter-out
這個函數和filter的用法是一樣的只不過,作用剛好相反,filter是儲存符合條件的字串,filter-out是儲存不符合條件的字串。
s = a.c abo.c s.o s.y x.o x.y
ss = $(filter-out %.c %.o, $(s))
main: demo.c
echo $(ss)
這個函數主要是用於幫助字串排序的,同時還會取出分割之後相同的字串。
s = g a b c d e f a a a a
ss = $(sort $(s))
main: demo.c
echo $(ss)
以上的makefile輸出結果如下圖所示:
從上面的輸出結果我們可以驗證sort不僅可以給字串排序還會去除相同的字串。
$(word <n>,<text>)
這個功能很簡單,返回
s = g a b c d e f a a a a
ss = $(word 1, $(s)) # 取出第一個字元
main: demo.c
echo $(ss)
$(wordlist <start>,<end>,<text>)
這個也是從字串當中取出字元,是取出第
s = g a b c d e f a a a a
ss = $(wordlist 1, 5, $(s))
main: demo.c
echo $(ss)
統計單詞的個數。
s = 1 2 3 4 5
ss = $(words $(s))
main: demo.c
echo $(ss)
這個函數主要是用於返回第一個字串的。
s = 1 2 3 4 5
ss = $(firstword $(s))
main: demo.c
echo $(ss)
在本篇文章當中主要給大家介紹了Makefile當中一些常用的函數和條件語句的使用,整體比較簡單,大家可以對照著makefile和結果自己實現一遍,下期我們將在makefile當中的一些其他的函數!
以上就是本篇文章的所有內容了,我是LeHung,我們下期再見!!!更多精彩內容合集可存取專案:https://github.com/Chang-LeHung/CSCore
關注公眾號:一無是處的研究僧,瞭解更多計算機(Java、Python、計算機系統基礎、演演算法與資料結構)知識。