2009-07-21 30 views
7

Ở vị trí của tôi, chúng tôi có một cơ sở mã C++ lớn và tôi nghĩ có vấn đề về cách sử dụng các tệp tiêu đề.Phụ đề tập tin phụ thuộc giữa các mô-đun C++

Hiện có nhiều dự án Visual Studio, nhưng vấn đề ở dạng khái niệm và không liên quan đến VS. Mỗi dự án là một mô-đun, thực hiện chức năng cụ thể. Mỗi dự án/mô-đun được biên dịch thành thư viện hoặc nhị phân. Mỗi dự án có một thư mục chứa tất cả các tệp nguồn - * .cpp và * .h. Một số tệp tiêu đề là API của mô-đun (ý tôi là tập con của tập tin tiêu đề khai báo API của thư viện đã tạo), một số là nội bộ của nó.

Bây giờ cho vấn đề - khi mô-đun A cần làm việc với mô đun B, hơn A thêm thư mục nguồn của B để bao gồm đường dẫn tìm kiếm. Do đó tất cả các tiêu đề nội bộ của mô-đun B được xem bởi A tại thời gian biên dịch.

Là một tác dụng phụ, nhà phát triển không bị buộc phải tập trung API chính xác của từng mô-đun, điều mà tôi coi là một thói quen xấu.

Tôi xem xét các tùy chọn về vị trí đầu tiên. Tôi nghĩ về việc tạo ra trong mỗi dự án một thư mục chuyên dụng chỉ chứa các tệp tiêu đề giao diện. Mô-đun khách hàng muốn sử dụng mô đun chỉ được phép bao gồm thư mục giao diện.

Cách tiếp cận này có ổn không? Làm thế nào vấn đề được giải quyết tại chỗ của bạn?

UPD Ở vị trí trước đây, sự phát triển đã được thực hiện trên Linux với g ++/gmake và chúng tôi thực sự sử dụng để cài đặt các tệp tiêu đề API vào một thư mục chung. Bây giờ chúng ta có dự án Windows (Visual Studio)/Linux (g ++) sử dụng cmake để tạo các tệp dự án. Làm thế nào tôi buộc các prebuild cài đặt các tập tin tiêu đề API trong Visual Studio?

Cảm ơn Dmitry

Trả lời

3

Có vẻ như bạn đã đi đúng hướng. Nhiều thư viện của bên thứ ba làm điều tương tự như vậy. Ví dụ:

3rdParty/mylib/src/                                  -contains các tiêu đề và các tập tin nguồn cần thiết để biên dịch thư viện
3rdParty/mylib/include/myLib/    - chứa các tiêu đề cần thiết cho các ứng dụng bên ngoài để bao gồm

Một số người/dự án chỉ đưa tiêu đề vào các ứng dụng bên ngoài trong/3rdParty/myLib/include, nhưng việc thêm thư mục myLib bổ sung có thể giúp tránh xung đột tên.

Giả sử bạn sử dụng cấu trúc: 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

nó sẽ không được trực quan hơn để đặt tiêu đề giao diện trong thư mục gốc của dự án, và thực hiện một thư mục con (gọi nó 'nội bộ' hoặc 'trợ giúp' hoặc một cái gì đó tương tự) cho các tiêu đề không phải API?

+0

Tôi tin rằng Google đặt tất cả tiêu đề nội bộ của chúng vào một thư mục có tên nội bộ. – xian

0

Tôi đã nhìn thấy các vấn đề như thế này được giải quyết bằng cách đặt tập hợp các tiêu đề trong mô-đun B được sao chép sang thư mục phát hành cùng với lib như một phần của quá trình xây dựng. Mô-đun A sau đó chỉ thấy các tiêu đề đó và không bao giờ có quyền truy cập vào nội bộ của B.Thông thường tôi chỉ thấy điều này trong một dự án lớn được phát hành công khai.

Đối với các dự án nội bộ, điều đó không xảy ra. Điều thường xảy ra là khi chúng nhỏ, nó không quan trọng. Và khi chúng lớn lên thì rất lộn xộn để tách nó ra không ai muốn làm điều đó.

0

Thông thường tôi chỉ nhìn thấy một thư mục bao gồm tất cả các tiêu đề giao diện được xếp chồng vào. Nó chắc chắn làm cho nó dễ dàng bao gồm các tiêu đề. Mọi người vẫn phải suy nghĩ về những mô-đun họ đang dùng phụ thuộc vào khi họ xác định các mô-đun cho mối liên kết.

