link library example linker shared-libraries cmake static-linking dynamic-library

linker - library - CMake: cómo producir binarios "lo más estático posible"



cmake add library example (2)

Hice una investigación y, aunque no encontré una solución satisfactoria al problema, sí encontré una solución a medias.

El problema de las construcciones estáticas se reduce a 3 cosas:

  1. Construyendo y enlazando las bibliotecas internas del proyecto.

    Bastante simple, solo hay que BUILD_SHARED_LIBS interruptor BUILD_SHARED_LIBS .

  2. Encontrar versiones estáticas de bibliotecas externas.

    La única forma parece ser configurar CMAKE_FIND_LIBRARY_SUFFIXES para que contenga los sufijos de archivo deseados (es una lista de prioridades).

    Esta solución es bastante "sucia" y está muy en contra de las aspiraciones multiplataforma de CMake. En mi humilde opinión, esto debería ser manejado entre bambalinas por CMake, pero por lo que 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 contra bibliotecas del sistema.

CMake proporciona una opción LINK_SEARCH_END_STATIC que se basa en la documentación: "Termine una línea de enlace para que se utilicen bibliotecas estáticas del sistema". Uno podría pensar, 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 pasadas al vinculador, incluyendo -Wl,-Bstatic . Sin embargo, esto no es suficiente. Solo instruir al vinculador para vincular estáticamente produce un error, en mi caso: /usr/bin/ld: cannot find -lgcc_s . Lo que falta es decirle a gcc también que necesitamos enlaces estáticos a través del argumento -static que no se genera a la llamada del enlazador por CMake. Creo que esto es un error, pero aún no he logrado obtener una confirmación de los desarrolladores.

Finalmente, creo que todo esto podría y debería 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 ...

Me gustaría tener control sobre el tipo de bibliotecas que se encuentran / vinculan con mis binarios en CMake. El objetivo final es generar binarios "lo más estáticos posible", es decir, vincular estáticamente a cada biblioteca que tenga una versión estática disponible. Esto es importante ya que permitiría la portabilidad de binarios a través de diferentes sistemas durante las pruebas.

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

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


Un archivo FindXXX.cmake bien hecho incluirá algo para esto. Si busca en FindBoost.cmake, puede configurar la variable Boost_USE_STATIC_LIBS para controlar si encuentra o no bibliotecas estáticas o compartidas. 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 para usar esto:

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)

Puede poner esto antes de llamar a find_package o, mejor, puede modificar los archivos .cmake y contribuir a la comunidad.

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