5

Im tratando de compilar un binario de un proyecto de código abierto para que nuestros usuarios no tengan que compilarlo ellos mismos.Crear un binario genérico en linux para todas las máquinas x86

Me he dado cuenta de que algunos binarios creados en una máquina ubuntu de 32 bits "A" no funcionan en la máquina "B" de 32 bits, y se informa de errores en archivos .so faltantes.

Sin embargo, si compilo desde cero en la máquina "B", todos los errores desaparecen.

¿Podría haber algún motivo por el que compilar el código en la máquina de destino haga que estos errores desaparezcan? Solo ejecuté "./configure" y "make" - no "make-install", así que no es como si hubiera hecho que estos archivos .so estuvieran disponibles globalmente.

¿Podría ser que el compilador detecte que hay .so archivos que faltan de la biblioteca del sistema y en este caso vincula una biblioteca estática en el ejecutable?

¿Cómo compila Ubuntu sus paquetes para que un paquete i386 se ejecute en todas las máquinas x86?

Respuesta

6

Supongo que el problema se llama "compatibilidad binaria" (hay a tag en desbordamiento de pila dedicado a estos problemas). Cuando vincula un binario en una máquina, el entorno circundante afecta al binario y, habiendo sido ejecutado en otra máquina, aún trata de encontrar el entorno similar al que se compiló.

Tolerancia a diferentes entornos en este caso se llama compatibilidad binaria.

¿Cómo funciona?

El punto clave aquí es que, incluso si se especifica las mismas opciones para enlazador en diferentes máquinas, es posible que todavía consigue diferentes binarios. Por ejemplo, si vincula su archivo binario a una biblioteca compartida con -lfoo, la versión exacta de foo que tiene en la máquina en la que está compilando (por ejemplo, libfoo.so.5) está codificada en el binario. Cuando se ejecuta en la máquina B, solo puede contener libfoo.so.4, y el binario se negará a ejecutarse porque necesita el archivo libfoo.so.5 que falta. Es por eso que la recompilación ayuda, y sin ella no funciona.

Los paquetes de Ubuntu -y estos de cualquier otra distribución- son todos compilados en el mismo entorno (entre ellos). Es por eso que se instalan bien. Y los proveedores de distribución ven que cada versión siguiente es compatible con versiones anteriores.

¿Qué debo hacer?

Si desea que su software sea compatible con diferentes distribuciones, es más fácil de lo que pensaba. Primero, intente con compile su aplicación en la distribución más antigua posible. Dado que, como mencioné anteriormente, las distribuciones modernas suelen ser compatibles con versiones anteriores, lo más probable es que su softmat se ejecute en las distribuciones más nuevas sin problema.

Para consultar más a fondo el paquete resultante y obtener más consejos sobre compatibilidad, puede hacerlo desde nuestra herramienta gratuita Linux Application Checker. También te puede estar interesado en generic tips for packaging Linux soft.

+2

Eso es correcto, pero no retroceda demasiado. La compilación de un binario en RHEL 4 probablemente no funcionará en ninguna distribución moderna. Al menos la libc es el determinante principal, a menudo está bloqueado a una versión menor específica. – Keith

+0

PD. Esta es también la razón por la cual algunas aplicaciones comerciales se envían con conjuntos completos de librerías por sí mismas, y usan LD_LIBRARY_PATH para garantizar que se usen en lugar de las del sistema. Otra opción es la vinculación estática. Para herramientas pequeñas que funciona bien. – Keith

2

Puede usar un proyecto como Ermine para crear distribuciones de binarios nativos dinámicamente vinculados con las bibliotecas compartidas incluidas.

Fuera de eso, puede compilar su código estático. Esto requeriría que obtenga el código fuente para todo su árbol de dependencias, que los compile y haga referencia a esos binarios compilados cuando construya su código. No puede compilar binarios estáticos contra otras bibliotecas compartidas (archivos .so). Esto puede ser un verdadero dolor, especialmente si sus dependencias tienen sus propias dependencias.

+0

Ermine se ve bien. Pero no es gratis. ¿Conoces alguna alternativa gratuita? – shivams

3

Si compila código en una máquina, lo más probable es que no obtenga ningún error con respecto a las bibliotecas faltantes si ejecuta el programa en esta máquina. Durante la ejecución de la configuración, se detectan todas las bibliotecas necesarias (esta es la razón principal para configurar, las autotools, etc.) y los indicadores apropiados, como -lsomelib y -I/some/include/patch se escriben en el archivo MAKE y se pasan al compilador y al enlazador .

Copio ese ejecutable en otra máquina que la máquina puede tener las libs en una versión incorrecta o que falta en absoluto, por lo que puede que no se ejecute.

El script de configuración generalmente no compilará binarios estáticos, a menos que explícitamente se lo haya indicado.

Los paquetes de Ubuntu no se ejecutarán en todas las máquinas x86. Pero el administrador de paquetes hace una resolución de dependencia para asegurarse de que no faltan bibliotecas o bibliotecas incorrectas, y se niega a instalar un paquete de lo contrario. Si fuerza la instalación independientemente de las dependencias que falten, es posible que vuelva a ejecutar los mismos problemas con las bibliotecas que faltan.

Si desea asegurarse de que su paquete es capaz de en cualquier máquina, simplemente conéctelo estático.

Si es suficiente para ejecutarlo en una distribución específica (por ejemplo, Ubuntu), puede crear un paquete usted mismo. Esto requiere un poco más de esfuerzo.

0

En lugar del enfoque de error LD_LIBRARY_PATH (que también requiere interacción del usuario) o enlace estático (no siempre posible o prohibido por GPL) puede intentar utilizar una ruta relativa como ruta de búsqueda de biblioteca (ofrecida en Windows por estándar desde DOS veces). Use la bandera $ORIGIN con el enlazador.

El enfoque completo está muy bien descrito en este blog (archived version).

Cuestiones relacionadas