2011-12-21 28 views
9

Tôi có một codebase lớn-ish mà xây dựng vài chục libaries và một số thực thi.việc sử dụng thích hợp của chỉ thị "dự án" CMake là gì

Codebase được chia nhỏ theo cấp bậc và thư viện được xây dựng ở mức độ khá nhiều.

Tôi đã xem xét và đặt một tệp CMakeLists.txt tại mỗi thư mục để xây dựng mỗi thư viện.

Trong mỗi CMakeLists.txt tôi đã sử dụng chỉ thị "dự án (xxx)". Điều này đã xác định cho tôi các biến PROJECT_NAME, PROJECT_SOURCE_DIR và PROJECT_BINARY_DIR mà tôi sử dụng một cách thận trọng.

Tuy nhiên, một trong những nhóm không hài lòng với cách tiếp cận này vì anh không thể tìm thấy bất kỳ ví dụ thế giới thực nào của bất kỳ ai khác đã thực hiện việc này. Ông thường trích dẫn các ví dụ KitWare như không sử dụng cách tiếp cận này và do đó không nên chúng tôi.

Phương pháp thay thế mà anh ấy đang ủng hộ là đặt các biến này trong mỗi tệp makefile có vẻ giống như "dự án" cung cấp cho bạn.

Tôi thực sự không thể nhìn thấy quan điểm của anh ấy và đang tạo ra một chút tiến bộ trong việc thuyết phục anh ấy theo cách khác. Bất cứ ai cũng có thể làm sáng tỏ những nhược điểm của việc sử dụng chỉ thị dự án theo cách này.

Tôi tự ném mình vào trí tuệ tập thể của mình?

+0

Bạn sử dụng biến 'PROJECT_NAME',' PROJECT_SOURCE_DIR' và 'PROJECT_BINARY_DIR' như thế nào? Và những thư viện này độc lập hay chúng chỉ là một phần của thư viện/ứng dụng chính? –

+0

Tôi sử dụng các biến này bên trong các macro tạo mã nguồn. Tôi tạo mục tiêu cấp cao nhất được gọi là $ {PROJECT_NAME} _SPDEF mà các dự án khác có thể phụ thuộc vào để tạo ra các mục tiêu này. Tôi cũng sử dụng các biến _DIR để đặt mã được tạo ở vị trí thích hợp. – ScaryAardvark

Trả lời

12

Thứ nhất, nó cho phép bạn sử dụng <projectName>_BINARY_DIR<projectName>_SOURCE_DIR, nhưng đó không phải là lợi thế chính. Nếu bạn cung cấp cho CMake một tên dự án thì nó sẽ tạo ra các mục tiêu xây dựng cho từng tiểu dự án trong các thư mục riêng của họ. Điều này có nghĩa rằng cho dù bạn đang sử dụng GNU Make, Eclipse CDT, XCode hay bất kỳ trình tạo nào khác được hỗ trợ, bạn có thể xây dựng các dự án phụ riêng lẻ. Ví dụ với GNU Làm cho mỗi tiểu dự án có hệ thống xây dựng đầy đủ của riêng nó từ thư mục riêng của nó.

Bạn có thể truy cập tên dự án hiện tại thông qua PROJECT_NAME và tên dự án gốc bằng CMAKE_PROJECT_NAME.

Chỉnh sửa: Tôi vừa mới nhận ra rằng dưới đây sẽ là hành vi tiêu chuẩn của CMake đối với bất kỳ mục tiêu xây dựng nào của chúng cho dù chúng là dự án hay không. Tôi sẽ giữ nó ở đây để biết thông tin chung nhưng không liên quan đến câu trả lời:

Giả sử tôi có thư viện C++ và tôi có thể tạo ba tệp thực thi nhị phân; Maintests/test1examples/ex1. Tôi có thể chạy thực hiện trong thư mục tôi gọi là CMake từ với ALL target, chạy make ex1, hoặc tôi có thể thay đổi thư mục thành examples/ và xây dựng các ví dụ với make từ thư mục đó. Điều này sẽ xây dựng tất cả các dự án và thư viện phụ thuộc ngay cả khi chúng ở một nơi khác trong cấu trúc thư mục nhưng sẽ không xây dựng Main hoặc tests/test1 hoặc bất kỳ thư viện nào mà chúng phụ thuộc vào examples/ex1 đó. Nếu sau đó tôi chạy từ thư mục chính, nó sẽ không xây dựng lại bất kỳ thư viện nào mà examples/ex1 phụ thuộc vào trừ khi nguồn của chúng đã thay đổi.

+1

Khả năng có thể "cd" đến bất kỳ cấp độ nào của phân cấp xây dựng và làm "tạo tất cả" và có tất cả các đồ tạo tác được xây dựng từ cấp này xuống là một chiến thắng lớn đối với tôi. Cảm ơn. – ScaryAardvark

+0

