Tratar con las dependencias de la biblioteca en Linux

Estoy usando libcurl en mi proyecto y depende de openssl y muchos otros .so en tiempo de ejecución.
Esta dependencia es una especie de dolor en el culo, ya que diferentes distributivos/versiones pueden contener diferentes versiones de openssl.

Por ejemplo, tengo problemas para ejecutar Ubuntu 11.10 si compilé mi aplicación en Ubuntu 9.10.

Veo dos opciones para resolver esto, pero ninguna de ellas es lo suficientemente buena para mi caso:

  1. empaquetar mi aplicación y dejar que el administrador de paquetes resuelva este tipo de cosas

  2. vincular todas las dependencias estáticamente

Mi aplicación es muy pequeña y empaquetarla/mantenerla sería una exageración. Además, uno de los requisitos es que debe poder descargarse y ejecutarse. Entonces, (1) no es una opción para mí.

El enlace estático (2) no sería una mala solución, pero parece que no hay distribuciones binarias estáticas de libopenssl, libcrypto y otras dependencias transitivas que vienen con libcurl.

Teóricamente podría intentar construir todo ese zoo de libs detrás de libcurl manualmente, pero parece que esto hará que el mantenimiento sea mucho más complicado.

Entonces, aquí está la pregunta: ¿me estoy perdiendo algo? ¿Hay una forma menos dolorosa de hacer lo que quiero en el mundo de Linux (Ubuntu para ser específicos) con menos dolor? Cualquier sugerencia es bienvenida.

preguntado el 03 de mayo de 12 a las 08:05

Si no está utilizando muchas funciones libcurl, puede escribir las llamadas GET, POST simples y analizar la respuesta HTTP manualmente. Encontrará fácilmente un código de muestra sobre cómo analizar estos datos. -

No puedo imaginar que haya más de tres o cuatro bibliotecas si no está utilizando una GUI. Y las dos bibliotecas que mencionó: libcurl y openssl, son bastante buenas en cuanto a la compatibilidad con versiones anteriores. P: ¿Estás seguro de que realmente hay un problema aquí? -

Si es una aplicación pequeña, podría escribirse en Python, donde estas bibliotecas son estándar y el control de versiones es un problema menor. -

En realidad, no puedo. Bueno, al menos no sería tan barato como parece. La cuestión es que esta aplicación es multiplataforma y debería poder funcionar en Windows/Linux/Mac y necesito libcurl como capa de abstracción. Además, no solo necesito HTTP simple sino también HTTPS y esto hace que las cosas sean un poco más complicadas. -

Python y otras cosas que requieren vm no son una opción. La aplicación es multiplataforma y obligar al usuario de Windows a instalar vm no es algo que pueda permitirme. -

4 Respuestas

Estoy usando libcurl en mi proyecto y depende de openssl y muchos otros .so en tiempo de ejecución. Esta dependencia es una especie de dolor en el culo, ya que diferentes distributivos/versiones pueden contener diferentes versiones de openssl.

Por ejemplo, tengo problemas para ejecutar Ubuntu 11.10 si compilé mi aplicación en Ubuntu 9.10.

Primero, ¿cuál es el problema con esto? No debería tener problemas si está pasando de una versión anterior de Ubuntu a una más nueva. Si no me equivoco, solo necesita especificar qué versión mínima de una biblioteca necesita y el administrador de paquetes debería poder instalar una versión adecuada. Las versiones más nuevas de las bibliotecas deberían no rompa las aplicaciones existentes a menos que esté usando funciones obsoletas.

Mi aplicación es muy pequeña y empaquetarla/mantenerla sería una exageración. Además, uno de los requisitos es que debe poder descargarse y ejecutarse. Entonces, (1) no es una opción para mí.

Para Linux (especialmente Ubuntu, Fedora y otras distribuciones principales), el empaquetado es realmente La manera de distribuir su aplicación. Descargar-instalar-ejecutar es una cosa de Windows y no es la forma en que las personas en Linux instalan el software (bueno, las personas nuevas en Linux podrían...)

