2011-12-13 48 views
9

Tôi đã đấu tranh với điều này trong một thời gian dài, và cuộc phiêu lưu của tôi với cmake chỉ dẫn đến các giải pháp hackish mà tôi khá chắc chắn là không chính xác.Cách đúng để cấu trúc dự án C++ của tôi với cmake?

Tôi tạo ra một thư viện mà bao gồm một số tác phẩm, như sau:

-libfolder 
    -codepart1folder 
    -CMakeLists.txt 
    -codepart1.cpp 
    -codepart1.hpp 
    -codepart2folder 
    -codepart3folder 
    -lib.cpp 
    -lib.hpp 
    -CMakeLists.txt 

Tôi đã viết một tập tin CMakeLists để biên dịch các thư viện (sau khi một số thử nghiệm), và tôi có thể tạo ra một tập tin lib.a. Bây giờ tôi muốn bao gồm mã này như một thư viện trong các dự án khác, và truy cập nó thông qua giao diện trong lib.hpp. Cách tốt nhất để làm điều này, về cấu trúc thư mục, và những gì tôi cần phải đưa vào CMakeLists.txt trong dự án gốc của tôi là gì?

nỗ lực hiện tại của tôi đã được thêm -libfolder như một thư mục con cho dự án hiện tại của tôi, và thêm các lệnh:

include_directories(${PROJECT_SOURCE_DIR}/libfolder) 
link_directories(${PROJECT_BINARY_DIR}/libfolder) 
add_subdirectory(libfolder) 
target_link_libraries(project lib) 

Khi tôi chạy make, thư viện biên dịch tốt, nhưng khi project.cpp biên dịch, nó phàn nàn rằng nó không thể tìm thấy codepart1.hpp (được bao gồm trong lib.hpp, bao gồm từ project.cpp).

Tôi nghi ngờ rằng đây là một cách sai lầm về việc này, nhưng tôi không thể lội qua tài liệu CMake và tìm thấy một hướng dẫn tốt về việc thiết lập các dự án như thế này. Xin hãy giúp, CMake rất kinh nghiệm!

+0

Có lẽ không hữu ích lắm đối với cmake cho mỗi lần xem, nhưng tôi khuyên bạn nên xem xét trước. Đó là gần đến sự trưởng thành và có nhiều lợi thế để cmake (một là nó là một heck của rất nhiều nhanh hơn để có được lên đến tốc độ với nó, đặc biệt là nếu bạn đã biết lua). Bạn có thể kiểm tra nó tại http://industriousone.com/what-premake. – Ylisar

+1

vì vậy, bạn có muốn cho phép dự án mới của mình sử dụng thư viện được xây dựng trước đó hay bạn muốn xây dựng cả hai từ một dự án meta sắp xếp? – moooeeeep

Trả lời

2

Ok, do đó sau khi tham khảo ý kiến ​​một đồng nghiệp của tôi là người một guru CMake, có vẻ như CMake không có hỗ trợ cho những gì tôi đang cố gắng để làm, để lại một với 3 lựa chọn:

  1. Thêm tất cả phụ thuộc vào các dự án mẹ CMakeLists.txt - không phải là rất sạch sẽ, nhưng nó sẽ có được điều để làm việc. Bạn sẽ phải làm điều này cho mọi dự án bạn thêm mã vào, và quay lại và sửa chữa mọi thứ nếu thư viện của bạn thay đổi.

  2. xóa tiêu đề thư viện của bạn. Điều này được thực hiện thông qua một số trình biên dịch hackery. Ý tưởng là để chuyển tiếp khai báo mọi lớp, và chỉ sử dụng con trỏ hoặc tăng :: shared_ptr, và sau đó chỉ bao gồm các phụ thuộc trong tệp cpp. Bằng cách đó bạn có thể xây dựng tệp cpp bằng cách sử dụng tất cả các công cụ tìm kiếm, và bạn nhận được tiền thưởng khi có thể sử dụng lib bằng cách chỉ bao gồm tiêu đề và liên kết đến thư viện.

  3. Xem xét các hệ thống xây dựng. Có mã di động và biên dịch mã nhanh với các phụ thuộc phức tạp không phải là một vấn đề được giải quyết! Từ các cuộc điều tra của tôi, nó trở nên khá phức tạp. Tôi đã kết thúc việc áp dụng hệ thống xây dựng đồng nghiệp của mình mà anh ấy đã tạo ra bằng cmake, sử dụng những thứ anh ấy đã chọn từ Google.

+0

+1, vì làm sạch giao diện của bạn sao cho nó không cần3 rdparty include-dirs thậm chí còn tốt hơn. –

5

Cách sạch để nhập khẩu một dự án CMake vào dự án khác là thông qua lệnh find_package. Việc khai báo gói được thực hiện bằng cách sử dụng lệnh export. Một lợi thế của việc sử dụng find_package là nó loại bỏ sự cần thiết phải các đường dẫn mã cứng vào các tệp của gói.

Về tệp hpp bị thiếu, bạn không bao gồm codepart1folder, vì vậy nó không nằm trên đường dẫn bao gồm.

+0

Ok ...từ câu trả lời này nó không thực sự rõ ràng với tôi cho dù find_package và xuất khẩu là những điều phải sử dụng trong trường hợp này, hoặc làm thế nào tôi sẽ làm như vậy. Bạn có thể xây dựng được không? – dlants

+0

sử dụng include_directories ($ {PROJECT_SOURCE_DIR}/libfolder/codepart1folder) – LeDYoM

