2012-06-26 18 views
15

que tienen la siguiente estructura del proyecto:CRealice - dependencias (cabeceras) entre aplicaciones/bibliotecas en un mismo proyecto

  • CMakeLists.txt
    • LIB1/CMakeLists.txt y todos los archivos cpp y cabecera de la lib
    • LIB2/CMakeLists.txt y todos los archivos cpp y cabecera de la lib
    • app/CMakeLists.txt y todos los archivos cpp y cabecera de la aplicación

La principal CMakeLists.txt parece:

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

El lib1/CMakeLists.txt parece, por ejemplo, como (pelado):

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

y el de la aplicación tiene el mismo aspecto, salvo de ADD_EXECUTABLE:

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

me encontré con la configuración de trabajo, así de esta manera porque fuera de esto, puedo generar un archivo de solución de Visual Studio que contiene todos esos tres proyectos. Pero mi problema es que mi aplicación incluye archivos de encabezado de lib1 (y también de lib2, que depende de lib1). Cuando hago

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

se genera fuera de la fuente VS archivo .sln como yo quiero, pero la aplicación no se compila porque no puede encontrar los archivos de cabecera de LIB1 (obviamente).

Ahora leo y probado muchas cosas, como TARGET_LINK_LIBRARIES(app lib1) (que tiene la aplicación para enlazar con la LIB1, pero no resuelve el problema de incluir cabecera), y cosas como add_subdirectory(../lib1) en diversas variantes en el CMakeLists.txt de aplicación (que todos arrojaron errores que no pude solucionar), y también find_package (que supongo que es el enfoque equivocado).

Entonces, ¿cómo puedo resolver este problema (supongo que simple ...)?

Respuesta

17

Aquí hay una solución posible:

Raíz 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) 


Hay un montón de diferentes maneras de lograr el mismo resultado final aquí. Para un proyecto relativamente pequeño, probablemente solo use un solo CMakeLists.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) 


Para más información sobre los comandos pertinentes y su razón de ser, ejecute:

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

El proyecto es bastante grande, así que no me gusta una sola CMakeLists.txt. – Ela782

+0

Su primera solución propuesta tiene un problema: especifica un proyecto (...) al comienzo de cada archivo lib/app CMakeLists.txt. ¿No es ese el mal estilo y debería usar project (...) solo una vez en la raíz CMakeLists.txt? Además, si uso project (...) en cada archivo CMakeLists.txt, CMake genera un archivo .sln para cada proyecto (además del .sln raíz con todos los proyectos) y otras cosas innecesarias, que es bueno de sobrecarga que nunca se usa y probablemente tampoco es la mejor solución? – Ela782

+0

@ Ela782 Sí - sin preocupaciones. Múltiples archivos CMakeLists.txt pueden simplificar las cosas bastante bien para cualquier cosa que no sea el más pequeño de los proyectos. – Fraser

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

dependencias Supongamos la siguiente manera:

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

Algo como esto:

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) 

por lo que en LIB2/src/file.cpp usted podría 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) 

por lo que en aplicación/src/file.cpp que podría hacer #include <lib1/header.hpp> y #include <lib2/header.hpp>

La magia es target_include_directories que unen la "incluyen" directorio para el objetivo, por lo que cuando se vincula con ella se tire el directorio de inclusión también;)

+1

solo está triste cmake no instales los encabezados de un destino, por lo que necesita una fea instalación extra (archivos ...) 'He intentado' PUBLIC_HEADER DESTINATION incluir/lib' sin éxito dentro de 'install (TARGETS ...) ' –

Cuestiones relacionadas