También debe intentar la aceptación de la distribución, lo que reducirá su carga con el tiempo. El primer paso hacia esto, al menos en Ubuntu, es crear su propio PPA (https://help.launchpad.net/Packaging/PPA).

El enlace estático (2) no sería una mala solución, pero parece que no hay distribuciones binarias estáticas de libopenssl, libcrypto y otras dependencias transitivas que vienen con libcurl.

Esto usualmente es un muy muy algo malo que hacer La vinculación estática o simplemente agrupar la biblioteca con su aplicación le impone la carga de actualizarla y hay implicaciones si no las actualiza. Por lo tanto, no recomiendo este enfoque. Ver aquí para más detalles: http://www.dwheeler.com/blog/2012/04/03/#insecure-libraries

Esta es la política de Fedora: http://fedoraproject.org/wiki/Packaging:No_Bundled_Libraries

Entonces, aquí está la pregunta: ¿me estoy perdiendo algo? ¿Hay una forma menos dolorosa de hacer lo que quiero en el mundo de Linux (Ubuntu para ser específicos) con menos dolor? Cualquier sugerencia es bienvenida.

Realmente hay dos cosas que hacer aquí:

  1. Empaquetado: Idealmente, será deb para Ubuntu/Debian y rpm para Fedora/Suse. La otra alternativa popular es usar autotools (autoconf/automake) para que el usuario pueda construir su aplicación con los requisitos previos requeridos. La última opción es proporcionar solo un Makefile y un README y esperar que sus usuarios hagan lo correcto.
  2. Distribución: Idealmente, esto es con los repositorios de distribución. Ubuntu PPA es un buen punto de partida. La alternativa es alojar los binarios/paquetes en su propio sitio.

Las aplicaciones más populares proporcionan tanto un .deb/.rpm para las distribuciones populares de Linux como un .tar.gz con herramientas automáticas para crear distribuciones que tienen un sistema de empaquetado diferente.

Al final, permítame preguntarle esto: ¿se enfoca en hacer que sea menos doloroso para usted proporcionar su aplicación o en hacer que sea menos doloroso para sus usuarios obtener su aplicación?

Respondido 12 Oct 17, 12:10

Gracias por la gran confianza. Acerca de libcurl y las versiones de Ubuntu: esto se debió a que intenté vincularme estáticamente solo con libcurl (no con dependencias transitivas). Como resultado: algunas de estas dependencias no estaban presentes en las versiones que quería libcurl enlazado estáticamente. - Eugenio Loy

Acerca de las compilaciones estáticas: sí, investigué un poco y ahora veo que esto es algo que se adapta a Windows, pero no de la forma en que debería seguir en Linux. Ahora estoy estudiando cómo empaquetar paquetes deb en mi cadena de herramientas, por lo que es muy probable que esta sea mi solución final. - Eugenio Loy

Y sobre la última pregunta: en realidad, estoy buscando un compromiso. Existe una gran posibilidad de que esta herramienta se actualice una vez por siglo, por lo que admitir esto por parte de otros desarrolladores (tal vez no yo) debería ser lo más fácil posible. Por otro lado, esta herramienta debe ser lo más fácil y ligera posible, por lo que la experiencia del usuario también es importante (probablemente me sentiría más cómodo con los paquetes, pero no he visto muchos usuarios de Linux que no sean desarrolladores en la naturaleza, y es por eso que tenía dudas sobre el embalaje). - Eugenio Loy

Hay una tercera opción:

Cree un archivo de algún tipo que se ajuste a sus necesidades e incluya los archivos .so/.dll que necesite, según la plataforma. Un archivo ZIP debería funcionar tanto para Linux como para Windows.

Luego use LD_LIBRARY_PATH en una secuencia de comandos contenedora para su instalación de Linux (que le permite colocar sus archivos .so en algún lugar especial, generalmente en un libs directorio). Windows, hasta donde yo sé, usa CWD como el primer lugar para buscar archivos .dll que necesita un binario, por lo que todo lo que necesita hacer es colocarlos en el mismo directorio que el binario y listo.

Con este método, puede mantener su "distribución" pequeña y no hay necesidad de vinculación estática o cualquier otro manejo especial.

Solo asegúrese de analizar la cadena de dependencia real de sus archivos .so/.dll para no sorprenderse cuando se carga alguna biblioteca no deseada en el entorno de destino.

contestado el 03 de mayo de 12 a las 11:05

un archivo por lotes contenedor para Windows también funcionará, necesitaría algo como esto: pastebin.com/eqfgNUwa - smerlin

Mmm. Sí, esto parece ser una opción. Sin embargo, parece un poco frágil y aún requiere un poco de esfuerzo. Todavía tengo dudas, pero supongo que intentaré hacer una compilación estática y si las cosas se ponen feas, recurriré a esta. Gracias. - Eugenio Loy

¿Consideraste usar qt? Simplemente no tendría esos problemas allí, y tienen un soporte poderoso y fácil de ssl y http

contestado el 03 de mayo de 12 a las 08:05

Sí, lo he pensado, pero hará que la aplicación sea mucho más pesada de lo que puedo pagar. Qt agrega ~ 50 MB solo para QtCore y no sé cuántos para QtNetwork. Sin mencionar que no podré vincular todo estáticamente en un exe gordo debido a su política de licencias. - Eugenio Loy

Eso no es cierto. Puede vincular en un exe. Además, no necesitaría implementar los dlls, el administrador de paquetes podría manejar eso por usted. Además, los dlls pueden ser más pequeños si es necesario. Puedo brindarle ayuda para compilar qt estáticamente o compilar librerías qt pequeñas y utilizables si es necesario: Muma

Además, parece que no hay compatibilidad inmediata con HTTPS. Al menos de un vistazo. - Eugenio Loy

Esto debería funcionar en combinación con SSL abierto hasta donde yo sé. - Muma

Bueno, físicamente puedo vincularme con Qt estáticamente pero... Me costará algo de dinero si quiero quejarme de su licencia (y lo hago), además no hay un administrador de paquetes para Windows, además el administrador de paquetes no es una opción como He mencionado en la publicación de preguntas. - Eugenio Loy

Así que preguntas "¿Hay una manera menos dolorosa?" Me gustan las otras respuestas, particularmente la respuesta de Naveen. entonces tienes dos soluciones

  1. Use los archivos .so (bibliotecas compartidas) en el sistema operativo y recomiende a sus usuarios que usen "al menos la versión x". Eso prácticamente se encargará de todo.

  2. Agrupe bibliotecas no compartidas (estáticas), los archivos .a, con su aplicación o agrupe bibliotecas compartidas, los archivos .so, con su aplicación.

Los archivos .a estáticos son bastante simples de construir desde la fuente utilizando los scripts ./configure. Los archivos .so los puede obtener fácilmente, pero necesitará un buen truco para agruparlos con su aplicación. Los archivos .so se pueden parchear; tienen rutas internas que indican desde dónde deben cargarse las dependencias. Por lo tanto, agrupar archivos .so no es imposible e incluso podría ser una forma práctica de evitar los pasos manuales de creación de archivos .a para una serie de dependencias, si encuentra y usa los scripts para reubicar los archivos .so.

Usted escribe:

En teoría, podría intentar construir todo ese zoológico de bibliotecas detrás de libcurl manualmente, pero parece que esto hará que el mantenimiento sea mucho más complicado.

Sí, lo hará, porque querrá parches de seguridad a medida que salgan, ¿verdad? Entonces, el mejor método es el n. ° 1: permitir que el usuario instale las últimas versiones que pueda tener en sus manos y asumir la responsabilidad de hacer que su sistema sea seguro.

La solución n.º 2 es útil cuando se encuentra en una situación en la que está realizando un trabajo personalizado para un cliente que no puede usar la solución n.º 1. Aquí proporciona versiones periódicas de su software según un cronograma, incluidas las dependencias más recientes con todas sus correcciones. El software pequeño generalmente llega a un punto en el que simplemente deja de necesitar cambios. Esta solución no es una buena solución para una pequeña pieza de software porque su software no cambia, pero aún realiza versiones periódicas simplemente porque las dependencias tienen actualizaciones. Por lo tanto, no use esta solución a menos que su cliente realmente la requiera. Es más caro a largo plazo.

¡Espero que esto ayude!

respondido 26 nov., 13:13

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.