2012-06-26 11 views
15

Mam następujące struktury projektu:CWprowadä - Zależności (nagłówki) między aplikacjami/bibliotek w samym projekcie

  • CMakeLists.txt
    • LIB1/CMakeLists.txt i wszystkie CPP a header pliki lib
    • Lib2/CMakeLists.txt i wszystkie CPP a header pliki lib
    • app/CMakeLists.txt i wszystkie CPP a header pliki aplikacji

Głównym CMakeLists.txt wygląda następująco:

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

LIB1/CMakeLists.txt wygląda jak np (usuwane):

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

i jeden dla aplikacji wygląda tak samo z wyjątkiem z ADD_EXECUTABLE:

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

Znalazłem ustawienia działa dobrze w ten sposób, ponieważ z tego mogę generować jeden plik rozwiązania Visual Studio, który zawiera wszystkie te trzy projekty. Ale moim problemem jest to, że moja aplikacja zawiera pliki nagłówkowe lib1 (a także lib2, która zależy od lib1). Kiedy zrobić

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

generuje out-of-źródła VS pliku .sln jak chcę go, ale aplikacja nie skompilować, ponieważ nie może znaleźć plików nagłówkowych z LIB1 (oczywiście).

Teraz czytam i wypróbowywuję wiele rzeczy, takich jak TARGET_LINK_LIBRARIES(app lib1) (która dostała aplikację do połączenia z lib1, ale nie rozwiązuje problemu z nagłówkiem) i rzeczy takie jak add_subdirectory(../lib1) w różnych wariantach w CMakeLists.txt aplikacji (która wszystkie rzucane błędy, których nie mogłem naprawić), a także find_package (co jest chyba błędnym podejściem).

Jak mogę rozwiązać ten problem (chyba prosty ...)?

Odpowiedz

17

Oto jeden z możliwych rozwiązań:

głównej 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) 


Istnieje wiele różnych sposobów, aby osiągnąć ten sam efekt końcowy tutaj. W przypadku stosunkowo małego projektu prawdopodobnie użyłbym tylko jednego CMakeListy.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) 


W celu uzyskania dalszych informacji na temat odpowiednich poleceń i ich uzasadnienie, uruchom:

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

Projekt jest dość duży, więc nie lubię jednego CMakeLists.txt. – Ela782

+0

Twoje pierwsze proponowane rozwiązanie ma jeden problem: określasz projekt (...) na początku każdego pliku CMakeLists.txt dla biblioteki lib/app. Czy to nie jest zły styl i powinienem użyć projektu (...) tylko raz w głównym katalogu CMakeLists.txt? Ponadto, jeśli używam projektu (...) w każdym pliku CMakeLists.txt, CMake generuje plik .sln dla każdego projektu (oprócz root .sln ze wszystkimi projektami w nim) i inne niepotrzebne rzeczy, które są miłe kosztów ogólnych, które nigdy nie są używane i prawdopodobnie nie są najlepszym rozwiązaniem? – Ela782

+0

@ Ela782 Tak - bez obaw. Wiele plików CMakeLists.txt może uprościć rzeczy całkiem niezależnie od wszystkiego, z wyjątkiem najmniejszych projektów. – Fraser

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

Załóżmy zależności następujące:

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

coś takiego:

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) 

więc w LIB2/src/file.cpp mogłeś do #include <lib1/header.hpp>

app/CMakeLists.txt:

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

    install(TARGETS app DESTINATION bin) 

więc w app/src/file.cpp można zrobić #include <lib1/header.hpp> i #include <lib2/header.hpp>

Magia jest target_include_directories które mocują „należą” do katalogu docelowego, więc podczas łączenia z niej wyciągnąć katalogu include także;)

+1

tylko smutne jest cmake nie instaluj nagłówków celu, więc potrzebujesz brzydkiego dodatkowego 'install (pliki ...)' Próbowałem 'PUBLIC_HEADER DESTINATION include/lib' bez sukcesu wewnątrz' install (TARGETS ...) ' –

Powiązane problemy