@ScaryAardvark khả năng chạy các lệnh khác nhau cho các trình biên dịch khác nhau và bao gồm các mã khác nhau với các hệ điều hành khác nhau tự động thực sự tốt đẹp, cộng với nó rất dễ dàng để thực hiện các hoạt động khá tiên tiến với một vài dòng mã. Tôi nén tài sản bằng 'zip' với CMake, hoạt động tốt trên mọi nền tảng/IDE/toolchain. Nó cũng giúp bạn dễ dàng biên dịch chéo cho ARM vv Bạn cũng nên kiểm tra hệ thống thử nghiệm được xây dựng của CMake, [CTest] (http://www.vtk.org/Wiki/CMake_Testing_With_CTest). Ngoài ra còn có các plugin CMake cho các hệ thống CI như Jenkins. –

+0

Vâng, tôi quen thuộc với điều này. Một câu hỏi mà tôi có là cmake xử lý các phiên bản khác nhau của cùng một trình biên dịch ... tức là chúng ta có một phần của cây dự án chỉ có thể được biên dịch dưới sunstudio11 và hầu hết nó cần sunstudio12. Tôi nghĩ rằng tôi sẽ đưa ra một câu hỏi khác liên quan đến điều đó, nhưng cảm ơn :) – ScaryAardvark

0

Nếu thư viện là các dự án thực sự độc lập thì bạn nên sử dụng lệnh project. Tuy nhiên, nếu họ không phải là tôi sẽ thay vào đó chỉ cần thêm chúng như là thư mục con trong gốc của bạn CmakeLists.txt. Bạn có thể sử dụng các biến số CMAKE_CURRENT_SOURCE_DIRCMAKE_CURRENT_BINARY_DIR nếu bạn cần biết các thư mục hiện đang được xử lý.

+0

Có CMAKE_CURRENT_PROJECT không. Nếu có thì tôi có thể thấy điểm của bạn, tuy nhiên nếu tôi phải sử dụng set() để tạo biến này (hoặc cái gì đó tương tự) thì tại sao không sử dụng "project" và có tất cả các biến được tạo cho tôi. – ScaryAardvark

0

Tôi đã tìm thấy ví dụ sử dụng tốt về chính xác hiện tại: thêm tài liệu Doxygen.

Tôi sử dụng CMake (và Ninja) để tạo các dự án C++ cá nhân của mình. Tôi quyết định chọn một số tài liệu Doxygen cho một trong những nỗ lực hoàn chỉnh nhưng không có giấy tờ của tôi. Tôi cũng nghĩ rằng nó sẽ được gọn gàng để thêm nó vào các dự án khác cũng như ngay sau khi tôi làm việc ra làm thế nào để làm cho nó như là chung chung nhất có thể.

Để bắt đầu, tôi đã tạo mẫu Doxygen chuẩn và đổi tên nó.

cd my_projects/projectx 
doxygen -g Doxyfile 
mv Doxyfile Doxyfile.in 

Lưu ý phần mở rộng .in. Có lẽ không cần thiết nhưng thông thường, nếu tôi hiểu chính xác.

Tiếp theo, tôi đã thêm khối mã sau vào tệp CMakeLists.txt của mình, ngay trước khi xác định mục tiêu của mình (không chắc liệu điều đó có quan trọng hay không đôi khi CMake đôi khi kén về chuỗi lệnh nhất định).

FIND_PACKAGE(Doxygen) 
IF("${DOXYGEN_FOUND}" MATCHES "^YES$") 
    CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 
        ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 
        @ONLY) 
    ADD_CUSTOM_TARGET( doc ALL 
         COMMAND ${DOXYGEN_EXECUTABLE} 
         ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 
         WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 
         COMMENT "Doxygenating..." 
         VERBATIM) 
ENDIF() 

Điều này tạo mục tiêu mới được gọi là doc. Chỉ định ALL thêm nó vào mục tiêu "tất cả" mặc định, nhưng đó là tùy chọn. Chỉ định @ONLY đảm bảo rằng mọi biến loại "$ {variable}" sẽ không được mở rộng bởi CONFIGURE_FILE, chỉ các loại "@ variable @". Hơi ít gây nhầm lẫn (với tôi ít nhất), CMAKE_CURRENT_SOURCE_DIR dường như đề cập đến thư mục dự án và CMAKE_CURRENT_BINARY_DIR đến thư mục xây dựng.

Cuối cùng, và đây là nơi PROJECT_NAME et al đến, tôi đã chỉnh sửa Doxyfile.in.

Đây là sự khởi đầu của Doxyfile.in mới của tôi:

DOXYFILE_ENCODING  = UTF-8 
PROJECT_NAME   = "@[email protected]" 
PROJECT_NUMBER   = @[email protected] 
PROJECT_BRIEF   = 
PROJECT_LOGO   = @[email protected]/res/doc_logo-200x55.png 
OUTPUT_DIRECTORY  = @[email protected]/doc 

Bạn nhận được các ý tưởng, tôi nghĩ. Một khi điều này là hoàn toàn genericised (là một từ?) Tôi có thể sao chép nó vào các dự án khác của tôi và miễn là tôi tag lên mã của tôi, tôi sẽ có tài liệu tốt đẹp ở khắp mọi nơi.

Thông báo PROJECT_BRIEF không được chỉ định. Tôi đã không hoàn thành với điều này và vẫn còn một vài khoảng trống cho tôi để suy nghĩ về. Ví dụ: PROJECT_VERSION_TWEAK thực sự chưa chứa bất kỳ thứ gì. Tôi sẽ phải tìm cách để có được số xây dựng của tôi ở đó.

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