GNU/Linux >> Tutoriales Linux >  >> Linux

Soporte de vida de 32 bits:compilación cruzada con GCC

Si es un desarrollador que crea paquetes binarios, como RPM, DEB, Flatpak o Snap, debe compilar código para una variedad de plataformas de destino diferentes. Los objetivos típicos incluyen x86 y ARM de 32 y 64 bits. Puede hacer sus compilaciones en diferentes máquinas físicas o virtuales, pero eso significa mantener varios sistemas. En su lugar, puede usar GNU Compiler Collection (GCC) para compilar de forma cruzada, produciendo archivos binarios para varias arquitecturas diferentes desde una sola máquina de compilación.

Suponga que tiene un juego simple de tirar dados que desea compilar de forma cruzada. Algo escrito en C es relativamente fácil en la mayoría de los sistemas, así que para agregar complejidad en aras del realismo, escribí este ejemplo en C++, por lo que el programa depende de algo que no está presente en C (iostream , específicamente).

#include <iostream>
#include <cstdlib>

using namespace std;

void lose (int c);
void win (int c);
void draw ();

int main() {
  int i;
    do {
      cout << "Pick a number between 1 and 20: \n";
      cin >> i;
      int c = rand ( ) % 21;
      if (i > 20) lose (c);
      else if (i < c ) lose (c);
      else if (i > c ) win (c);
      else draw ();
      }
      while (1==1);
      }

void lose (int c )
  {
    cout << "You lose! Computer rolled " << c << "\n";
  }

void win (int c )
  {
    cout << "You win!! Computer rolled " << c << "\n";
   }

void draw ( )
   {
     cout << "What are the chances. You tied. Try again, I dare you! \n";
   }

Compílelo en su sistema usando g++ comando:

$ g++ dice.cpp -o dice

Luego ejecútelo para confirmar que funciona:

$ ./dice
Pick a number between 1 and 20:
[...]

Puede ver qué tipo de binario acaba de producir con el archivo comando:

$ file ./dice
dice: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically
linked (uses shared libs), for GNU/Linux 5.1.15, not stripped

E igual de importante, a qué bibliotecas se vincula con ldd :

