2012-06-26 36 views
15

tôi có cấu trúc dự án sau:CMake - phụ thuộc (tiêu đề) giữa các ứng dụng/thư viện trong cùng một dự án

  • CMakeLists.txt
    • lib1/CMakeLists.txt và tất cả cpp và tiêu đề file của lib
    • lib2/CMakeLists.txt và tất cả cpp và tiêu đề file của lib
    • app/CMakeLists.txt và tất cả cpp và tiêu đề file của ứng dụng

Các CMakeLists.txt chính trông giống như:

PROJECT(${PROJECT_NAME}) 
add_subdirectory(lib1) 
add_subdirectory(lib2) 
add_subdirectory(app) 

Các lib1/CMakeLists.txt trông ví dụ như (tước):

SET(SOURCE 
file.cpp 
) 
SET(HEADERS 
    some_lib_header.h 
) 
add_library(lib1 ${SOURCE} ${HEADERS}) 

và một cho các ứng dụng trông giống nhau ngoại trừ của ADD_EXECUTABLE:

SET(SOURCE 
main.cpp 
) 
SET(HEADERS 
    some_header.h 
) 
add_library(lib1 ${SOURCE} ${HEADERS}) 
ADD_EXECUTABLE(app ${SOURCE} ${HEADERS}) 

Tôi thấy thiết lập hoạt động tốt theo cách này vì tôi có thể tạo một tệp giải pháp Visual Studio chứa tất cả ba dự án đó. Nhưng vấn đề của tôi là ứng dụng của tôi bao gồm các tệp tiêu đề của lib1 (và cũng của lib2, phụ thuộc vào lib1). Khi tôi làm

$mkdir build 
$cd build 
$cmake -C ..\myproject 

nó tạo out-of-nguồn VS file sln như tôi muốn nó, nhưng các ứng dụng không biên dịch bởi vì nó không thể tìm thấy các tập tin tiêu đề của lib1 (rõ ràng).

Bây giờ tôi đã đọc và thử nhiều thứ, như TARGET_LINK_LIBRARIES(app lib1) (ứng dụng này có liên kết với lib1, nhưng không giải quyết vấn đề tiêu đề) và những thứ như add_subdirectory(../lib1) trong các biến thể khác nhau trong CMakeLists.txt của ứng dụng (tất cả các lỗi được ném mà tôi không thể sửa), và cũng find_package (mà tôi đoán là cách tiếp cận sai).

Vậy làm thế nào tôi có thể giải quyết vấn đề này (tôi đoán đơn giản ...)?

Trả lời

17

Dưới đây là một giải pháp khả thi:

gốc CMakeLists.txt:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR) 
project(${PROJECT_NAME}) 
add_subdirectory(lib1) 
add_subdirectory(lib2) 
add_subdirectory(app) 


lib1/CMakeLists.txt:

project(Lib1) 
add_library(lib1 lib1.cpp lib1.h) 


lib2/CMakeLists.txt:

project(Lib2) 
add_library(lib2 lib2.cpp lib2.h) 

# Add /lib1 to #include search path 
include_directories(${Lib1_SOURCE_DIR}) 
# Specify lib2's dependency on lib1 
target_link_libraries(lib2 lib1) 


app/CMakeLists.txt:

project(App) 
add_executable(app main.cpp some_header.h) 

# Add /lib1 and /lib2 to #include search path 
include_directories(${Lib1_SOURCE_DIR} ${Lib2_SOURCE_DIR}) 
# Specify app's dependency on lib2. 
# lib2's dependency on lib1 is automatically added. 
target_link_libraries(app lib2) 


Có rất nhiều cách khác nhau để đạt được kết quả cuối cùng ở đây. Đối với một dự án tương đối nhỏ, tôi có thể chỉ sử dụng một CMakeLists đơn lẻ.txt:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR) 
project(Test) 

add_library(lib1 lib1/lib1.cpp lib1/lib1.h) 
add_library(lib2 lib2/lib2.cpp lib2/lib2.h) 
add_executable(app app/main.cpp app/some_header.h) 

