cmake external-project

CMake: enlace a la biblioteca descargada desde ExternalProject_add()



external-project (6)

Cuando usa ExternalProject_Add, no puede usar find_package, ya que no hay nada que encontrar cuando CMake se ejecuta para configurar el proyecto externo.

Por lo tanto, si las ubicaciones de las bibliotecas varían según la plataforma, necesitará una lógica condicional basada en su plataforma. (No conozco las bibliotecas o la estructura de protobuf aquí, así que esto es solo un ejemplo, pero debería llevarte en la dirección correcta ...) Algo como esto:

if(WIN32) set(PROTOBUF_LIB_DIR "${MYPROJ_SOURCE_DIR}/dependencies/win" set(prefix "") set(suffix ".lib") elseif(APPLE) set(PROTOBUF_LIB_DIR "${MYPROJ_SOURCE_DIR}/dependencies/mac" set(prefix "lib") set(suffix ".a") else() set(PROTOBUF_LIB_DIR "${MYPROJ_SOURCE_DIR}/dependencies/linux" set(prefix "lib") set(suffix ".a") endif() set(PROTOBUF_LIBRARIES "${PROTOBUF_LIB_DIR}/${prefix}protobufLib1${suffix}" "${PROTOBUF_LIB_DIR}/${prefix}protobufLib2${suffix}")

Por supuesto, esto es menos conveniente que usar find_package. Si puede usar un paquete preinstalado / preinstalado, debería hacerlo, de modo que pueda usar find_package. Sin embargo, si debe compilar el otro paquete a partir del código fuente como parte de su proyecto, ExternalProject_Add es útil, aunque no puede abstraer todos los detalles por usted.

Estoy tratando de usar ExternalProject_add () para descargar / instalar dependencias. Se instala bien, pero no puedo averiguar cómo vincular realmente las bibliotecas después de que se descarguen.

Quiero llamar a target_link_libraries () en la biblioteca que se acaba de descargar, pero la ruta a la biblioteca variará según el sistema.

Si esto fuera una dependencia del sistema, podría llamar a find_package (), pero los paquetes no se instalaron en la ruta de búsqueda predeterminada. No creo que pueda especificar una ruta de búsqueda para find_package en el modo de módulo.

Aquí hay un fragmento de mi CMakeLists.txt que no funciona:

ExternalProject_Add( protobuf URL http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.gz CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> PREFIX ${MYPROJ_SOURCE_DIR}/dependencies ) find_package(protobuf REQUIRED) set(LIBS ${LIBS} ${PROTOBUF_LIBRARIES}) target_link_libraries (mybinary ${LIBS})


Debido a que está descargando el proyecto externo, ya sabe dónde está todo porque lo acaba de descargar, por lo que no es necesario encontrarlo.

Lo tengo trabajando con add_library. Este es mi código real que funciona:

ExternalProject_Add(ForexConnectDownload PREFIX 3rd_party #--Download step-------------- URL http://fxcodebase.com/bin/forexconnect/1.3.1/ForexConnectAPI-1.3.1-Linux-x86_64.tar.gz URL_HASH SHA1=7fdb90a2d45085feb8b76167cae419ad4c211d6b #--Configure step------------- CONFIGURE_COMMAND "" #--Build step----------------- BUILD_COMMAND "" #--Install step--------------- UPDATE_COMMAND "" # Skip annoying updates for every build INSTALL_COMMAND "" ) SET(FXCM_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/3rd_party/src/ForexConnectDownload/include) SET(FXCM_LIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/3rd_party/src/ForexConnectDownload/lib) add_library(ForexConnect SHARED IMPORTED) set_target_properties(ForexConnect PROPERTIES IMPORTED_LOCATION ${FXCM_LIB_DIR}/libForexConnect.so)

A partir de ahí, cada programa que depende de él necesita add_dependencies y, por supuesto, target_link_libraries . P.ej:

include_directories(${FXCM_INCLUDE_DIR}) add_executable(syncDatabase syncDatabase.cpp trader/database.cpp trader/fxcm.cpp) target_link_libraries(syncDatabase ForexConnect) add_dependencies(syncDatabase ForexConnectDownload)

  • include_directories - le dice que busque directorios allí
  • target_link_libraries - solo agrega tu biblioteca, como la nombraste (no es una variable)

Las add_dependencies lo hacen esperar antes de intentar incluir los directorios necesarios.

Eso hace el truco para mí. Funciona con make -j4. Consigue todas las dependencias correctas.


Otro idioma que puedes usar para resolver este problema:

  1. Haga que sus comandos find_package sean opcionales (elimine ''REQUIRED'')
  2. Agrega algún código de condición para construir solo tus objetivos si find_package tiene éxito.
  3. find_package fallará y sus objetivos no se construirán la primera vez, pero se construirán los Proyectos Externos.
  4. Ejecute cmake / make nuevamente, esta vez find_package tendrá éxito y sus objetivos se construirán.

Puede ver este idioma en acción en https://github.com/biometrics/likely .


Para expandir la respuesta anterior de DLRdave, no necesita establecer prefijos y sufijos manualmente para las bibliotecas estáticas porque CMAKE proporciona las variables con los correctos para cada plataforma.

Ver CMake Variables útiles para más información.

Por ejemplo:

  • CMAKE_SHARED_LIBRARY_PREFIX
  • CMAKE_SHARED_LIBRARY_SUFFIX
  • CMAKE_STATIC_LIBRARY_PREFIX
  • CMAKE_STATIC_LIBRARY_SUFFIX

Puede consultar las propiedades de un proyecto externo como source_dir o binary_dir por ExternalProject_Get_Property . binary_dir puede ser una sugerencia para find_package mientras que la ruta a los encabezados puede derivarse de source_dir . En el caso de protobuf, los encabezados están en ${source_dir}/src .

Aquí está mi solución:

ExternalProject_Add( protobuf-external PREFIX protobuf URL https://github.com/google/protobuf/archive/v3.6.0.tar.gz BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/protobuf CMAKE_CACHE_ARGS "-Dprotobuf_BUILD_TESTS:BOOL=OFF" "-Dprotobuf_BUILD_EXAMPLES:BOOL=OFF" "-Dprotobuf_WITH_ZLIB:BOOL=OFF" SOURCE_SUBDIR cmake BUILD_ALWAYS 1 STEP_TARGETS build INSTALL_COMMAND "" ) ExternalProject_Get_Property(protobuf-external source_dir) ExternalProject_Get_Property(protobuf-external binary_dir) find_package(protobuf HINTS ${binary_dir}) include_directories(${source_dir}/src)


Puede usar el comando link_directories para vincular bibliotecas dentro de un directorio específico. En su caso el directorio donde se construye su proyecto externo.

ExternalProject_Add(MyExternalLibrary ...)

Agregue el directorio de salida a la ruta de búsqueda:

link_directories(${CMAKE_BINARY_DIR}/lib/MyExternalLibrary-prefix/lib)

Asegúrese de agregar el ejecutable después de especificar el directorio de enlaces:

add_executable(MyProgram main.c)

Especifique las bibliotecas a las que se debe vincular su proyecto:

target_link_libraries(MyProgram ExternalLibraryName)

No olvides depender del proyecto externo:

add_dependencies(MyProgram MyExternalLibrary)