2011-02-01 61 views
0

我們使用Microsoft NMAKE編譯大量本機C++和某些英特爾Fortran文件。典型地,生成文件所包含的行如本(對於每個文件):更改較早的makefile系統以利用並行編譯

$(LINKPATH)\ olemisc.obj:OLE2 \ olemisc.cpp $(OLEMISC_DEP)
$(CCDEBUG)OLE2 \ olemisc.cpp
$ (GDEPS)OLE2 \ olemisc.cpp

OLEMISC_DEP = \
E:\ OLE2 \ ifaceole.hpp \
E:\ OLE2 \ cpptypes.hpp \

它工作正常,但一次編譯一個文件。我們希望利用多核處理器並一次編譯多個文件。我希望得到關於實現這一目標的最佳方式的一些建議。這是我到目前爲止。

一: GNU化妝可以讓你使用例如--jobs = 2選項執行並行作業和正常工作與海灣合作委員會(我們不能使用GCC黯然)。但是微軟的NMAKE似乎不支持這種選擇。這兩個名稱程序的兼容性如何,如果我們開始使用GNU MAKE,您是否可以同時運行兩個cl.exe進程?我希望他們抱怨PDB(調試)文件被鎖定,或者是否有一個新的cl.exe命令行參數可以幫助你解決這個問題?

二: cl.exe時具有/ MP(構建具有多個進程)標誌,它可以讓你在同一時間編譯多個文件是否通過命令行傳遞在一起,例如:

CL/MP7 a.cpp b.cpp c.cpp d.cpp e.cpp

但是使用這將需要更改生成文件。我們的make文件是由我們自己的程序從其他文件生成的,所以我可以輕鬆地更改我們在makefile中的內容。但是,如何將來自不同cpp文件的依賴關係結合在makefile中,以便通過一次cl.exe調用將它們一起編譯?每個.obj都有一組不同的目標和一組命令來完成它?

或者我更改makefile來不調用cl.exe,而是我們編寫的其他一些小的可執行文件,然後將一系列.cpp文件集中在一起,然後將shell傳出到cl.exe,傳遞多個參數?這將工作,似乎可行,但也似乎過於複雜,我不能看到其他人這樣做。

我錯過了一些明顯的東西嗎?必須有一個更簡單的方法來完成這個?

我們不使用Visual Studio或解決方案文件進行編譯,因爲文件列表非常廣泛,我們在makefile中有一些特殊項目,理論上不希望過度依賴於MS C++等

回答

1

我徹底推薦在Windows上使用GNU make。我傾向於使用cygwin make,因爲它創建的環境往往是可移植到類Unix平臺(Mac和Linux的一開始)的。使用Microsoft工具鏈進行編譯並行並具有100%準確的依賴關係和CPU使用情況非常有效。你有其他的要求,但。

只要你的nmake問題去了,在手冊中查找batch-mode inference rules。基本上,nmake能夠一次調用C編譯器,一次傳遞一整個C文件。因此,您可以使用編譯器的/MP...類型開關。

內置於編譯器中的並行編譯?呸!可怕的破碎我說。這裏是一個骨架反正:

OBJECTS = a.obj b.obj c.obj 
f.exe: $(OBJECTS) 
    link $** -o [email protected] 

$(OBJECTS): $$(@R).c 

# "The only syntactical difference from the standard inference rule 
# is that the batch-mode inference rule is terminated with a double colon (::)." 
.c.obj:: 
    cl -c /MP4 $< 

編輯

如果每個.obj都有其自己的依賴(可能!),那麼你只需添加爲單獨的依賴性線(即,他們沒有任何shell命令附帶)。

a.obj: b.h c.h ../include/e.hpp 
b.obj: b.h ../include/e.hpp 
    ∶ 

通常這樣的鍋爐板由另一工具和!INCLUDE d到主生成文件生成。如果你很聰明,那麼你可以在編譯時免費生成這些依賴關係。 (如果你走得很遠,那麼nmake開始在接縫處吱吱作響,你也許應該換成GNU make。)

0

好吧,我今天早上花了一些時間在這個上面工作,並且感謝bobbogo,我得到了它工作。下面是其他任何人的具體細節是誰考慮這個:

舊風格的makefile即一次編譯一個文件有噸這樣的:

$(LINKPATH)\PS_zlib.obj : zlib\PS_zlib.cpp $(PS_ZLIB_DEP) 
     $(CC) zlib\PS_zlib.cpp 

$(LINKPATH)\ioapi.obj : zlib\minizip\ioapi.c $(IOAPI_DEP) 
     $(CC) zlib\minizip\ioapi.c 

$(LINKPATH)\iowin32.obj : zlib\minizip\iowin32.c $(IOWIN32_DEP) 
     $(CC) zlib\minizip\iowin32.c 

注意,每個文件在一次編譯一個。所以現在你想用花哨的Visual Studio 2010/MP開關「/ MP [n]最多使用'n'進程進行編譯」來同時編譯多個文件。怎麼樣?你的Makefile需要利用在NMAKE一批推理規則,如下:

$(LINKPATH)\PS_zlib.obj : zlib\PS_zlib.cpp $(PS_ZLIB_DEP) 

$(LINKPATH)\ioapi.obj : zlib\minizip\ioapi.c $(IOAPI_DEP) 

$(LINKPATH)\iowin32.obj : zlib\minizip\iowin32.c $(IOWIN32_DEP) 

#Batch inference rule for extension "cpp" and path "zlib": 
{zlib}.cpp{$(LINKPATH)}.obj:: 
     $(CC) $(CCMP) $< 

#Batch inference rule for extension "c" and path "zlib\minizip": 
{zlib\minizip}.c{$(LINKPATH)}.obj:: 
     $(CC) $(CCMP) $< 

在這種情況下,在其他地方,我們有

CCMP = /MP4 

注意,執行nmake推理批規則不支持通配符或空格在路徑中。我在某處發現了一些體面的nmake文檔,指出您需要爲每個擴展名和源文件位置創建單獨的規則,如果這些文件位於不同位置,則不能有一條規則。另外,使用#import的文件不能用/ MP編譯。

我們有一個工具可以生成我們的makefile,所以它現在也生成批量推斷規則。

但它的工作!編譯一個大dll的時間從12分鐘降到7分鐘!哇噢!

+0

有人給我一個「這很有用」的勾號給你所有的細節嗎? * grins * – 2011-03-17 19:48:46

1

需要牢記的一點是:您基本上必須爲每個路徑和擴展名定義一個批處理規則。但是,如果在兩個不同的源目錄中有兩個具有相同名稱的文件並且這些目錄具有批處理推理規則,則批處理規則可能不會選擇您想要的文件。

基本上,make系統知道它需要製作一個obj文件,只要它找到一個推理規則,它就會使用它。

解決方法是不要有重複的命名文件,如果不能避免,不要使用這些文件的推理或批處理規則。