2013-08-05 62 views
3

編譯器如何知道何時不需要重新編譯代碼的某些部分,特別是在大型項目中?編譯器如何知道何時不重新編譯?


例如,假設在C++中我們有兩個C++文件和兩個頭文件。頭文件相互依賴。 (它們使用在其他文件中指定的類)。

編譯器是否總是需要解析頭文件(也可能是用於方法實現的C++文件)以獲取類信息以生成兩個C++文件?


我一直以爲,當你在命令提示符下運行編譯器,其輸出的目標文件後立即關閉 - 所以這將是不可能的緩存抽象語法樹或中間代碼。大多數C++編譯器是否知道某個文件何時不需要輸出到目標文件,因此會被跳過?

+4

這通常是構建系統的工作(例如,做),而不是編譯器的。 –

+0

這是例如使與生成文件 – hamon

+0

的幫助下通常它是做了檢查提出的,這是相當複雜的,告訴哪些文件依賴於哪些其他文件... – xanatos

回答

3

我知道的所有編譯器都會編譯每個源文件,他們會告訴 。總是。並且他們爲他們編譯的每個源文件生成對象 的新版本。

只編譯需要的工作通常是留給 構建系統(make或其他)。知道需要重新生成哪些對象 取決於每個源文件包含的內容,可以直接使用 或間接;大多數編譯器都可以選擇以某種格式輸出此信息,或者是作爲一個獨立的 調用,而構建系統(至少可用的) 使用此信息來確定依賴關係。

0

我不知道他們是如何實現的(因爲許多人不......不要問我爲什麼),但我很確定這很容易。您可以在中間(obj)文件中保存源文件和正在編譯的每個相關文件的名稱和散列,以及正在使用的編譯選項,編譯器的散列(或其內部版本)以及編譯結果(ok/error)。下一次用戶嘗試重新編譯文件時,編譯器會檢查是否已經存在中間文件,檢查所有哈希是否相同,如果編譯選項相同,並且編譯器相同......如果所有內容都是同樣,它給出了預先保存的錯誤消息,並且不做任何事情而退出。

中間文件會稍大一些(可能每個都有一個kb)。

+1

我從來沒有聽說過這樣做的編譯器或構建系統。通常的編譯系統依賴於編譯器輸出來確定依賴關係,以及文件上的時間戳以確定哪些文件實際需要重新編譯。 –

+0

實際上聽起來像'ccache'。如果僅僅是因爲時鐘同步,分佈式構建比本地構建要困難一些。 – MSalters

0

如上所述,編譯器會編譯每個要求編譯的文件。需要make等工具來決定需要編譯的內容。

make之一設置規則。每個規則都有一個目標,依賴關係列表,如果這些依賴關係未得到滿足,則會運行命令。例如,

target.o : target.c 
    gcc -c -o target.o target.c 

在大多數文件系統上,每個文件都有一個時間戳。如果target.o具有比target.c更新的時間戳(規則依賴性),那麼make不會在下面運行gcc命令。這是因爲首先編輯源文件,然後將源文件編譯成目標文件。

但是,如果依賴源文件比目標文件更新,那麼我們知道源文件在編譯發生後編輯,而另一個編譯按順序編輯。因此make將執行該規則的構建命令。

它當規則依賴於其他的規則,但同樣的原則也適用得到了很多更加複雜。