2009-12-14 140 views
2

如果你有一個包含多個源文件的C++項目,並且你需要編譯,那麼編譯器開始使用哪個文件?C++編譯器在哪裏啓動?

我問的原因我在圖書館有一些#包括依賴關係問題。

編譯器是:VC2003。

回答

15

它不應該是順序依賴的。唯一相關的步驟如下:

  1. 每個編譯單元包括它依賴的內容,應該單獨編譯。這意味着,首先,每個CPP文件包含它所依賴的所有標題;其次,每個頭文件應該包含它所需要的內容,以便它可以編譯,即使它是第一個被編譯的。
  2. 鏈接步驟將所有編譯的目標代碼放在一起並生成最終的二進制文件。
+1

@Daniel:您還可以添加每個頭還應該包含它所依賴的內容,以便即使它是模塊包含的第一個頭也會進行編譯。 – quamrana 2009-12-14 13:29:31

+0

謝謝@quamrana,我試圖將你的評論納入我的答案。 – 2009-12-14 13:44:19

+3

我的方式是:只包含一個'#include'的源文件應該始終編譯(到.o文件)而不會出錯。我使用了一個「hcheck」腳本,它創建了一個.c或.cc文件,它包含在命令行中指定的文件,然後嘗試編譯它,並刪除臨時.c/.cc文件完成。 – 2009-12-14 14:15:02

3

這取決於環境。一般來說,「編譯器」一次只能在單個源文件上工作;您使用更高級的工具來引導它並計算正確的構建順序。

此類工具的示例可以是make,ant,CMake,SCons,Eclipse和Visual Studio。基本檢查通常是源代碼文件的修改日期,以及定義各種輸出文件如何依賴於輸入的內置和自定義規則。

4

無關。發佈確切的問題。編譯順序是非確定性和任意的,並且不會影響項目的可編譯性。

+1

事實上,甚至可能沒有編譯分配的編譯命令。如果它發生在不同的機器上,你不能說在b.cpp之前或之後編譯a.cpp。 – MSalters 2009-12-15 11:18:57

5

它不應該的問題它開始哪個文件,所有文件都被編譯

1

編譯器編譯中不應該有所作爲,正如其他人指出的順序後,鏈接器解析外部引用。

從編譯器的角度來看,當您編譯一個帶有#include的文件時,包含的文件會插入正在編譯的文件中#include所在的位置,並在必要時進行遞歸。

0

正如其他人所指出的那樣,從概念上講,從哪個文件開始並不重要。但是,從具有最多依賴性的文件開始使用最近編輯的文件(假定編輯了多個文件)可能很有用。某些環境(如Code :: Blocks)實際上允許您對源文件進行加權,以使您能夠控制編譯順序。

1

我能想到的唯一的「包含依賴」問題是遞歸包含。對於其修復通常與#ifdef

#ifndef INCLUDED_THEFILENAME_H 
#define INCLUDED_THEFILENAME_H 

/* content goes here * 

#endif 

守着,但你最好在你所遇到的問題的闡述。

+1

請注意,名稱__THEFILENAME_H在用戶編寫的C++代碼中是非法的。 – 2009-12-14 13:14:12

+0

uhm ...對於宏?好吧,無論如何,這個名字是無關緊要的。 – 2009-12-14 13:21:58

+1

@ hacker:即使是宏,你仍然不應該有前導下劃線。對於一個宏來說,大寫就足夠了,當你有'_H''結尾時,它就是一個包含守衛的充分慣例。 – quamrana 2009-12-14 13:27:06

1

其他人已經表示,訂單不應該有所作爲。

你可能沒有意識到的是編譯器編譯每.cpp.cc文件。它確實不是編譯頭文件。而且通常情況下,您只有#include頭文件,而永不.cpp文件,所以順序無關緊要。每個.cpp文件都是獨立處理的。它包含許多標題,但這些標題永遠不會單獨編譯,而且它的確不是而是通常還包含其他.cpp文件。

+0

它不編譯頭文件?如果一個類在頭文件中包含所有的代碼,並且沒有cpp文件呢? – clamp 2009-12-14 15:11:37

+0

Jalf的含義(甚至在後面的段落中提到)是編譯器通常不會自己編譯頭文件*。相反,它通過編譯包含它的.cpp文件隱式編譯頭文件,從這個意義上講,頭文件經常被編譯*多次*,每個包含它的源文件編譯一次。鏈接器將所有重複都作爲最終構建步驟進行分類。 – 2009-12-14 16:53:58

+0

是的。編譯器處理「翻譯單元」。一個翻譯單元是一個.cpp文件的結果,並且複製/粘貼所有'#inc'並評估所有的宏。所以編譯器看到的基本上是一個.cpp文件,並附有所有頭文件。但它從不編譯頭文件* *。 – jalf 2009-12-14 17:42:14

0

make工具構建make文件中指定的依賴項的有向非循環圖。這通常會說可執行文件取決於一些目標文件。目標文件依賴於源文件,每個源文件都依賴於頭文件等等。

這基本上生成一個多路樹。該樹將以可執行文件爲根,並且通常主要包含葉節點的標題(儘管如果您使用的是某種代碼生成器,它也可以將該代碼生成器的輸入文件作爲葉)。

然後,它走過那棵從葉節點到根節點的樹,然後繼續建築。說「無關緊要」的答案基本上指出,它可以選擇樹的任何一個分支來構建第一個分支。但是,當它選擇一個分支時,它會按照爲該分支指定的順序進行構建。