2010-07-10 172 views
241
CC=g++ 
CFLAGS=-c -Wall 
LDFLAGS= 
SOURCES=main.cpp hello.cpp factorial.cpp 
OBJECTS=$(SOURCES:.cpp=.o) 
EXECUTABLE=hello 

all: $(SOURCES) $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS) 
    $(CC) $(LDFLAGS) $(OBJECTS) -o [email protected] 

.cpp.o: 
    $(CC) $(CFLAGS) $< -o [email protected] 

[email protected]$<是做什麼的?

+4

上面的鏈接被打破,這是另一個:http://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html – asciz 2013-01-26 01:12:43

+1

嗨這是什麼「.cpp.o :「作爲目標是什麼意思? (在最後一行?)。 – 2013-07-02 06:47:39

+3

「.cpp.o:」意思是從「.cpp」(源文件)構建「.o」(目標文件) – jaguzu 2013-09-13 06:30:17

回答

287

[email protected]是正在生成的文件的名稱,以及$<的第一個先決條件(通常是源文件)。您可以在GNU Make manual中找到所有這些特殊變量的列表。

例如,請考慮下面的聲明:

all: library.cpp main.cpp 

在這種情況下:

+5

值得注意的是'$ @'不一定非得成爲一個文件,它可能也是'.PHONY'目標的名字。 – Ephemera 2015-04-11 08:04:57

+0

我可以添加命令行選項:'$ @ s'來生成彙編輸出,如name.os? – 2017-07-30 16:25:57

57

[email protected]$<被稱爲自動變量。 [email protected]是輸出變量。 $<是第一個輸入變量。例如:

hello.o: hello.c hello.h 
     gcc -c $< -o [email protected] 

這裏,hello.o是輸出文件。這是[email protected]擴展到。第一個依賴項是hello.c。這就是$<的擴展。

-c標誌生成.o文件;有關更詳細的解釋,請參見man gcc-o指定要輸出到的文件。

欲瞭解更多詳情,你可以閱讀this

此外,你可以檢查GNU手冊。有一種方法可以調試makefile以更好地理解它。

這將輸出生成文件數據庫:

$make -p 
+1

你的答案聽起來像'$ <'將擴展到'hello.c hello.h'(兩者)。請澄清。 – 2015-07-10 06:05:16

+0

是的,它會包含hello.c和hello.h – 2015-07-11 04:37:08

+8

'$ <'只是第一個項目。要包含全部,請使用'$ ^'。 – 2015-07-11 05:14:04

23

Managing Projects with GNU Make, 3rd Edition(這是在GNU自由文檔許可證):

自動變量make規則匹配後置。他們 提供對目標和先決條件列表中的元素的訪問權限,所以 您不必明確指定任何文件名。它們非常有用,用於避免代碼重複,但在定義更一般的模式規則時非常重要。

有七個「芯」自動變量:

  • [email protected]:代表目標文件名。

  • $%:檔案成員規範的文件名元素。

  • $<:第一個先決條件的文件名。

  • $?:比目標更新的所有先決條件的名稱, 以空格分隔。

  • $^:所有先決條件的文件名,以空格分隔。此 列表中有重複的文件名被刪除,因爲對於大多數用途,例如 編譯,複製等,不需要重複。

  • $+:到$^相似,這是所有先決條件的名稱用空格分隔 ,除了$+包括重複。這個變量是 爲特定情況創建的,例如連接器的參數,其中 重複值有意義。

  • $*:目標文件名的詞幹。莖通常是沒有後綴的文件名 。它在模式規則之外的使用是不鼓勵的 。

另外,上述各變量的具有用於與其他品牌 兼容性兩個變體。一個變體只返回值的目錄部分 。這通過在 符號,$(@D),$(<D)等上附加「D」來指示。另一個變體僅返回值的文件 部分。這通過在 符號$(@F),$(<F)等上附加「F」來指示。請注意,這些變體名稱長度超過 ,因此必須用圓括號括起來。 GNU make 爲dir和notdir函數提供了一個更可讀的替代方案。

9

生成文件構建hello可執行如果改變的main.cpphello.cppfactorial.cpp任何一個。儘可能小的Makefile來實現這一規範可能是:

hello: main.cpp hello.cpp factorial.cpp 
    g++ -o hello main.cpp hello.cpp factorial.cpp 
  • 親:很容易閱讀
  • CON:維護的噩夢,在C++依賴的重複
  • CON:效率問題,我們重新編譯所有C++即使只有一個被更改

爲了改進上述內容,我們只編譯那些被編輯的C++文件。然後,我們只需將生成的目標文件鏈接在一起。

OBJECTS=main.o hello.o factorial.o 

hello: $(OBJECTS) 
    g++ -o hello $(OBJECTS) 

main.o: main.cpp 
    g++ -c main.cpp 

hello.o: hello.cpp 
    g++ -c hello.cpp 

factorial.o: factorial.cpp 
    g++ -c factorial.cpp 
  • 親:修復效率的問題
  • CON:新的維護的噩夢,在目標文件規則的潛在錯字

爲了改善這一點,我們可以用一個替換所有目標文件的規則.cpp.o規則:

OBJECTS=main.o hello.o factorial.o 

hello: $(OBJECTS) 
    g++ -o hello $(OBJECTS) 

.cpp.o: 
    g++ -c $< -o [email protected] 
  • 親:回到具有較短的makefile,有點易於閱讀

這裏.cpp.o規則定義如何建立從anyfile.cppanyfile.o

  • $<匹配到第一依賴,在這種情況下,anyfile.cpp
  • [email protected]目標相匹配,在這種情況下,anyfile.o

存在於生成文件的其他變化有:

  • 使其更容易從克++到任何C++編譯器的編譯器的變化。
  • 更容易更改編譯器選項。
  • 更易於更改鏈接器選項。
  • 更容易更改C++源文件和輸出。
  • 添加默認規則'all',作爲快速檢查以確保在嘗試構建應用程序之前存在所有源文件。