Cómo cambiar de biblioteca compartida a biblioteca estática con CMake

Contexto:

Construí un a.out en mi sistema local con un moderno Proyecto CMake agregando una dependencia a una biblioteca compartida:

find_package(GDAL QUIET)

if(GDAL_FOUND)
  get_property(_loc TARGET GDAL::GDAL PROPERTY LOCATION)
  message(STATUS "Found GDAL: ${_loc} (version ${GDAL_VERSION})")
  add_library(gdal_external INTERFACE)  # dummy

Todo funciona bien en mi sistema. Ahora quiero distribuir el a.out a sistemas que no tienen la dependencia (el .so).

Problema:

He copiado el binario a.out en un cluster, y cuando lo ejecuto, obtengo el siguiente error: error while loading shared libraries: libgdal.so.26: cannot open shared object file: No such file or directory.

Posible solución y otras consideraciones

  • Instalar las dependencias del cluster, pero no tengo derechos de administración en este servidor
  • incluso si tuviera la dependencia instalada por el personal, el mismo problema surgirá más tarde cuando enviaré el binario a posibles usuarios
  • No puedo pedir a los futuros usuarios que administren dependencias y construyan de fuentes.
  • Me parece que debería incrustar todas las dependencias en el mismo ejecutable, que está usando una biblioteca estática en lugar de compartir
  • Cuestiones de tamaño ejecutable o memoria no son la prioridad

¿Cómo puedo indicar que CMake utilice la versión estática de una biblioteca?

Pregunta hecha hace 3 años, 4 meses, 28 días - Por codecrafty


2 Respuestas:

  • Para cambiar de una biblioteca compartida a una biblioteca estática en CMake, puedes seguir estos pasos:

    • Primero, asegúrate de tener la versión estática de la biblioteca que necesitas. En este caso, la biblioteca GDAL. Puedes compilar la versión estática de la biblioteca desde las fuentes si la biblioteca no proporciona una versión estática por defecto.
    • Una vez que tengas la biblioteca estática, necesitas modificar tu archivo CMakeLists.txt para enlazar con la versión estática en lugar de la compartida. Puedes hacer esto de la siguiente manera:
    cmake
    find_package(GDAL QUIET)
    
    if(GDAL_FOUND)
        get_property(_loc TARGET GDAL::GDAL PROPERTY LOCATION)
        message(STATUS "Found GDAL: ${_loc} (version ${GDAL_VERSION})")
    
        

    Reemplazar el enlace con la biblioteca compartida GDAL con la versión estática

    add_library(gdal_external STATIC IMPORTED) set_property(TARGET gdal_external PROPERTY IMPORTED_LOCATION /ruta/a/libgdal.a) target_link_libraries(tu_binario gdal_external) endif()
    • En el código anterior, reemplaza `/ruta/a/libgdal.a` con la ruta real de la biblioteca estática GDAL en tu sistema. A continuación, debes enlazar tu binario con la biblioteca estática `gdal_external`.
    • Después de realizar estos cambios, vuelve a compilar tu proyecto con CMake. Ahora, cuando ejecutes tu binario en un sistema que no tiene la biblioteca compartida disponible, debería funcionar correctamente al estar enlazado con la biblioteca estática.

    Siguiendo estos pasos, deberías poder cambiar de una biblioteca compartida a una biblioteca estática en CMake para asegurar que tu binario sea autocontenido y no dependa de bibliotecas externas.

    Respondida el Dec 18, 2020 a las 19:30 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Para cambiar de biblioteca compartida a biblioteca estática con CMake, puedes utilizar la siguiente estrategia:

    • Busca la biblioteca estática:
    - Verifica si la biblioteca tiene una versión estática disponible. Esto generalmente se indica con un sufijo "a" o "lib" en el nombre del archivo, por ejemplo, "libgdal.a" o "gdal.lib".
    • Si la biblioteca estática no está disponible, considera compilarla tú mismo desde las fuentes.
    • Ajusta el archivo CMakeLists.txt:
    - Reemplaza la llamada a `find_package(GDAL)` con lo siguiente:
    cmake
         find_library(GDAL_STATIC_LIB NAMES GDAL)
         
    • Esta línea buscará la biblioteca estática "GDAL".
    • Si la biblioteca estática se encuentra en una ruta no estándar, utiliza `set(GDAL_STATIC_LIB_DIR /path/to/lib)` para especificar su ubicación.

    • Vincula con la biblioteca estática:
    - Enlaza tu ejecutable con la biblioteca estática encontrada usando:
    cmake
         targetlinklibraries( ${GDALSTATICLIB})
         

    • Recompila tu proyecto:
    - Vuelve a compilar tu proyecto para generar el ejecutable vinculado estáticamente.

    Ejemplo actualizado de CMakeLists.txt:

    cmake
    find_library(GDAL_STATIC_LIB NAMES GDAL)
    target_link_libraries(gdal_external INTERFACE)  

    dummy

    target_link_libraries( ${GDAL_STATIC_LIB})

    Esto debería generar un ejecutable que esté vinculado con la versión estática de la biblioteca GDAL, eliminando la necesidad de bibliotecas compartidas en tiempo de ejecución.

    Respondida el Dec 18, 2020 a las 19:32 - por Gemini

    Votos positivos: 0 | Votos negativos: 0