cmake - guia - qgis español
CMake: cómo crear proyectos externos e incluir sus objetivos (3)
Tengo un Proyecto A que exporta una biblioteca estática como un objetivo:
install(TARGETS alib DESTINATION lib EXPORT project_a-targets)
install(EXPORT project_a-targets DESTINATION lib/alib)
Ahora quiero utilizar el Proyecto A como un proyecto externo del Proyecto B e incluir sus objetivos integrados:
ExternalProject_Add(project_a
URL ...project_a.tar.gz
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/project_a
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
)
include(${CMAKE_CURRENT_BINARY_DIR}/lib/project_a/project_a-targets.cmake)
El problema es que el archivo de inclusión aún no existe cuando se ejecuta CMakeLists del Proyecto B.
¿Hay alguna manera de hacer que la inclusión dependa del proyecto externo que se está creando?
Creo que estás mezclando dos paradigmas diferentes aquí.
Como notó, el módulo ExternalProject
altamente flexible ejecuta sus comandos en tiempo de compilación, por lo que no puede usar directamente el archivo de importación del Proyecto A, ya que solo se crea una vez que se ha instalado el Proyecto A.
Si desea include
el archivo de importación del Proyecto A, deberá instalar el Proyecto A manualmente antes de invocar el CMakeLists.txt del Proyecto B, al igual que cualquier otra dependencia de terceros agregada de esta manera o mediante find_file
/ find_library
/ find_package
.
Si desea utilizar ExternalProject_Add
, deberá agregar algo como lo siguiente a su CMakeLists.txt:
ExternalProject_Add(project_a
URL ...project_a.tar.gz
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/project_a
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
)
include(${CMAKE_CURRENT_BINARY_DIR}/lib/project_a/project_a-targets.cmake)
ExternalProject_Get_Property(project_a install_dir)
include_directories(${install_dir}/include)
add_dependencies(project_b_exe project_a)
target_link_libraries(project_b_exe ${install_dir}/lib/alib.lib)
También puede forzar la creación del objetivo dependiente en un proceso secundario de fabricación
Ver mi respuesta sobre un tema relacionado.
Esta publicación tiene una respuesta razonable:
CMakeLists.txt.in
:
cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
CMakeLists.txt
:
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in
googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
execute_process(COMMAND ${CMAKE_COMMAND} --build .
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
# Prevent GoogleTest from overriding our compiler/linker options
# when building with Visual Studio
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This adds
# the following targets: gtest, gtest_main, gmock
# and gmock_main
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
${CMAKE_BINARY_DIR}/googletest-build)
# The gtest/gmock targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later. Otherwise we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11)
include_directories("${gtest_SOURCE_DIR}/include"
"${gmock_SOURCE_DIR}/include")
endif()
# Now simply link your own targets against gtest, gmock,
# etc. as appropriate
Sin embargo, parece bastante hacky. Me gustaría proponer una solución alternativa: usar submódulos de Git.
cd MyProject/dependencies/gtest
git submodule add https://github.com/google/googletest.git
cd googletest
git checkout release-1.8.0
cd ../../..
git add *
git commit -m "Add googletest"
Luego, en MyProject/dependencies/gtest/CMakeList.txt
puede hacer algo como:
cmake_minimum_required(VERSION 3.3)
if(TARGET gtest) # To avoid diamond dependencies; may not be necessary depending on you project.
return()
endif()
add_subdirectory("googletest")
No he intentado esto extensivamente todavía pero parece más limpio.
Editar: Hay una desventaja en este enfoque: el subdirectorio podría ejecutar comandos de install()
que no desee. Esta publicación tiene un enfoque para deshabilitarlos, pero no funcionaba y no funcionaba para mí.
Editar 2: si usa add_subdirectory("googletest" EXCLUDE_FROM_ALL)
, parece que significa que los comandos de install()
en el subdirectorio no se utilizan de forma predeterminada.