2011-08-13 11 views
6

¿Cómo puedo exportar las bibliotecas de las que depende una biblioteca cmake, de modo que un archivo ejecutable que depende de esa biblioteca no tenga que depender manualmente de las dependencias de esa biblioteca?¿Cómo se exporta una biblioteca del sistema usando cmake?

Eso es un poco de un bocado, así que aquí está un ejemplo:

ficticia (aplicación) ----> depende de la Liba

Liba ----> depende de libpng

Compilación ficticia genera errores:

-- Found LIBPNG 
-- Found LIBA 
-- Configuring done 
-- Generating done 
-- Build files have been written to: /home/doug/projects/dummy/build 
Linking C executable dummy 
../deps/liba/build/liba.a(a.c.o): In function `a_dummy': 
/home/doug/projects/dummy/deps/liba/src/a.c:6: undefined reference to `png_sig_cmp' 
collect2: ld returned 1 exit status 
make[2]: *** [dummy] Error 1 
make[1]: *** [CMakeFiles/dummy.dir/all] Error 2 
make: *** [all] Error 2 

que puede solución que mediante la adición de esto en CMakeLists.txt dummy:

TARGET_LINK_LIBRARIES (PNG ficticio)

Sin embargo, el muerto tiene ningún conocimiento de cómo Liba implementa su API. En algún punto que puede cambiar a ser libjpg, u otra cosa, que romperá la aplicación ficticia.

Después de conseguir la ayuda de la lista de correo cmake He sido dirigidos a este ejemplo de cosas que exportan: http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file

Sin embargo, después de que el enfoque me deja atrapado en esta línea:

exportación (OBJETIVOS $ {LIBPNG_LIBRARY} ARCHIVO "$ {PROJECT_BINARY_DIR} /ALibraryDepends.cmake")

Claramente me falta algo aquí; este comando 'exportar' parece diseñado para exportar subproyectos a un alto nivel; es decir. proyectos anidados dentro de liba.

Sin embargo, ese no es el problema aquí.

Al configurar liba (o cualquier biblioteca de cmake) siempre generaré una lista de dependencias que no son parte de ese proyecto.

¿Cómo puedo exportar esos para que aparezcan como parte de LIBA_LIBRARY cuando uso find_package() para resolver liba?

El uso de bibliotecas estáticas no es una opción (biblioteca estática de algo que enlaza con OpenGL? N.)

+0