$ ldd dice
linux-vdso.so.1 => (0x00007ffe0d1dc000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(0x00007fce8410e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6
(0x00007fce83d4f000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6
(0x00007fce83a52000)
/lib64/ld-linux-x86-64.so.2 (0x00007fce84449000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1
(0x00007fce8383c000)

Ha confirmado dos cosas de estas pruebas:el binario que acaba de ejecutar es de 64 bits y está vinculado a bibliotecas de 64 bits.

Eso significa que, para realizar una compilación cruzada para 32 bits, debe indicarle a g++ a:

  1. Producir un binario de 32 bits
  2. Enlace a bibliotecas de 32 bits en lugar de las bibliotecas predeterminadas de 64 bits

Configurando su entorno de desarrollo

Para compilar a 32 bits, necesita bibliotecas y encabezados de 32 bits instalados en su sistema. Si ejecuta un sistema puro de 64 bits, entonces no tiene bibliotecas ni encabezados de 32 bits y necesita instalar un conjunto base. Como mínimo, necesita las bibliotecas C y C++ (glibc y libstdc++ ) junto con la versión de 32 bits de las bibliotecas GCC (libgcc ). Los nombres de estos paquetes pueden variar de una distribución a otra. En Slackware, una distribución pura de 64 bits con compatibilidad de 32 bits está disponible en multilib paquetes proporcionados por Alien BOB. En Fedora, CentOS y RHEL:

$ yum install libstdc++-*.i686
$ yum install glibc-*.i686
$ yum install libgcc.i686

Independientemente del sistema que esté utilizando, también debe instalar las bibliotecas de 32 bits que utilice su proyecto. Por ejemplo, si incluye yaml-cpp en su proyecto, debe instalar la versión de 32 bits de yaml-cpp o, en muchos sistemas, el paquete de desarrollo para yaml-cpp (por ejemplo, yaml-cpp-devel en Fedora) antes de compilarlo.

Una vez resuelto esto, la compilación es bastante simple:

$ g++ -m32 dice.cpp -o dice32 -L /usr/lib -march=i686

El -m32 flag le dice a GCC que compile en modo de 32 bits. El -marzo=i686 La opción define aún más qué tipo de optimizaciones usar (consulte info gcc para obtener una lista de opciones). El -L marca establece la ruta a las bibliotecas a las que desea que GCC se vincule. Suele ser /usr/lib para 32 bits, aunque, dependiendo de cómo esté configurado su sistema, podría ser /usr/lib32 o incluso /opt/usr/lib o cualquier lugar donde sepa que guarda sus bibliotecas de 32 bits.

Después de compilar el código, vea la prueba de su compilación:

$ file ./dice32
dice: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
dynamically linked (uses shared libs) [...]

Y, por supuesto, ldd ./dice32 apunta a sus bibliotecas de 32 bits.

Distintas arquitecturas

La terminal de Linux

  • Los 7 mejores emuladores de terminal para Linux
  • 10 herramientas de línea de comandos para el análisis de datos en Linux
  • Descargar ahora:hoja de referencia de SSH
  • Hoja de trucos de comandos avanzados de Linux
  • Tutoriales de línea de comandos de Linux

La compilación de 32 bits en 64 bits para la misma familia de procesadores permite a GCC hacer muchas suposiciones sobre cómo compilar el código. Si necesita compilar para un procesador completamente diferente, debe instalar las utilidades GCC de compilación cruzada adecuadas. La utilidad que instale depende de lo que esté compilando. Este proceso es un poco más complejo que compilar para la misma familia de CPU.

Cuando realiza una compilación cruzada para la misma familia, puede esperar encontrar el mismo conjunto de bibliotecas de 32 bits que de bibliotecas de 64 bits, porque su distribución de Linux mantiene ambas. Al compilar para una arquitectura completamente diferente, es posible que deba buscar las bibliotecas requeridas por su código. Es posible que las versiones que necesita no estén en los repositorios de su distribución porque es posible que su distribución no proporcione paquetes para su sistema de destino, o puede que no refleje todos los paquetes en una ubicación conveniente. Si el código que está compilando es suyo, probablemente tenga una buena idea de cuáles son sus dependencias y posiblemente dónde encontrarlas. Si el código es algo que ha descargado y necesita compilar, entonces probablemente no esté tan familiarizado con sus requisitos. En ese caso, investigue qué requiere el código para compilar correctamente (generalmente se enumeran en los archivos README o INSTALL, y ciertamente en el código fuente mismo), luego reúna los componentes.

Por ejemplo, si necesita compilar código C para ARM, primero debe instalar gcc-arm-linux-gnu (32 bits) o gcc-aarch64-linux-gnu (64 bits) en Fedora o RHEL, o arm-linux-gnueabi-gcc y binutils-arm-linux-gnueabi en Ubuntu. Esto proporciona los comandos y las bibliotecas que necesita para construir (al menos) un programa C simple. Además, necesita las bibliotecas que use su código. Puede colocar archivos de encabezado en la ubicación habitual (/usr/include en la mayoría de los sistemas), o puede colocarlos en un directorio de su elección y apuntar a GCC con -I opción.

Al compilar, no use el estándar gcc o g++ dominio. En su lugar, use la utilidad GCC que instaló. Por ejemplo:

$ arm-linux-gnu-g++ dice.cpp \
  -I/home/seth/src/crossbuild/arm/cpp \
  -o armdice.bin

Verifica lo que has construido:

$ file armdice.bin
armdice.bin: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV) [...]

Bibliotecas y entregables

Este fue un ejemplo simple de cómo usar la compilación cruzada. En la vida real, su código fuente puede producir más que un solo binario. Si bien puede administrar esto manualmente, probablemente no haya una buena razón para hacerlo. En mi próximo artículo, demostraré GNU Autotools, que hace la mayor parte del trabajo necesario para que su código sea portátil.


Linux
  1. BleachBit 4.1.1 lanzado con soporte de limpieza Slack

  2. Mozilla Firefox 84.0 lanzado con soporte nativo de Apple Silicon

  3. ¿Está buscando un editor de archivos Gui alternativo con soporte para archivos grandes?

  4. Cómo evitar los ataques de Stack Smashing con GCC

  5. Lanzamiento de Kali Linux 1.0.8 con soporte de arranque EFI

Devuélvele la vida a un viejo MacBook con Linux

Devuelva el hardware antiguo a la vida con OpenBSD

Dale nueva vida a un viejo MacBook con Linux

Mejorar la duración de la batería del portátil en Ubuntu con TLP

Editor de texto / registro con soporte de actualización automática

Compiladores Latex con soporte paralelo