include_directories(${CMAKE_SOURCE_DIR}/lib1 ${CMAKE_SOURCE_DIR}/lib2) 

target_link_libraries(lib2 lib1) 
target_link_libraries(app lib2) 


Để biết thêm chi tiết về các lệnh có liên quan và lý do của họ, hãy chạy:

cmake --help-command add_subdirectory 
cmake --help-command include_directories 
cmake --help-command target_link_libraries 
+1

Dự án khá lớn, vì vậy tôi không thích một CMakeLists.txt duy nhất. – Ela782

+0

Giải pháp được đề xuất đầu tiên của bạn có một vấn đề: Bạn chỉ định một dự án (...) ở đầu mỗi tệp lib/app CMakeLists.txt. Đó không phải là phong cách xấu và tôi nên sử dụng dự án (...) chỉ một lần trong gốc CMakeLists.txt? Ngoài ra, nếu tôi sử dụng dự án (...) trong mỗi tệp CMakeLists.txt, CMake tạo tệp .sln cho từng dự án (ngoài phần gốc .sln với tất cả các dự án trong đó) và các công cụ không cần thiết khác, của chi phí không bao giờ được sử dụng và cũng có thể không phải là giải pháp tốt nhất? – Ela782

+0

@ Ela782 Yeah - đừng lo. Nhiều tập tin CMakeLists.txt có thể đơn giản hóa mọi thứ khá tốt cho bất cứ thứ gì trừ các dự án nhỏ nhất. – Fraser

4
Project 
CMakeLists.txt 
\-lib1 
    CMakeLists.txt 
    \- include \ lib1 
    \- src 
\-lib2 
    CMakeLists.txt 
    \- include \ lib2 
    \- src 
\-app 
    CMakeLists.txt 
    \- src 

phụ thuộc Giả sử như sau:

lib1 ---> lib2 ---> app 
    \--------------> app 

Something như thế này:

CMakeLists.txt:

add_subdirectory(lib1) 
add_subdirectory(lib2) 
add_subdirectory(app) 

lib1/CMakeLists.txt:

file(GLOB_RECURSE _HDRS "include/*.hpp") 
    file(GLOB_RECURSE _SRCS "src/*.[hc]pp") 
    add_library(lib1 ${_HDRS} ${_SRCS}) 
    #target_link_libraries(lib1) 
    target_include_directories(lib1 PUBLIC include) 

    install(TARGETS lib1 DESTINATION lib) 
    install(FILES ${_HDRS} DESTINATION include/lib1) 

lib2/CMakeLists.txt:

file(GLOB_RECURSE _HDRS "include/*.hpp") 
    file(GLOB_RECURSE _SRCS "src/*.[hc]pp") 
    add_library(lib2 ${_HDRS} ${_SRCS}) 
    target_link_libraries(lib2 lib1) 
    target_include_directories(lib2 PUBLIC include) 

    install(TARGETS lib2 DESTINATION lib) 
    install(FILES ${_HDRS} DESTINATION include/lib2) 

như vậy trong lib2/src/file.cpp bạn có thể làm #include <lib1/header.hpp>

ứng dụng/CMakeLists.txt:

file(GLOB_RECURSE _SRCS "src/*.[hc]pp") 
    add_executable(app ${_SRCS}) 
    target_link_libraries(app lib1 lib2) 

    install(TARGETS app DESTINATION bin) 

như vậy trong app/src/file.cpp bạn có thể làm #include <lib1/header.hpp>#include <lib2/header.hpp>

Sự kỳ diệu là target_include_directories mà gắn "bao gồm" thư mục vào mục tiêu, vì vậy khi liên kết với nó, bạn kéo bao gồm thư mục cũng;)

+1

chỉ buồn là cmake không cài đặt tiêu đề của một mục tiêu, vì vậy bạn cần cài đặt thêm 'install (files ...)' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ') ' –

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