La instalación de las bibliotecas del sistema debe ser manejada por [package manager] (https://en.wikipedia.org/wiki/Package_manager) –

Respuesta

6

Dada su comentario a la respuesta de arrowdodger sobre el miedo de instalar algo haría desordenar su sistema, he elegido para dar un comentario conceptual en forma de una respuesta debido a su longitud .

Encadenar el proyecto de cmake funciona mediante find_package, que busca * Config.cmake y * -config.cmake archivos.

del Proyecto A CMakeLists.txt:

#CMakeLists.txt 
project(A) 
install(FILES 
    ${CMAKE_CURRENT_SOURCE_DIR}/AConfig.cmake share/A/cmake 
) 

#AConfig.cmake 
message("Yepp, you've found me.") 

$ mkdir build 
$ cd build 
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install .. 
$ make install 

Proyecto de B CMakeLists.txt:

project(B) 
find_package(A) 

Entonces

$ mkdir build 
$ cd build 
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install .. 
$ make install 

resultados en

... 
-- Detecting CXX compiler ABI info 
-- Detecting CXX compiler ABI info - done 
Yepp, you've found me. 

B encontró A porque instaló AConfig.cmake en una ubicación donde cmake lo encontrará 'compartir/A/cmake' Y se le dio el mismo valor para CMAKE_INSTALL_PREFIX.

Ahora esto es eso. Pensemos en lo que puede hacer en AConfig.cmake: AFAIK todo lo que desee. Pero el tarea más común es extraer información acerca de los objetivos de A a través de include(), qué algunas invoctions find_package adicionales para la tercera parte paquetes (pista pista) y crear las variables

A_LIBRARIES 
A_INCLUDE_DIRS 

Lo que se quiere es incluir un archivo que fue creado por

install(EXPORT A-targets 
    DESTINATION share/A/cmake 
) 

en CMakeLists.txt de a, donde a-objetivos se refieren a una variable global cmake que acumula toda la información de destino cuando se utiliza en

install(TARGETS ... 
    EXPORT A-targets 
    ... 
) 

declaraciones.Lo que se crea al instalar el maquillaje es

/tmp/test-install/share/A/cmake/A-targets.cmake 

que entonces reside junto AConfig.cmake en el mismo directorio. Eche un vistazo a la página wiki sobre cómo usar este archivo dentro de AConfig.cmake.

Con respecto al comando export(): Esto es útil si sus proyectos se han ENORME y se necesita una cantidad considerable de para instalarlos. Para acelerar las cosas, quiere usar lo que es directamente en la compilación/directorio de A. Es una optimización y también explicado en la wiki. Todavía funciona a través de find_package(), consulte

Pero me sugieren fuertemente que usted va para el maquillaje habitual instalar ruta por ahora.

1

Si Liba no proporciona ningún medio para determinar sus dependencias, no se puede hacer nada. Si liba es una biblioteca desarrollada por usted y está usando CMake para compilarla, entonces debe instalar el archivo libaConfig.cmake con liba, que contendría las definiciones necesarias. Luego incluye libaConfig en CMakeLists.txt del dummy para obtener información sobre cómo se ha generado liba.

Puede ver cómo se hace en el proyecto LLVM, los archivos relevantes tienen cmake.en extensión http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/

Al final, en el proyecto ficticio que debe utilizar

target_link_libraries(${LIBA_LIBRARIES})

include_directories(${LIBA_INCLUDE_DIR})

link_directories(${LIBA_LIBRARY_DIR})

Si eso Liba es utilizado sólo por ficticio, se puede construir del único proyecto CMake. Esto es más conveniente, ya que no necesita instalar liba cada vez que lo vuelve a compilar, y se reconstruirá y volverá a vincular con dummy automáticamente cada vez que ejecute make. Si le gustó este enfoque, lo único que debe hacer es definir en liba 'CMakeLists.txt las variables que necesita con la opción PARENT_SCOPE (ver el manual de instrucciones set()).

Finalmente, puede usar librerías compartidas, .so no tiene ese problema.

+0

Soy reacio a utilizar este enfoque específicamente porque estoy compilando los archivos binarios de ARM de Android . Si instalo la biblioteca, ¿no estropeará mi sistema? – Doug

+2

Bueno, no es necesario 'make install' para obtener el archivo generado libAConfig.cmake. – arrowd

+0

También es posible que desee generar un 'libALibraryDepends.cmake' además de' libAConfig.cmake' que contiene las definiciones 'ìmport' del destino de la biblioteca junto con las bibliotecas dependientes. – MKroehnert

2

He encontrado mi propia solución a este problema utilizando la solución aceptada anteriormente, que dejo aquí para que otros:

En Liba/CMakeLists.txt:

# Self 
set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} "${PROJECT_SOURCE_DIR}/include") 
set(A_LIBRARIES ${A_LIBRARIES} "${PROJECT_BINARY_DIR}/liba.a") 

# Libpng 
FIND_PACKAGE(libpng REQUIRED) 
set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} ${LIBPNG_INCLUDE_DIRS}) 
set(A_LIBRARIES ${A_LIBRARIES} ${LIBPNG_LIBRARIES}) 

ADD_LIBRARY(a ${SOURCES}) 

# Includes 
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS}) 

# Allow other projects to use this 
configure_file(AConfig.cmake.in "${PROJECT_BINARY_DIR}/AConfig.cmake") 

En Liba/AConfig.cmake:

set(A_LIBRARIES @[email protected]) 
set(A_INCLUDE_DIRS @[email protected]) 

En CMakeLists.txt maniquí /:

FIND_PACKAGE(A REQUIRED) 
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS}) 
TARGET_LINK_LIBRARIES(dummy ${A_LIBRARIES}) 

El resultado es un AConfig.cmake que lee:

set(A_LIBRARIES /home/doug/projects/dummy/deps/liba/build/liba.a;/usr/lib/libpng.so) 
set(A_INCLUDE_DIRS /home/doug/projects/dummy/deps/liba/include;/usr/include) 

Y una compilación verbosa que lee:

/usr/bin/gcc -std=c99 -g CMakeFiles/dummy.dir/src/main.c.o -o dummy -rdynamic ../deps/liba/build/liba.a -lpng 

que es exactamente lo que estaba buscando.

Cuestiones relacionadas