2014-05-15 21 views
8

Tôi đang làm việc trên một dự án bao gồm 3 tệp thực thi máy chủ và một thư viện cho mã được chia sẻ. Tôi muốn nó được nền tảng, vì vậy tôi đang sử dụng CMake (kể từ khi Xcode là một nỗi đau anyway) để xử lý quá trình xây dựng. Tôi gặp sự cố khi thiết lập các CMakeLists để tôi có thể đưa thư viện từ một thư mục ở cùng cấp khi tôi đang xây dựng tệp thi hành.CMake: Xây dựng nhiều thực thi trong một dự án với thư viện tĩnh

Dưới đây là cấu trúc thư mục (và các tập tin CMake):

tethealla2.0/ 
    CMakeLists.txt 
    libtethealla/ 
     CMakeLists.txt 
     encryption/ 
     utils/ 
    patch_server/ 
     CMakeLists.txt 
    login_server/ 
     CMakeLists.txt 
    ship_server/ 
     CMakeLists.txt 

cấp cao nhất của tôi CMake (tethealla2.0/CMakeLists.txt, chỉ bao gồm các tiểu dự án đó phải biên dịch):

project(tethealla CXX) 
cmake_minimum_required(VERSION 2.6) 

add_subdirectory(libtethealla) 
add_subdirectory(patch_server) 

tethealla2.0/libtethealla/CMakeLists.txt, mà tạo ra một thư viện tĩnh:

project(Libtethealla C) 
cmake_minimum_required(VERSION 2.6) 

include_directories(encryption) 

set(ENC_DR encryption/) 

set(ENCRYPTION_SOURCES 
    ${ENC_DR}/psobb-crypt.c 
    ${ENC_DR}/psogc-crypt.c 
    ${ENC_DR}/psobb-crypt.c 
    ${ENC_DR}/encryption.c 
) 

add_library(tethealla STATIC ${ENCRYPTION_SOURCES}) 

tet healla2.0/patch_server/CMakeLists.txt vậy, đến nay:

project(patch_server CXX) 
cmake_minimum_required(VERSION 2.6) 

add_executable(server main.cc) 
target_link_libraries(server tethealla) 

Vì vậy, nó có ý nghĩa hơn nếu tôi xây dựng nó từ cấp cao nhất kể từ tethealla2.0/CMakeLists.txt sẽ kế thừa các mục tiêu từ mỗi thư mục con và một trong patch_server sẽ có quyền truy cập vào thư viện tethealla. Tuy nhiên những gì tôi muốn là để có thể xây dựng từ bên trong các thư mục con này để tạo ra các dự án Xcode để tôi có thể làm việc trên/biên dịch chúng riêng lẻ. Để làm như vậy, tôi cần có khả năng truy cập thư mục libtethealla/build (trong đó CMake output) để truy cập thư viện libtethealla.a từ patch_server. Điều này có thể không? Trên một loại ghi chú khác, ngay cả khi xây dựng từ thư mục cấp cao nhất, nguồn của tôi trong patch_server không thể bao gồm "encryption.h", tệp tiêu đề cho thư viện trong mã hóa. Mà dường như được xây dựng tốt. Bất kỳ suy nghĩ về điều đó cũng được đánh giá cao!

Trả lời

14

Giải pháp của tôi là sử dụng add_subdirectory với bản vá tương đối vào thư mục shared_lib. Tôi không nghĩ rằng đây là một giải pháp hoàn hảo, nó có những cảnh báo của nó:

  • Logic rất giống với bộ bảo vệ tiêu đề phải được thêm vào thư viện CMakeLists.txt để ngăn không cho xác định mục tiêu nhiều lần.
  • Mỗi tệp CMakeList.txt phải biết bản vá tương đối vào thư viện, nếu muốn di chuyển thư viện, tất cả các CMakeLists phải được cập nhật.

Giả sử rằng cấu trúc thư mục trông như thế này:

root/ 
    CMakeLists.txt 
    shared_lib/ 
     CMakeLists.txt 
     inc/ 
      foo.h 
     src/ 
      foo.c 
    exec1/ 
     CMakeLists.txt 
     main.c 
    exec2/ 
     CMakeLists.txt 
     main.c 

root/CMakeList.txt

cmake_minimum_required(VERSION 2.6) 

add_subdirectory(shared_lib) 

add_subdirectory(exec1) 
add_subdirectory(exec2) 

tôi đã quyết định rằng shared_lib/CMakeLists.txt sẽ xuất khẩu một biến có tên SHARED_DIR_INCLUDE_DIR . Cách tiếp cận này giúp phân tách mọi thứ một chút.

root/exec1/CMakeLists.txt

cmake_minimum_required(VERSION 2.6) 

add_subdirectory(./../shared_lib shared_lib) 

include_directories(${SHARED_LIB_INCLUDE_DIR}) 

set(SRCS main.c) 
add_executable(exec1 ${SRCS}) 
target_link_libraries(exec1 shared_lib) 

if() ở dòng thứ tư giải quyết các vấn đề với định nghĩa nhiều mục tiêu trong trường hợp tập tin CMakeLists được bổ sung nhiều lần.Các dòng thứ hai và thứ ba xuất khẩu các thư mục bao gồm cho thư viện trong SHARED_LIB_INCLUDE_DIR

root/shared_lib/CMakeLists.txt

cmake_minimum_required(VERSION 2.6) 

set(SHARED_LIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/inc) 

set(SHARED_LIB_INCLUDE_DIR ${SHARED_LIB_INCLUDE_DIR} PARENT_SCOPE) 

if(TARGET shared_lib) 

message("shared_lib is already defined") 

else() 

include_directories(${SHARED_LIB_INCLUDE_DIR}) 

set(LIB_SRCS ./src/foo.c) 

add_library(shared_lib STATIC ${LIB_SRCS}) 

endif() 
Các vấn đề liên quan