45

Me gustaría tener control sobre el tipo de bibliotecas que se encuentran/vinculadas con mis binarios en CMake. El objetivo final es generar los archivos binarios "lo más estáticos posible" que enlazarán estáticamente con cada biblioteca que tenga una versión estática disponible. Esto es importante ya que permitiría la portabilidad de los binarios en los diferentes sistemas durante las pruebas.CMake: cómo producir binarios "tan estáticos como sea posible"

ATM esto parece ser bastante difícil de lograr ya que los paquetes FindXXX.cmake, o más precisamente el comando find_library siempre recoge las bibliotecas dinámicas siempre que tanto estáticos como dinámicos están disponibles.

Sugerencias sobre cómo implementar esta funcionalidad, preferiblemente de una manera elegante, serían muy bienvenidas.

+0

No es una estafa de: http://stackoverflow.com/questions/2113231/making-cmake-choose-static -linkage-when-possible, que es específico de GCC. –

+0

De hecho, no solo es específico de gcc, también es una solución inconveniente. Ver mi comentario en la otra pregunta. – pszilard

+0

@pszilard ¿Ha encontrado finalmente la solución? Estoy tratando de hacer lo mismo con g ++. – augustin

Respuesta

14

Un archivo FindXXX.cmake bien hecho incluirá algo para esto. Si busca en FindBoost.cmake, puede establecer la variable Boost_USE_STATIC_LIBS para controlar si encuentra bibliotecas estáticas o compartidas o no. Desafortunadamente, la mayoría de los paquetes no implementan esto.

Si un módulo usa el comando find_library (la mayoría lo hace), entonces puede cambiar el comportamiento de CMake a través de la variable CMAKE_FIND_LIBRARY_SUFFIXES. Aquí está el código CMake relevante de FindBoost.cmake utilizar este:

IF(WIN32) 
    SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) 
ELSE(WIN32) 
    SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) 
ENDIF(WIN32) 

Usted puede poner esto antes de llamar find_package, o, mejor, se puede modificar el .cmake propios archivos y contribuir a la comunidad.

Para los archivos .cmake que uso en mi proyecto, los guardo en su propia carpeta dentro del control de fuente. Hice esto porque descubrí que tener el archivo .cmake correcto para algunas bibliotecas era inconsistente y conservar mi propia copia me permitió hacer modificaciones y asegurarme de que todos los que revisaran el código tuvieran los mismos archivos del sistema de compilación.

+0

Gracias por el comentario, en realidad llegué a la conclusión mientras tanto que lo anterior es la única solución factible para obtener la versión estática de libs externos detectados. Sin embargo, esta es una manera bastante sucia, preferiría no tener que especificar sufijos. Desafortunadamente, según las discusiones en la lista de correo de CMake, parece que, dado que Windows tiene un nombre de biblioteca bastante confuso, no hay un plan para implementarlo correctamente. Sin embargo, esto debería funcionar en la mayoría del sistema * NIX. – pszilard

+0

Tenga en cuenta que si desea * solo * que se detecten las bibliotecas estáticas (y quizás la configuración falle, los comandos anteriores no deben anteponer los nombres de archivo de la biblioteca estática a CMAKE_FIND_LIBRARY_SUFFIXES, sino que establecen esa variable para esos nombres de archivo. Esto inhibe find_ *() funciones de buscar bibliotecas compartidas con los sufijos habituales – mabraham

+1

Tenga en cuenta también que no importa qué tan "bien hecho" esté el paquete FindXXXX.cmake si la biblioteca se encuentra en un directorio de enlaces implícito, por ejemplo, la ruta del sistema. CMake deliberadamente revierte a -lXXXX para permitir que el enlazador use su resolución normal en ese caso; consulte http://public.kitware.com/pipermail/cmake/2015-January/059702.html – mabraham

26

Hice un poco de investigación y aunque no pude encontrar una solución satisfactoria al problema, encontré una solución a medias.

El problema de la electricidad estática se acumula se reduce a 3 cosas:

  1. construcción y la vinculación de bibliotecas internas del proyecto.

    Bastante simple, uno solo tiene que voltear el BUILD_SHARED_LIBS, interruptor .

  2. Encontrar versiones estáticas de bibliotecas externas.

    La única forma parece ser configurar CMAKE_FIND_LIBRARY_SUFFIXES para contener el (los) sufijo (s) del archivo deseado (es una lista de prioridades).

    Esta solución es bastante "sucia" y va en contra de las aspiraciones multiplataforma de CMake. En mi humilde opinión, esto debería ser manejado por CMake detrás de las escenas, pero por lo que yo entendí, debido a la confusión ".lib" en Windows, parece que los desarrolladores de CMake prefieren la implementación actual.

  3. Vinculación estática con las bibliotecas del sistema.

CMake proporciona una opción LINK_SEARCH_END_STATIC cuales basa en la documentación: "Finalizar una línea de enlace de tal manera que se utilizan las bibliotecas del sistema estáticas." Uno pensaría, esto es, el problema está resuelto. Sin embargo, parece que la implementación actual no está a la altura de la tarea. Si la opción está activada, CMake genera una llamada de vinculador implícita con una lista de argumentos que termina con las opciones pasaron al enlazador, incluyendo -Wl,-Bstatic. Sin embargo, esto no es suficiente. Solo instruir al enlazador para que se enlace estáticamente resulta en un error, en mi caso: /usr/bin/ld: cannot find -lgcc_s. Lo que falta es decirle a gcc que necesitamos enlaces estáticos a través del -static argumento que es no generó al llamado enlazador por CMake. creo que esto es un error, pero no han logrado obtener una confirmación por parte de los desarrolladores todavía.

por último, creo que todo esto puede y debe ser hecho por CMake detrás de escena, después de todo, no es tan complicado, excepto que es imposible en Windows, si eso cuenta como complicado ...

+1

¿No debería establecer 'BUILD_SHARED_LIBS' en off (por lo que * no * compilaría bibliotecas compartidas)? – Nooble

+0

Hahha, en casi cinco años eres el primero en notar ese error. Gracias. – pszilard

Cuestiones relacionadas