2009-02-12 34 views
57

我最近有理由與一些Visual Studio C++項目一起使用調試和發佈配置,還有'全部釋放'和'全部調試',這是我以前從未見過的。#include所有.cpp文件到單個編譯單元中?

事實證明,項目的作者有一個ALL.cpp,其中包含所有其他.cpp文件。 *所有配置只是建立這一個ALL.cpp文件。它當然被排除在常規配置之外,並且常規配置不會生成ALL.cpp

我只是想知道這是否是一種常見的做法?它帶來了什麼好處? (我的第一反應是它聞起來很糟糕。)

你可能會遇到什麼樣的缺陷?我能想到的一點是,如果你的.cpps中有匿名命名空間,那麼它們不再是該「cpp」的「私有」,而是現在也可以在其他cpp中看到?

所有的項目都建立DLL,所以匿名命名空間中的數據不是一個好主意,對嗎?但功能會好嗎?

乾杯。

+0

我們正式構建總是需要重建,所以我認爲這種做法可以提高構建性能很多。但由於官方版本主要由開發人員使用,但UnityBuild生成的pdbs對於非unitybuild代碼可能無效。 (我們不想用統一編譯配置進行開發,對吧?) – 2010-01-12 10:52:27

+0

完全不同的理由將一些實現文件包含到另一個實現文件中:這些文件可以自動生成。自動生成整個文件比處理注入到現有代碼中的更改要容易得多。 – 2012-07-25 17:32:55

+1

絕對病態;我只能猜測爲什麼有人會這樣做(如果你可以直接問他們,你應該)。通常在C++中,你想做相反的事情,不僅要保持實現文件,而且要保持頭部分離。 (C++項目的一個常見陷阱是「#include spaghetti」,每個頭文件都依賴於其他文件)。也許是爲了測試編譯器? – Morendil 2009-02-12 22:26:38

回答

47

它被一些(和google-able)稱爲「Unity Build」。它非常快速地鏈接並且合理快速地編譯。對於不需要迭代的構建而言,這非常棒,就像從中央服務器構建版本,但不一定需要增量構建。

這是一個PITA來維護。

編輯:這是第一個谷歌鏈接瞭解更多信息:http://buffered.io/posts/the-magic-of-unity-builds/

,使得它很快的事情是,編譯器只需要在一切都讀一次,編譯出來,然後鏈接,而不是做,每.cpp文件。

布魯斯·道森有一個更好的寫了這個在他的博客:http://randomascii.wordpress.com/2014/03/22/make-vc-compiles-fast-through-parallel-compilation/

6

我不知道這是否是ALL.cpp試圖將整個項目單個編譯單元內,以改善編譯器的能力優化程序的大小?

通常,某些優化只能在不同的編譯單元中執行,例如刪除重複的代碼和內聯。我似乎記得最近的編譯器(微軟的,英特爾的,但我不認爲這包括GCC)可以在多個編譯單元中進行優化,所以我懷疑這個「技巧」是不必要的。

這就是說,它會很好奇,看看是否有任何區別。

40

由於三個主要原因,Unity提高了構建速度。第一個原因是所有的共享頭文件只需要被解析一次。許多C++項目都有很多頭文件被大多數或所有CPP文件包含,冗餘解析這些是編譯的主要代價,尤其是如果您有很多短源文件。預編譯頭文件可以幫助解決這個問題,但通常有很多頭文件沒有預編譯。

統一構建提高構建速度的下一個主要原因是因爲編譯器調用次數更少。調用編譯器有一些啓動成本。

最後,冗餘頭解析的減少意味着內聯函數冗餘代碼的減少,因此目標文件的總大小更小,這使得鏈接更快。

Unity builds也可以提供更好的代碼。

Unity builds NOT由於磁盤I/O減少而加快。我用xperf描述了許多構建,我知道我在說什麼。如果您有足夠的內存,那麼操作系統磁盤緩存將避免冗餘I/O - 後續的標題讀取將來自操作系統磁盤緩存。如果你沒有足夠的內存,那麼編譯器的內存佔用就會超出可用內存並被分頁出去,所以統一編譯甚至會使編譯時間變得更糟。

磁盤I/O很貴,這就是爲什麼所有操作系統都積極緩存數據以避免冗餘磁盤I/O。

1

我同意布魯斯;根據我的經驗,我嘗試過爲我的.dll項目中的一個項目實施Unity Build,這些項目包含大量的頭文件和大量的.cpp文件;爲了減少VS2010上的整體編譯時間(已經用盡了Incremental Build選項),但不是縮短編譯時間,而是耗盡內存,Build甚至無法完成編譯。

但是要添加;我確實發現在Visual Studio中啓用多處理器編譯選項對於縮短編譯時間非常有幫助;我不確定在其他平臺編譯器中是否有這樣的選項。

相關問題