徹底掌握Makefile(二)
徹底掌握Makefile(二)
前言
在前面的文章徹底掌握Makefile(一)當中,我們簡要的介紹了一些常見的makefile使用方法,在本篇文章當中我們將繼續介紹一些makefile當中的常見用法。
Makefile中的條件判斷
ifeq 和 ifneq
我們在寫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>"
ifdef 和 ifndef
除了上面的兩個關鍵字之外,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
在進行判斷的時候並不會將變數直接展開,而是直接判斷成不為空。
Makfile中的函數
在makefile當中除了能夠使用條件表達式之外我們還可以使用函數,在makefile當中函數的使用規則如下:
$(<函數名> <函數參數>)
或者
將()替換為{}
函數的調用規則如上圖所示,函數參數用,隔開。
字元串函數
subst
$(subst <from>,<to>,<text>)
- 字元串替換函數。
表示文本,這個函數會將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
$(patsubst <pattern>,<replacement>,<text>)
- pattern 表示第一個參數,用於表示如何對 text 進行匹配。
- replacement 表示第二個參數 表示如何對匹配的字元進行重寫。
- patsubst在進行匹配替換的時候,會先將字元串text根據空格或者tab鍵或者回車換行符進行分割,然後一一的進行替換和匹配。
這個函數也是一個字元串替換函數,但是與上面的函數不同的是這是一個模式替換。我們直接根據例子來進行分析:
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
$(strip <string>)
- 主要功能去掉字元串 string 首尾的空格。
findstring
$(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)
sort
這個函數主要是用於幫助字元串排序的,同時還會取出分割之後相同的字元串。
s = g a b c d e f a a a a
ss = $(sort $(s))
main: demo.c
echo $(ss)
以上的makefile輸出結果如下圖所示:
從上面的輸出結果我們可以驗證sort不僅可以給字元串排序還會去除相同的字元串。
word
$(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
$(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)
words
統計單詞的個數。
s = 1 2 3 4 5
ss = $(words $(s))
main: demo.c
echo $(ss)
firstword
這個函數主要是用於返回第一個字元串的。
s = 1 2 3 4 5
ss = $(firstword $(s))
main: demo.c
echo $(ss)
在本篇文章當中主要給大家介紹了Makefile當中一些常用的函數和條件語句的使用,整體比較簡單,大家可以對照著makefile和結果自己實現一遍,下期我們將在makefile當中的一些其他的函數!
以上就是本篇文章的所有內容了,我是LeHung,我們下期再見!!!更多精彩內容合集可訪問項目://github.com/Chang-LeHung/CSCore
關注公眾號:一無是處的研究僧,了解更多電腦(Java、Python、電腦系統基礎、演算法與數據結構)知識。