c++ - r16b - solidity español
CMake: dependencias(encabezados) entre aplicaciones/bibliotecas en el mismo proyecto (2)
Tengo la siguiente estructura de proyecto:
- CMakeLists.txt
- lib1 / CMakeLists.txt y todos los archivos de encabezado y cpp de la biblioteca
- lib2 / CMakeLists.txt y todos los archivos de encabezado y cpp de la biblioteca
- app / CMakeLists.txt y todos los archivos de encabezado y cpp de la aplicación
El principal CMakeLists.txt se parece a:
PROJECT( ${PROJECT_NAME} )
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)
El lib1 / CMakeLists.txt se ve, por ejemplo, como (despojado):
SET(SOURCE
file.cpp
)
SET(HEADERS
some_lib_header.h
)
add_library( lib1 ${SOURCE} ${HEADERS} )
y el de la aplicación es el mismo, excepto ADD_EXECUTABLE:
SET(SOURCE
main.cpp
)
SET(HEADERS
some_header.h
)
add_library( lib1 ${SOURCE} ${HEADERS} )
ADD_EXECUTABLE( app ${SOURCE} ${HEADERS} )
Encontré que la configuración funcionaba bien de esta manera porque, a partir de esto, puedo generar un archivo de solución de Visual Studio que contenga los 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 lo hago
$mkdir build
$cd build
$cmake -C ../myproject
genera un archivo VS.sln fuera de la fuente como lo quiero, pero la aplicación no se compila porque no puede encontrar los archivos de encabezado de lib1 (obviamente).
Ahora leí e intenté muchas cosas, como TARGET_LINK_LIBRARIES( app lib1 )
(que hizo que la aplicación se vinculara con lib1, pero no resolviera el problema de inclusión del encabezado), y cosas como add_subdirectory( ../lib1 )
en varias variantes en el CMakeLists .txt de la aplicación (que arrojó todos los errores que no pude arreglar), y también find_package (que creo que es el enfoque equivocado).
Entonces, ¿cómo puedo resolver este problema (supongo que simple ...)?
Aquí hay una posible solución:
Root 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 muchas maneras diferentes de lograr el mismo resultado final aquí. Para un proyecto relativamente pequeño, probablemente solo usaría 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 obtener más información sobre los comandos relevantes y su justificación, ejecute:
cmake --help-command add_subdirectory
cmake --help-command include_directories
cmake --help-command target_link_libraries
Project
CMakeLists.txt
/-lib1
CMakeLists.txt
/- include / lib1
/- src
/-lib2
CMakeLists.txt
/- include / lib2
/- src
/-app
CMakeLists.txt
/- src
Supongamos dependencias como sigue:
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)
así que en lib2 / src / file.cpp podría hacer #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)
así que en app / src / file.cpp puedes hacer #include <lib1/header.hpp>
y #include <lib2/header.hpp>
La magia es target_include_directories que adjunta el directorio "include" al destino, por lo que al enlazar con él, también se tira del directorio include;)