MakeFile 使用


Makefile中的%標記和系統通配符*的區別在於,*是應用在系統中的,%是應用在這個Makefile文件中的。

(本文的測試環境是Windows7下使用MinGW提供的make.exe)

例如,如果你想編譯一個文件夾下的所有.c文件,你可能會這樣寫:

1 %.o:%.c 2 gcc -o $@ $<

但是如果整個文件只有這兩行的話,就會出現這樣的錯誤:

Make: *** target not found. stop.

 


 

要知道原因,我們先來看看另一個makefile的運行過程,例如有Makefile如下:

復制代碼
 1 test1.o:test1.c  2  3 gcc -o test1.o test1.c  4  5  6 test2.o:test2.c  7  8 gcc -o test2.o test2.c  9 10 11 all:test1.o test2.o
復制代碼

如果沒有指定輸出項目的時候Make會自動找到makefile中第一個目標中沒有通配符的目標進行構造,所以步驟是:

  1. 構造all,發現需要test1.o和test2.o
  2. 這個時候他就會在Makefile文件中找到目標能匹配test1.o和test2.o的規則。
  3. 找到test1.o的規則並且知道test1.c存在,運行下面的命令。
  4. 同步驟三構造出test2.o
  5. 現在構造all的源文件已經齊全,構建all

 

其中最重要的是第2步。

Makefile的通配符是在帶着目的(如“尋找test1.o”)的時候才會把他要尋找的目標套用通配符%中。

 

所以通配符%的意思是:

  •  我要找test1.o的構造規則,看看Makefile中那個規則符合。
  •  然后找到了%.o:%.c,
  •  來套一下來套一下:
  •  %.o 和我要找的 test1.o 匹配
  • 套上了,得到%=test1。
  • 所以在后面的%.c就表示test1.c了。
  • OK進行構造

 

而通配符*的意思是:

  • 不知道目標的名字,系統該目錄下中所有后綴為.c的文件都是我要找的。
  • 然后遍歷目錄的文件,看是否匹配。找出所有匹配的項目。

 

所以雖然連個符號的意思有點沾邊,但是他們的工作方式時完全不一樣。

 


 

現在知道了為什么文件中只有

1 %.o:%.c 2 gcc -o $@ $<

會找不到目標了吧。因為沒有-f參數時Make會自動找到makefile中第一個目標中沒有通配符的目標進行構造,所以就等於找不到目標了。它的意思並不會自動把文件中所有的文件都編譯。

 

所以正確的代碼應該是:

1 all:$(subst .c,.o,$(wildcard *.c)) 2 3 %.o:%.c 4 gcc -o $@ $<

這才是把目錄下所有文件都編譯的命令。

 

下面是幾個特舒符號的意思:

 

$@:目標的名字

$^:構造所需文件列表所有所有文件的名字

$<:構造所需文件列表的第一個文件的名字

$?:構造所需文件列表中更新過的文件

 

例如:

1 test1.o:test1.c 2 gcc -o $@ $<

$@:就是test1.o

$<:就是test1.c

1 test1.o:test1.c head.c 2 gcc -o $@ $^

$^:就是test1.c head.c

 

$(subst 要被替換的字符串,用來替換的字符串,被處理的字符串)

用“用來替換的字符串”替換“被處理的字符串”中的“要被替換的字符串”

所以:

$(subst .c,.o,test1.c test2.c)

就會得到test1.o test2.o

 

$(wildcard 尋找的文件)

在系統中尋找文件

例如:

$(wildcard *.c)

就等於找到系統中所有后綴為.c的文件,返回成以空格隔開的一整行字符

例如:test1.c test2.c test3.c 這樣

 

$(basename 文件名)

取得文件的名字(去掉后綴的意思)

例如:

$(basename test1.c)

就會取得test1

 

$(addprefix 前綴名,字符串1 字符串2 ...)

給字符串組添加前綴

$(addprefix fixstring,string1 string2 ...)

 

 

$(addsuffix 后綴名,字符串1 字符串2 ...)

給字符串組添加后綴

$(addsuffix suffixstring,string1 string2 ...)

 

 

foreach 函數和別的函數非常的不一樣。因為這個函數是用來做循環用的,Makefile中的foreach函數幾乎是仿照於Unix標准Shell (/bin/sh)中的for語句,或是C-Shell(/bin/csh)中的foreach語句而構建的。它的語法是:

   $(foreach <var>,<list>,<text>)


這個函數的意思是,把參數<list>;中的單詞逐一取出放到參數<var>;所指定的變量中,然后再執行< text>;所包含的表達式。每一次<text>;會返回一個字符串,循環過程中,<text>;的所返回的每個字符串會以空格分隔,最后當整個循環結束時,<text>;所返回的每個字符串所組成的整個字符串(以空格分隔)將會是foreach函數的返回值。
所以,<var>;最好是一個變量名,<list>;可以是一個表達式,而<text>;中一般會使用<var>;這個參數來依次枚舉<list>;中的單詞。舉個例子:

    names := a b c d

    files := $(foreach n,$(names),$(n).o)

上面的例子中,$(name)中的單詞會被挨個取出,並存到變量“n”中,“$(n).o”每次根據“$(n)”計算出一個值,這些值以空格分隔,最后作為foreach函數的返回,所以,$(files)的值是“a.o b.o c.o d.o”。
注意,foreach中的<var>;參數是一個臨時的局部變量,foreach函數執行完后,參數<var>;的變量將不在作用,其作用域只在foreach函數當中。

 

'@'  符號的使用
      通常makefile會將其執行的命令行在執行前輸出到屏幕上。如果將‘@’添加到命令行前,這個命令將不被make回顯出來。
      例如:@echo --compiling module----;  // 屏幕輸出 --compiling module----
                                echo --compiling module----;  // 沒有@ 屏幕輸出echo --compiling module----    

 

 
' - ' 符號的使用
     
     通常刪除,創建文件如果碰到文件不存在或者已經創建,那么希望忽略掉這個錯誤,繼續執行,就可以在命令前面添加 -,
     -rm dir;
     -mkdir aaadir;
 
' $ '符號的使用
           美元符號$,主要擴展打開makefile中定義的變量
 
' $$ '符號的使用
          $$ 符號主要擴展打開makefile中定義的shell變量
 
例如:
     @for dir in $(subdirs); do \

          @echo -------compiling $$dir-----------; \
          $(MAKE) -C?"; \
     done

以上subdir屬於makefile中定義的變量,而dir則屬於makefile中定義的shell變量,所有使用是使用 ‘ $$ ’ 而不是 ' $ '。
 
 
如果make執行時,帶入make參數“-n”或“--just-print”,那么其只是顯示命令,但不會執行命令,這個功能很有利於我們調試我們的Makefile,看看我們書寫的命令是執行起來是什么樣子的或是什么順序的。 

而make參數“-s”或“--slient”則是全面禁止命令的顯示。

 

 

 

轉載:http://www.cnblogs.com/warren-wong/p/3979270.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM