2009-07-21 103 views
7

就我而言,我們有一個很大的C++代碼庫,我認爲如何使用頭文件存在問題。C++模塊之間的頭文件依賴關係

有許多Visual Studio項目,但問題是在概念上,並與VS無關。每個項目都是一個模塊,執行特定的功能。每個項目/模塊都被編譯爲庫或二進制文件。每個項目都有一個包含所有源文件的目錄 - * .cpp和* .h。一些頭文件是模塊的API(我的意思是頭文件的子集聲明創建的庫的API),一些頭文件是內部的。

現在的問題 - 當模塊A需要使用模塊B時,比A增加B的源目錄以包含搜索路徑。因此編譯時A會看到所有B的模塊內部頭文件。

作爲一個副作用,開發人員不會被迫集中每個模塊的確切API,我認爲這是一個壞習慣。

我認爲它應該放在第一位。我曾想過在每個項目中創建一個僅包含接口頭文件的專用目錄。允許使用該模塊的客戶端模塊僅包含接口目錄。

這種方法好嗎?問題如何解決?

UPD在我以前的地方,開發是在Linux上用g ++/gmake完成的,我們確實用API API頭文件安裝到一個公共目錄是一些解決方案。現在我們有使用cmake生成項目文件的Windows(Visual Studio)/ Linux(g ++)項目。我如何強制Visual Studio中的API頭文件的預生成安裝?

感謝 梅德

回答

3

這聽起來像你在正確的軌道上。許多第三方庫都是這樣做的。例如:

的3rdParty/MYLIB/SRC/                                  - 包含標頭和所需的源文件編譯庫
的3rdParty/MYLIB /包含/ myLib/    - 包含外部應用程序所需的標頭,包括

有些人/項目只是將頭文件包含在/ 3rdParty/myLib/include中,但添加額外的myLib目錄可以避免名稱衝突。

使用結構假設你:的3rdParty/MYLIB /包括/ MYLIB/

 

In Makefile of external app: 
--------------- 
INCLUDE =-I$(3RD_PARTY_PATH)/myLib/include 
INCLUDE+=-I$(3RD_PARTY_PATH)/myLib2/include 
... 
... 

In Source/Headers of the external app 
#include "myLib/base.h" 
#include "myLib/object.h" 

#include "myLib2/base.h" 
2

那豈不是更直觀的將接口設置標題項目的根源,並作出一個子文件夾(電話它'內部'或'助手'或類似的東西)的非API頭?

+0

我相信Google會將其所有內部標題放在名爲internal的文件夾中。 – xian 2009-07-21 17:54:45

0

我已經看到類似這樣的問題,因爲在模塊B中有一組頭文件作爲構建過程的一部分與lib一起復制到版本目錄中。模塊A只能看到這些頭文件,並且從來沒有訪問過B的內部。通常我只是在一個公開發布的大型項目中看到了這一點。

對於內部項目它不會發生。通常發生的事情是,當他們很小時,這並不重要。當他們長大的時候,很難分開,沒有人願意這樣做。

0

通常我只看到一個包含所有接口頭文件的包含目錄。它確實很容易包含頭文件。當他們爲鏈接器指定模塊時,人們仍然需要考慮他們依賴哪些模塊。

這就是說,我有點更喜歡你的方法。甚至可以避免將這些目錄添加到包含路徑中,以便人們可以通過頂部#includes中的相對路徑知道源文件依賴於哪些模塊。

根據項目的佈局方式,從頭文件中包含它們可能會產生問題,但由於頭文件的相對路徑來自.cpp文件,而不是來自.h文件,所以.h文件不一定知道.cpp文件的位置。

但是,如果您的項目有一個扁平的層次結構,這將起作用。假設你有

base\foo\foo.cpp 
base\bar\bar.cpp 
base\baz\baz.cpp 
base\baz\inc\baz.h 

現在,任何頭文件可以包含
#include "..\baz\inc\baz.h
,它會工作,因爲所有的cpp文件是一個級別比底部深。

2

我在哪裏工作,我們有一個在構建時創建的交付文件夾結構。定義庫的頭文件被複制到包含文件夾中。我們使用自定義構建腳本,讓開發人員指出應該導出哪些頭文件。

我們的版本植根於subst ed驅動器,這使我們可以使用絕對路徑作爲include目錄。

我們還有一個基於網絡的參考版本,它允許我們使用映射驅動器來進行include和lib引用。

更新:我們的參考版本是構建服務器上的網絡共享。我們使用一個引用構建腳本來設置構建環境並在構建服務器上映射(使用net use)指定的共享(即\ BLD_SRV \ REFERENCE_BUILD_SHARE)。然後在每週構建(或手動)期間,我們設置共享(使用net share)指向新構建。

我們的項目然後列出了include和lib引用的絕對路徑。

例如:

subst'ed local build drive j:\ 
mapped drive to reference build: p:\ 
path to headers: root:\build\headers 
path to libs: root:\build\release\lib 
include path in project settings j:\build\headers; p:\build\headers 
lib path in project settings  j:\build\release\lib;p:\build\release\lib 

這將帶你本地修改,然後再如果你還沒有做出任何本地更改(或者至少你還沒有建立它們),它會使用頭文件和庫從你最後在構建服務器上構建。

+0

你能解釋什麼是基於網絡的參考構建? – dimba 2009-07-21 17:50:51

0

在組我一直在努力,一切公衆保持在一個特定的模塊文件夾,而私人的東西(私有頭,CPP文件等)都在此保持在_imp文件夾:

base\foo\foo.h 
base\foo\_imp\foo_private.h 
base\foo\_imp\foo.cpp 

通過這種方式,您可以在項目文件夾結構中抓取並獲取所需的標題。你可以grep找到包含_imp的#include指令,並仔細看看它們。您也可以抓住整個文件夾,將其複製到某個地方,然後刪除所有_imp子文件夾,因爲您知道已準備好發佈API。 在項目頭,其中通常包括作爲

#include "foo/foo.h" 

然而,如果該項目不得不使用一些API,然後API頭會被複制/由API的編譯安裝,無論他們被認爲通過構建去該平臺上系統,然後安裝爲系統標題:

#include <foo/foo.h>