在檔案名中使用通配符

一個簡單的檔案名可以通過使用通配符代表許多檔。Make 中的通配符和Bourne shell 中的通配符一樣是‘*’、‘?’和‘[…]’。例如:指在當前目錄中所有以‘ *.c’結尾的文件。

字元‘~’在檔案名的前面也有特殊的含義。如果字元‘~’單獨或後面跟一個斜杠‘/’,則代 表您的home目錄。如‘~/bin’擴展為‘/home/bin’。如果字元‘~’後面跟一個字,它擴展為home 目錄下以該字為名字的目錄,如‘~John/bin’表示‘home/John/bin’。在一些作業系統(如 ms-dos,ms-windows)中不存在home目錄,可以通過設置環境變數home來類比。

在目標、依賴和命令中的通配符自動擴展。在其他上下文中,通配符只有在您明確表明 調用通配符函數時才擴展。

通配符另一個特點是如果通配符前面是反斜杠‘\’,則該通配符失去通配能力。如 ‘foo\ *bar’表示一個特定的檔其名字由‘foo’、‘*’和‘bar’構成。

通配符例子

通配符可以用在規則的命令中,此時通配符由shell 擴展。例如,下面的規則刪除所有

OBJ檔:
clean:
rm –f *.o

通配符在規則的依賴中也很有用。在下面的makefile規則中,‘make print’將列印所有從 上次您列印以後又有改動的‘.c’文件:

print: *.c
ls $?
touch print

本規則使用‘ptint’作為一個空目標檔(參看使用空目標檔記錄事件);自動變數‘$?’用來列印 那些已經修改的檔,參看自動變數。 當您定義一個變數時通配符不會擴展,如果您這樣寫:

objects = *.o

變數objects的值實際就是字串‘*.o’。然而,如果您在一個目標、依賴和命令中使用變數 objects的值,通配符將在那時擴展。使用下面的語句可使通配符擴展:

objects=$(wildcard *.o)

使用通配符的常見錯誤

下面有一個幼稚使用通配符擴展的例子,但實際上該例子不能完成您所希望完成的任 務。假設可執行檔‘foo’由在當前目錄的所有OBJ 檔創建,其規則如下:

objects = *.o
foo : $(objects)
cc -o foo $(CFLAGS) $(objects)

由於變數objects的值為字串‘.o’,通配符在目標‘foo’的規則下擴展,所以每一個OBJ 檔都 會變為目標‘foo’的依賴,並在必要時重新編譯自己。 但如果您已刪除了所有的OBJ 檔,情況又會怎樣呢?因沒有和通配符匹配的檔,所以 目標‘foo’就依靠了一個有著奇怪名字的檔‘.o’。因為目錄中不存在該檔,make 將發出不能 創建‘*.o’的錯誤資訊。這可不是所要執行的任務。 實際上,使用通配符獲得正確的結果是可能的,但您必須使用稍微複雜一點的技術,該 技術包括使用函數wildcard和替代字串等。詳細內容將在下一節論述。 微軟的作業系統(MS-DOS、MS-WINDOWS)使用反斜杠分離目錄路徑,如:

C:\foo\bar\bar.c

這和Unix風格c:/foo/bar/bar.c等價(‘c:’是驅動器字母)。當make在這些系統上運行時, 不但支援在路徑中存在反斜杠也支持Unix 風格的前斜杠。但是這種對反斜杠的支持不包括 通配符擴展,因為通配符擴展時,反斜杠用作引用字元。所以,在這些場合您必須使用Unix 風格的前斜杠。

函數wildcard

通配符在規則中可以自動擴展,但設置在變數中或在函數的參數中通配符一般不能正常 擴展。如果您需要在這些場合擴展通配符,您應該使用函數wildcard,格式如下:

$(wildcard pattern...)

可以在makefile檔的任何地方使用該字串,應用時該字串被一列在指定目錄下存在的並且檔 案名和給出的檔案名的格式相符合的檔所代替,檔案名中間由空格隔開。如果沒有和指定格 式一致的檔,則函數wildcard 的輸出將會省略。注意這和在規則中通配符擴展的方式不同, 在規則中使用逐字擴展方式,而不是省略方式。 使用函數wildcard得到指定目錄下所有的C語言根源程式檔案名的命令格式為:

$(wildcard *.c)

我們可以把所獲得的C 語言根源程式檔案名的字元串通過將‘.c’尾碼變為‘.o’轉換為OBJ 檔 案名的字串,其格式為:

$(patsubst %.c,%.o,$(wildcard *.c))

這裏我們使用了另外一個函數:patsubst,詳細內容參閱字串替換和分析函數。 這樣,一個編譯特定目錄下所有C 語言根源程式並把它們連接在一起的makefile 檔可 以寫成如下格式:

objects := $(patsubst %.c,%.o,$(wildcard *.c))
foo : $(objects)
cc -o foo $(objects)

這裏使用了編譯C語言根源程式的隱含規則,因此沒有必要為每個檔寫具體編譯規則。

results matching ""

    No results matching ""