2009-07-21 15 views
7

W moim miejscu mamy dużą bazę kodu C++ i myślę, że jest problem z wykorzystaniem plików nagłówkowych.Zależności między nagłówkami plików między modułami C++

Istnieje wiele projektów Visual Studio, ale problem jest w koncepcji i nie jest związany z VS. Każdy projekt jest modułem realizującym określoną funkcjonalność. Każdy projekt/moduł jest skompilowany do biblioteki lub pliku binarnego. Każdy projekt ma katalog zawierający wszystkie pliki źródłowe - * .cpp i * .h. Niektóre pliki nagłówkowe są API modułu (mam na myśli podzbiór plików nagłówkowych deklarujących API utworzonej biblioteki), niektóre są wewnątrz niego.

Teraz na problem - kiedy moduł A musi pracować z modułem B, to A dodaje katalog źródłowy B, aby uwzględnić ścieżkę wyszukiwania. Dlatego wszystkie nagłówki wewnętrznych modułów B są widziane przez A w czasie kompilacji.

Jako efekt uboczny programista nie musi koncentrować się na dokładnym API każdego modułu, co i tak uważam za zły nawyk.

Rozważam opcje, jak powinno być na pierwszym miejscu. Pomyślałem o stworzeniu w każdym projekcie dedykowanego katalogu zawierającego tylko pliki nagłówkowe interfejsu. Moduł klienta, który chce korzystać z modułu, może zawierać tylko katalog interfejsu.

Czy to podejście jest w porządku? W jaki sposób problem rozwiązany jest na twoim miejscu?

UPD Na moim poprzednim miejscu, opracowanie zostało wykonane na Linux zg ++/gmake a my rzeczywiście używany do instalowania plików API nagłówka do wspólnego katalogu jest kilka odpowiedzi zaproponować. Teraz mamy projekt Windows (Visual Studio)/Linux (g ++) używający cmake do generowania plików projektu. Jak wymuszam instalację preampu plików nagłówkowych API w Visual Studio?

Dzięki Dmitry

Odpowiedz

3

Brzmi jak jesteś na dobrej drodze. Wiele bibliotek zewnętrznych robi to samo. Na przykład:

3rdParty/myLib/src/                                  -contains nagłówki i pliki źródłowe potrzebne do kompilacji biblioteki
3rdParty/myLib/include/myLib/    - zawiera nagłówki potrzebne do zewnętrznych aplikacji, które zawierają:

Niektóre osoby/projekty właśnie dodają nagłówki do zewnętrznych aplikacji w/3rdParty/myLib/include, ale dodanie dodatkowego katalogu myLib może pomóc uniknąć kolizji nazw.

Zakładając, że stosując strukturę: 3rdParty/myLib/include/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

czy nie byłoby bardziej intuicyjny umieścić nagłówki interfejsu w katalogu głównym projektu i uczynić podfolder (call to "wewnętrzny" lub "pomocnik" lub coś w tym rodzaju) dla nagłówków innych niż API?

+0

Uważam, że Google umieszcza wszystkie swoje wewnętrzne nagłówki w folderze o nazwie internal. – xian

0

Widziałem problemy, jak to rozwiązano, poprzez zestaw nagłówków w module B, które zostaną skopiowane do katalogu wydania wraz z biblioteką jako częścią procesu kompilacji. Moduł A widzi tylko te nagłówki i nigdy nie ma dostępu do wewnętrznych elementów B.Zwykle widziałem to tylko w dużym projekcie, który został opublikowany publicznie.

W przypadku projektów wewnętrznych po prostu tak się nie dzieje. Zazwyczaj dzieje się tak, że gdy są małe, nie ma to znaczenia. A kiedy dorosną, jest tak niechlujnie, aby go oddzielić, nikt nie chce tego robić.

0

Zazwyczaj po prostu widzę katalog, w którym znajdują się wszystkie nagłówki interfejsu. Z pewnością ułatwia dołączanie nagłówków. Ludzie wciąż muszą zastanowić się, z którymi modułami biorą zależności, kiedy określają moduły dla linkera.

To powiedziawszy, bardziej podoba mi się twoje podejście. Można nawet uniknąć dodawania tych katalogów do ścieżki dołączania, aby ludzie mogli określić, które moduły pliku źródłowego zależą od względnych ścieżek w #includes u góry.

W zależności od projektu, może to być problematyczne przy dołączaniu ich do nagłówków, ponieważ względna ścieżka do nagłówka pochodzi z pliku .cpp, a nie z pliku .h, więc .h plik niekoniecznie musi wiedzieć, gdzie znajdują się pliki .cpp.

Jeśli jednak Twoje projekty mają płaską hierarchię, to zadziała. Załóżmy, że masz

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

Teraz każdy nagłówek pliku może zawierać
#include "..\baz\inc\baz.h
i będzie działać, ponieważ wszystkie pliki cpp są o jeden poziom głębiej niż podstawy.

2

Gdzie pracuję, mamy strukturę folderów dostawy utworzoną w czasie kompilacji. Pliki nagłówkowe definiujące biblioteki są kopiowane do folderu dołączania. Używamy skryptów budowania niestandardowego, które pozwalają programistom określić, które pliki nagłówkowe powinny zostać wyeksportowane.

Nasza kompilacja jest zakorzeniona na dysku subst, co pozwala nam używać ścieżek bezwzględnych do katalogów włączeń.

Posiadamy również referencyjną kompilację sieciową, która pozwala nam używać zmapowanego dysku dla odnośników i odnośników lib.

AKTUALIZACJA: Nasza kompilacja referencyjna to udział sieciowy na naszym serwerze kompilacji. Używamy referencyjnego skryptu budowania, który konfiguruje środowisko kompilacji i mapuje (używając net use) nazwany udział na serwerze kompilacji (tj. \ BLD_SRV \ REFERENCE_BUILD_SHARE). Następnie podczas cotygodniowej kompilacji (lub ręcznie) ustawiamy udział (używając net share), aby wskazać nową kompilację.

Nasze projekty to lista bezwzględnych ścieżek dla odniesień do bibliotek i bibliotek.

Na przykład:

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 

to zajmie Ci lokalnych zmian, a dopiero potem, jeśli nie dokonano żadnych zmian lokalnych (lub przynajmniej ich nie zbudowano) użyje nagłówki i bibliotekami z ostatnia kompilacja na serwerze kompilacji.

+0

Czy możesz wyjaśnić, co to jest referencyjna wersja sieciowa? – dimba

0

W grupie I pracował, wszystko publiczna była utrzymywana w folderze modułu specyficzne, podczas gdy prywatne rzeczy (prywatny nagłówek itp plik cpp) były przetrzymywane w folderze _imp ciągu to:

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

W ten sposób można po prostu przechwycić strukturę folderów projektów i uzyskać żądany nagłówek.Możesz odwołać się do dyrektyw #include zawierających _imp i dobrze się im przyjrzeć. Możesz także pobrać cały folder, skopiować go gdzieś i usunąć wszystkie podkatalogi _imp, wiedząc, że wszystko będzie gotowe do wydania interfejsu API. ramach projektów nagłówków gdzie zazwyczaj uwzględniane jako

#include "foo/foo.h" 

Jednakże, jeśli projekt musiał użyć niektórych API, następnie nagłówki API byłyby kopiowane/instalowane zbudować API gdziekolwiek oni jechać na tej platformie przez kompilacji system, a następnie zainstalować jako nagłówki systemowe:

#include <foo/foo.h> 
Powiązane problemy