Makefile中wildcard的介紹
在Makefile規則中,通配符會被自動展開。但在變量的定義和函數引用時,通配符將失效。這種情況下如果需要通配符有效,就需要使用函數“wildcard”,它的用法是:$(wildcard PATTERN...) 。在Makefile中,它被展開為已經存在的、使用空格分開的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函數會忽略模式字符並返回空。需要注意的是:這種情況下規則中通配符的展開和上一小節匹配通配符的區別。
一般我們可以使用“$(wildcard *.c)”來獲取工作目錄下的所有的.c文件列表。復雜一些用法;可以使用“$(patsubst %.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函數獲取工作目錄下的.c文件列表;之后將列表中所有文件名的后綴.c替換為.o。這樣我們就可以得到在當前目錄可生成的.o文件列表。因此在一個目錄下可以使用如下內容的Makefile來將工作目錄下的所有的.c文件進行編譯並最后連接成為一個可執行文件:
#sample Makefile
objects := $(patsubst %.c,%.o,$(wildcard *.c))
foo : $(objects)
cc -o foo $(objects)
這里我們使用了make的隱含規則來編譯.c的源文件。對變量的賦值也用到了一個特殊的符號(:=)。
1、wildcard : 擴展通配符
2、notdir : 去除路徑
3、patsubst :替換通配符
例子:
建立一個測試目錄,在測試目錄下建立一個名為sub的子目錄
$ mkdir test
$ cd test
$ mkdir sub
在test下,建立a.c和b.c2個文件,在sub目錄下,建立sa.c和sb.c2 個文件
建立一個簡單的Makefile
src=$(wildcard *.c ./sub/*.c)
dir=$(notdir $(src))
obj=$(patsubst %.c,%.o,$(dir) )
all:
@echo $(src)
@echo $(dir)
@echo $(obj)
@echo "end"
執行結果分析:
第一行輸出:
a.c b.c ./sub/sa.c ./sub/sb.c
wildcard把 指定目錄 ./ 和 ./sub/ 下的所有后綴是c的文件全部展開。
第二行輸出:
a.c b.c sa.c sb.c
notdir把展開的文件去除掉路徑信息
第行輸出:
a.o b.o sa.o sb.o
在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的變量符合后綴是.c的全部替換成.o,
任何輸出。
或者可以使用
obj=$(dir:%.c=%.o)
效果也是一樣的。
這里用到makefile里的替換引用規則,即用您指定的變量替換另一個變量。
它的標准格式是
$(var:a=b) 或 ${var:a=b}
它的含義是把變量var中的每一個值結尾用b替換掉a
=========================================================================================
此兩者均為通配符,但更准確的講,%為Makefile規則通配符,一般用於規則描述,如
%.o:%c
$(CC) $< -o $@
表示所的目標文件及其依賴文件,或者
$(filter %.c ,SOURCES)
此處SOURCES表示包含.c .cc .cpp等多類型源文件,該過濾器函數將c文件過濾出來,而%.c即為此過濾器規則。
通配符*則不具備上述功能。尤其是在Makefile,當變量定義或者函數調用時,該通配符的展開功能就失效了,即不能正常使用了,此時需要借助wildcard函數。二者應用范圍不同。
=============================================================================================================
.PHONY :$(ModuleLib) all clean
all :$(target)
$(target) :$(ModuleLib) $(Srcs_obj) $(DependLib)
@echo Making target...
$(CC) -lpthread -lrt -lgcov $(LDFLAGS) -o $@ -Wl,--start-group $^ -Wl,--end-group
$(ModuleLib):
$(RM) $(ModuleLib)
cd $(ModuleDir)/make && ./mkfppall.sh gtest
%.co :%.c
@echo Compiling Src file:[$(notdir $<)]...
$(CC) $(CXXFLAGS) -c $< -o $@
clean :
$(RM) $(Srcs_obj) $(Srcs_gcno) $(app)
makefile中的偽目標:
A phony target is one that is not really the name of a file; rather it is just a name for a recipe to be executed when you make an explicit request. There are two reasons to use a phony target: to avoid a conflict with a file of the same name, and to improve performance.
在本例中,$(ModuleLib)由於沒有依賴文件,因此,在普通的make中不會執行命令(因為沒有文件比它新),現在將其作為偽目標之一,因為
偽目標gcc不當做真正的文件,因此不會去比較目標新舊,其命令總是能被執行。
https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
偽目標總是能夠被執行。
如果一個目標不存在,就相當於隱式的偽目標,它的命令也總是可以跑一邊。
makefile:
1、如果目標不存在,執行命令。(包括依賴和命令)
2、如果目標存在,依賴文件有更新(依賴文件是遞歸的,找依賴的依賴,如果有更新,就更新)。執行命令。
3、如果目標存在,且依賴沒有更新,(遞歸的,包括依賴的依賴。。。),不更新,不執行命令。
============================================================================================================
%和*的區別:
此兩者均為通配符,但更准確的講,%為Makefile規則通配符,一般用於規則描述,如
%.o:%c
$(CC) $< -o $@
表示所的目標文件及其依賴文件,或者
$(filter %.c ,SOURCES)
此處SOURCES表示包含.c .cc .cpp等多類型源文件,該過濾器函數將c文件過濾出來,而%.c即為此過濾器規則。
通配符*則不具備上述功能。尤其是在Makefile,當變量定義或者函數調用時,該通配符的展開功能就失效了,即不能正常使用了,此時需要借助wildcard函數。二者應用范圍不同。
=====================================================================================================================
cd 命令在makefile里面只對當前行有用。
比如你在/opt下執行makefile
如果我要tar開一個包在 /lib下
cd /lib
tar -xvf xxxx.tar
結果只會將這個tar包在執行makefile的當前目錄下/opt解包
正確寫法是:
cd /lib && tar -xvf xxxx.tar 或者 cd /lib; tar -xvf xxxx.tar