1

Nhìn vào bài đăng của bạn, bạn dường như không thêm 'codepart1folder' vào bao gồm ở bất kỳ đâu. How are you bao gồm codepart1.hpp như:

#include <codepart1.hpp> 
#include "codepart1folder/codepart1.hpp" 

Tôi không nghĩ rằng có một cách tiêu chuẩn được chấp nhận để cấu trúc dự án cmake. Tôi đã xem xét một loạt các repo cmake và họ có xu hướng có sự khác biệt. Cá nhân tôi làm như sau:

-project 
    CMakeLists.txt 
    -build 
    -cmake 
     OptionalCmakeModule.cmake 
    -src 
     -Main 
      Main.cpp 
      Main.hpp 
     -DataStructs 
      SomeTree.hpp 
      SomeObject.hpp 
     -Debug 
      Debug.hpp 
     -UI 
      Window.hpp 
      Window.cpp 

Về cơ bản rằng bãi tất cả các mã nguồn vào 1 thư mục, sau đó bạn thực hiện một ra khỏi nguồn xây dựng với: 'mkdir xây dựng & & cd xây dựng & & cmake .. & & làm 'trong thư mục gốc của dự án.

Nếu bạn có lib riêng biệt như một phần của dự án, thì bạn có thể muốn một thư mục libs riêng biệt với một thư mục con khác cho lib cụ thể của bạn.

Tôi có một số bản repos của mình trên: https://github.com/dcbishop/ nếu bạn muốn xem các tệp CMakeLists.txt.

Những vấn đề chính với cơ cấu dự án của tôi là rằng tôi sử dụng FILE_GLOB mà rõ ràng là cách 'sai' để làm việc (nếu bạn thêm các tập tin sau khi chạy 'cmake ..' sau đó họ sẽ không được nhặt bạn làm một 'make').Tôi đã không tìm ra những gì 'đúng' cách để làm điều đó là (từ những gì tôi có thể nhìn thấy nó liên quan đến việc giữ một danh sách các tập tin riêng biệt) Tôi cũng chỉ sử dụng 1 tập tin CMakeLists.txt.

Một số dự án cũng chọn tách tệp cpp và hpp của họ thành các thư mục riêng biệt. Vì vậy, bạn sẽ có một thư mục include và src (ít nhất là đối với các tệp hpp được dự định được sử dụng bên ngoài). Tôi nghĩ rằng chủ yếu là cho các dự án chủ yếu là các thư viện lớn. Cũng sẽ làm cho cài đặt các tập tin tiêu đề dễ dàng hơn nhiều.

+0

codepart1folder được bao gồm trong tệp CMakeLists.txt bên trong thư mục libfolder. Có vẻ như sai khi tôi phải thêm tất cả các thư mục con, bao gồm và các liên kết trong CmakeLists.txt trong thư mục dự án, vì project.cpp không phụ thuộc vào bất kỳ thư mục nào - chỉ lib.hpp thực hiện. Trong cây của bạn, hãy tưởng tượng rằng có một project2 định nghĩa một thư viện và tôi muốn sử dụng project2 như một phần phụ của dự án. – dlants

+0

@JohnSavage. Nhưng nó là đúng cách ... Tôi sẽ tạo ra một biến LIB_INCLUDE_DIRS trong dự án lib, được "xuất khẩu" cho CMakeCache chứa tất cả các phụ thuộc cần thiết bao gồm-dirs. Giả sử biến đó sẽ xuất hiện khi dự án cmake-ing. –

+0

+1 cho các liên kết github – hAcKnRoCk

0

Bạn đang có thể bị thiếu

include_directories(${PROJECT_SOURCE_DIR}/libfolder/codepart1folder) 

Trong trường hợp này bạn có thể muốn set(CMAKE_INCLUDE_CURRENT_DIR on) để thêm tất cả thư mục vào thư mục bao gồm biến đường.

Kiểm tra đầu ra của cmake trên dòng lệnh cho dù các thư mục bao gồm chính xác có được đặt hay không. Ngoài ra, bạn luôn có thể sử dụng message() làm "gỡ lỗi in" cho biến cmake. Trong trường hợp có các thư mục bao gồm, bạn cần phải đọc thuộc tính thư mục để xem những gì thực sự nằm trong các thư mục bao gồm.

get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES) 
message("inc_dirs = ${inc_dirs}") 

Tôi hy vọng điều này sẽ giúp bạn tìm ra những gì còn thiếu.

Sửa

Tôi chỉ thấy nhận xét của bạn về codepart1folder thêm vào trong libfolder. Nó chỉ có sẵn trong đường dẫn include_directory của libfolder và không được lan truyền đến thư mục gốc. Vì bao gồm codepart1.hpp có trong lib.hpp tuy nhiên bạn cần có nó cũng có sẵn trong đường dẫn dự án nếu không bạn sẽ bị thiếu các lỗi khai báo khi bạn xây dựng dự án của mình.

+0

Ok, vì vậy đây là vấn đề của tôi. Tôi cảm thấy như tôi không cần phải đi và bao gồm lại tất cả các thư mục con của tôi trong dự án phụ huynh. lib là một đoạn mã độc lập với CMakeLists.txt của chính nó và biên dịch thành lib.a. Tôi không muốn phải dây tất cả vào tất cả các dự án tôi muốn sử dụng nó. – dlants

+1

Sau đó, bạn nên giao diện phù hợp với lib của bạn. – Bort

Các vấn đề liên quan