GNU/Linux >> Linux Esercitazione >  >> Linux

Supporto vitale a 32 bit:compilazione incrociata con GCC

Se sei uno sviluppatore che crea pacchetti binari, come un RPM, DEB, Flatpak o Snap, devi compilare il codice per una varietà di piattaforme di destinazione diverse. Gli obiettivi tipici includono x86 e ARM a 32 bit e 64 bit. Potresti fare le tue build su diverse macchine fisiche o virtuali, ma ciò significa mantenere diversi sistemi. Invece, puoi utilizzare GNU Compiler Collection (GCC) per eseguire la cross-compilazione, producendo binari per diverse architetture da un'unica macchina di compilazione.

Supponiamo di avere un semplice gioco di lancio di dadi che vuoi compilare in modo incrociato. Qualcosa scritto in C è relativamente facile sulla maggior parte dei sistemi, quindi per aggiungere complessità per motivi di realismo, ho scritto questo esempio in C++, quindi il programma dipende da qualcosa non presente in C (iostream , in particolare).

#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";
   }

Compilalo sul tuo sistema usando g++ comando:

$ g++ dice.cpp -o dice

Quindi eseguilo per confermare che funziona:

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

Puoi vedere che tipo di file binario hai appena prodotto con il file 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 altrettanto importante, a quali librerie si collega 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)

Hai confermato due cose da questi test:il binario che hai appena eseguito è a 64 bit ed è collegato a librerie a 64 bit.

Ciò significa che, per eseguire la compilazione incrociata per 32 bit, devi dire a g++ a:

  1. Produci un binario a 32 bit
  2. Collegamento a librerie a 32 bit anziché alle librerie a 64 bit predefinite

Configurazione del tuo ambiente di sviluppo

Per compilare a 32 bit, sono necessarie librerie e intestazioni a 32 bit installate sul sistema. Se esegui un sistema a 64 bit puro, non hai librerie o intestazioni a 32 bit e devi installare un set di base. Per lo meno, hai bisogno delle librerie C e C++ (glibc e libstdc++ ) insieme alla versione a 32 bit delle librerie GCC (libgcc ). I nomi di questi pacchetti possono variare da distribuzione a distribuzione. Su Slackware, è disponibile una distribuzione a 64 bit pura con compatibilità a 32 bit da multilib pacchetti forniti da Alien BOB. Su Fedora, CentOS e RHEL:

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

Indipendentemente dal sistema che stai utilizzando, devi anche installare tutte le librerie a 32 bit utilizzate dal tuo progetto. Ad esempio, se includi yaml-cpp nel tuo progetto, devi installare la versione a 32 bit di yaml-cpp o, su molti sistemi, il pacchetto di sviluppo per yaml-cpp (ad esempio, yaml-cpp-devel su Fedora) prima di compilarlo.

Una volta risolto, la compilazione è abbastanza semplice:

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

Il -m32 flag dice a GCC di compilare in modalità a 32 bit. Il -march=i686 l'opzione definisce ulteriormente il tipo di ottimizzazione da utilizzare (fare riferimento a info gcc per un elenco di opzioni). La -L flag imposta il percorso delle librerie a cui desideri collegare GCC. Di solito è /usr/lib per 32 bit, anche se, a seconda di come è configurato il tuo sistema, potrebbe essere /usr/lib32 o anche /opt/usr/lib o in qualsiasi luogo in cui sai di conservare le tue librerie a 32 bit.

Dopo la compilazione del codice, guarda la prova della tua build:

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

E, naturalmente, ldd ./dice32 punta alle tue librerie a 32 bit.

Diverse architetture

Il terminale Linux

  • I 7 migliori emulatori di terminale per Linux
  • 10 strumenti da riga di comando per l'analisi dei dati in Linux
  • Scarica ora:cheat sheet SSH
  • Cheat sheet sui comandi avanzati di Linux
  • Esercitazioni sulla riga di comando di Linux

La compilazione a 32 bit su 64 bit per la stessa famiglia di processori consente a GCC di fare molte ipotesi su come compilare il codice. Se devi compilare per un processore completamente diverso, devi installare le utilità GCC cross-build appropriate. L'utilità che installi dipende da cosa stai compilando. Questo processo è un po' più complesso della compilazione per la stessa famiglia di CPU.

Quando esegui la compilazione incrociata per la stessa famiglia, puoi aspettarti di trovare lo stesso set di librerie a 32 bit delle librerie a 64 bit, perché la tua distribuzione Linux le mantiene entrambe. Quando si compila per un'architettura completamente diversa, potrebbe essere necessario cercare le librerie richieste dal codice. Le versioni di cui hai bisogno potrebbero non essere nei repository della tua distribuzione perché la tua distribuzione potrebbe non fornire pacchetti per il tuo sistema di destinazione o potrebbe non rispecchiare tutti i pacchetti in una posizione conveniente. Se il codice che stai compilando è tuo, probabilmente hai una buona idea di quali siano le sue dipendenze e possibilmente dove trovarle. Se il codice è qualcosa che hai scaricato e devi compilare, probabilmente non hai familiarità con i suoi requisiti. In tal caso, esamina ciò che il codice richiede per essere compilato correttamente (di solito sono elencati nei file README o INSTALL e sicuramente nel codice sorgente stesso), quindi vai a raccogliere i componenti.

Ad esempio, se devi compilare il codice C per ARM, devi prima installare gcc-arm-linux-gnu (32 bit) o ​​gcc-aarch64-linux-gnu (64-bit) su Fedora o RHEL, o arm-linux-gnueabi-gcc e binutils-arm-linux-gnueabi su Ubuntu. Questo fornisce i comandi e le librerie necessarie per costruire (almeno) un semplice programma C. Inoltre, hai bisogno di tutte le librerie utilizzate dal tuo codice. Puoi posizionare i file di intestazione nella posizione normale (/usr/include sulla maggior parte dei sistemi), oppure puoi inserirli in una directory a tua scelta e puntare su GCC con il -I opzione.

Durante la compilazione, non utilizzare lo standard gcc o g++ comando. Invece, usa l'utilità GCC che hai installato. Ad esempio:

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

Verifica cosa hai costruito:

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

Biblioteche e prodotti finali

Questo è stato un semplice esempio di come utilizzare la compilazione incrociata. Nella vita reale, il tuo codice sorgente può produrre più di un singolo binario. Sebbene tu possa gestirlo manualmente, probabilmente non ci sono buone ragioni per farlo. Nel prossimo articolo mostrerò GNU Autotools, che fa la maggior parte del lavoro necessario per rendere portabile il tuo codice.


Linux
  1. BleachBit 4.1.1 Rilasciato con supporto per la pulizia

  2. Mozilla Firefox 84.0 rilasciato con supporto nativo per il silicio Apple

  3. KeePassXC 2.6.4 rilasciato con supporto Apple Silicon M1

  4. Driver della stampante HP HPLIP 3.21.4 rilasciato con supporto per HP Envy 6400

  5. Cerchi un editor di file Gui alternativo con supporto per file di grandi dimensioni?

Riporta in vita un vecchio MacBook con Linux

Riporta in vita il vecchio hardware con OpenBSD

Dai nuova vita a un vecchio MacBook con Linux

Miglioramento della durata della batteria del notebook in Ubuntu con TLP

Editor di testo/log con supporto per l'aggiornamento automatico

Compilatori Latex con supporto parallelo