Điều đó nói rằng, tôi thích cách tiếp cận của bạn tốt hơn. Bạn thậm chí có thể tránh thêm các thư mục này vào đường dẫn bao gồm, để mọi người có thể cho biết mô-đun nào một tệp nguồn phụ thuộc vào chỉ bởi các đường dẫn tương đối trong #includes ở trên cùng.

Tùy thuộc vào cách dự án của bạn được đặt ra, điều này có thể có vấn đề khi đưa chúng vào tiêu đề, vì đường dẫn tương đối đến tiêu đề là từ tệp .cpp chứ không phải từ tệp .h, do đó .h tệp không nhất thiết phải biết tệp .cpp của nó ở đâu.

Nếu dự án của bạn có cấu trúc phân cấp phẳng, tuy nhiên, điều này sẽ hoạt động. Giả sử bạn có

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

Bây giờ bất kỳ tập tin tiêu đề có thể bao gồm
#include "..\baz\inc\baz.h
và nó sẽ làm việc kể từ khi tất cả các file cpp là một mức độ sâu hơn so với cơ sở.

2

Nơi tôi làm việc, chúng tôi có cấu trúc thư mục phân phối được tạo tại thời điểm xây dựng. Các tệp tiêu đề xác định các thư viện được sao chép vào một thư mục bao gồm. Chúng tôi sử dụng tập lệnh tạo tùy chỉnh để cho nhà phát triển biểu thị tệp tiêu đề nào sẽ được xuất.

Bản dựng của chúng tôi sau đó được bắt nguồn tại một ổ đĩa subst ed cho phép chúng tôi sử dụng đường dẫn tuyệt đối để bao gồm các thư mục.

Chúng tôi cũng có một tham chiếu dựa trên mạng cho phép chúng tôi sử dụng một ổ đĩa được ánh xạ để bao gồm và tham chiếu lib.

CẬP NHẬT: Bản dựng tham chiếu của chúng tôi là một chia sẻ mạng trên máy chủ xây dựng của chúng tôi. Chúng tôi sử dụng tập lệnh tạo tham chiếu để thiết lập môi trường xây dựng và bản đồ (sử dụng net use) chia sẻ được đặt tên trên máy chủ xây dựng (ví dụ: \ BLD_SRV \ REFERENCE_BUILD_SHARE). Sau đó, trong quá trình xây dựng hàng tuần (hoặc theo cách thủ công), chúng tôi đặt phần chia sẻ (sử dụng net share) để trỏ đến bản dựng mới.

Dự án của chúng tôi sau đó là danh sách đường dẫn tuyệt đối để bao gồm và tham chiếu lib.

Ví dụ:

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 

này sẽ đưa bạn thay đổi địa phương đầu tiên, sau đó nếu bạn chưa thực hiện bất kỳ thay đổi địa phương (hoặc ít nhất bạn đã không được xây dựng chúng) nó sẽ sử dụng các tiêu đề và libs từ bạn xây dựng lần cuối trên máy chủ xây dựng.

+0

Bạn có thể giải thích cấu trúc tham chiếu dựa trên mạng là gì không? – dimba

0

Trong một nhóm tôi đã làm việc, tất cả mọi thứ công cộng đã được giữ trong một thư mục module-cụ thể, trong khi thứ tư nhân (tiêu đề tin, cpp tập tin vv) được lưu giữ trong một thư mục _imp trong vòng này:

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

Bằng cách này bạn chỉ có thể lấy xung quanh trong cấu trúc thư mục dự án của bạn và nhận được tiêu đề bạn muốn.Bạn có thể grep cho #include chỉ thị có chứa _imp và có cái nhìn tốt về chúng. Bạn cũng có thể lấy toàn bộ thư mục, sao chép nó ở đâu đó và xóa tất cả các thư mục con _imp, biết rằng bạn đã sẵn sàng để phát hành một API. Trong tiêu đề dự án nơi thường được bao gồm như

#include "foo/foo.h" 

Tuy nhiên, nếu dự án có sử dụng một số API, sau đó tiêu đề API sẽ được sao chép/cài đặt bằng cách xây dựng của API bất cứ nơi nào họ đã dự định đi trên nền tảng đó bằng cách xây dựng hệ thống và sau đó được cài đặt làm tiêu đề hệ thống:

#include <foo/foo.h> 
Các vấn đề liên quan