GNU/Linux >> Tutoriels Linux >  >> Linux

Assistance à la vie 32 bits :compilation croisée avec GCC

Si vous êtes un développeur créant des packages binaires, comme un RPM, DEB, Flatpak ou Snap, vous devez compiler du code pour une variété de plates-formes cibles différentes. Les cibles typiques incluent x86 et ARM 32 bits et 64 bits. Vous pouvez faire vos builds sur différentes machines physiques ou virtuelles, mais cela implique de maintenir plusieurs systèmes. Au lieu de cela, vous pouvez utiliser la collection de compilateurs GNU (GCC) pour effectuer une compilation croisée, produisant des binaires pour plusieurs architectures différentes à partir d'une seule machine de construction.

Supposons que vous ayez un simple jeu de lancer de dés que vous souhaitez compiler de manière croisée. Quelque chose d'écrit en C est relativement facile sur la plupart des systèmes, donc pour ajouter de la complexité dans un souci de réalisme, j'ai écrit cet exemple en C++, donc le programme dépend de quelque chose qui n'est pas présent en C (iostream , en particulier).

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

Compilez-le sur votre système en utilisant g++ commande :

$ g++ dice.cpp -o dice

Ensuite, exécutez-le pour confirmer qu'il fonctionne :

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

Vous pouvez voir quel type de binaire vous venez de produire avec le fichier commande :

$ 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

Et tout aussi important, à quelles bibliothèques il est lié avec 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)

Vous avez confirmé deux choses à partir de ces tests :le binaire que vous venez d'exécuter est 64 bits et il est lié à des bibliothèques 64 bits.

Cela signifie que, pour effectuer une compilation croisée pour 32 bits, vous devez indiquer à g++ à :

  1. Produire un binaire 32 bits
  2. Lien vers les bibliothèques 32 bits au lieu des bibliothèques 64 bits par défaut

Configuration de votre environnement de développement

Pour compiler en 32 bits, vous avez besoin de bibliothèques et d'en-têtes 32 bits installés sur votre système. Si vous exécutez un système 64 bits pur, vous n'avez pas de bibliothèques ou d'en-têtes 32 bits et vous devez installer un ensemble de base. À tout le moins, vous avez besoin des bibliothèques C et C++ (glibc et libstdc++ ) ainsi que la version 32 bits des bibliothèques GCC (libgcc ). Les noms de ces packages peuvent varier d'une distribution à l'autre. Sur Slackware, une distribution 64 bits pure avec une compatibilité 32 bits est disponible sur multilib packages fournis par Alien BOB. Sur Fedora, CentOS et RHEL :

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

Quel que soit le système que vous utilisez, vous devez également installer toutes les bibliothèques 32 bits utilisées par votre projet. Par exemple, si vous incluez yaml-cpp dans votre projet, alors vous devez installer la version 32 bits de yaml-cpp ou, sur de nombreux systèmes, le package de développement pour yaml-cpp (par exemple, yaml-cpp-devel sur Fedora) avant de le compiler.

Une fois cela fait, la compilation est assez simple :

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

Le -m32 indique à GCC de compiler en mode 32 bits. Le -mars=i686 l'option définit en outre le type d'optimisations à utiliser (reportez-vous à info gcc pour une liste d'options). Le -L flag définit le chemin vers les bibliothèques auxquelles vous voulez que GCC se lie. Il s'agit généralement de /usr/lib pour 32 bits, bien que, selon la configuration de votre système, cela puisse être /usr/lib32 ou même /opt/usr/lib ou n'importe quel endroit où vous savez que vous conservez vos bibliothèques 32 bits.

Une fois le code compilé, consultez la preuve de votre build :

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

Et, bien sûr, ldd ./dice32 pointe vers vos bibliothèques 32 bits.

Différentes architectures

Le Terminal Linux

  • Les 7 meilleurs émulateurs de terminaux pour Linux
  • 10 outils de ligne de commande pour l'analyse de données sous Linux
  • Télécharger maintenant :Aide-mémoire SSH
  • Aide-mémoire des commandes Linux avancées
  • Tutoriels de ligne de commande Linux

Compiler 32 bits sur 64 bits pour la même famille de processeurs permet à GCC de faire de nombreuses hypothèses sur la façon de compiler le code. Si vous devez compiler pour un processeur entièrement différent, vous devez installer les utilitaires GCC inter-build appropriés. L'utilitaire que vous installez dépend de ce que vous compilez. Ce processus est un peu plus complexe que la compilation pour la même famille de CPU.

Lorsque vous effectuez une compilation croisée pour la même famille, vous pouvez vous attendre à trouver le même ensemble de bibliothèques 32 bits que de bibliothèques 64 bits, car votre distribution Linux gère les deux. Lors de la compilation pour une architecture entièrement différente, vous devrez peut-être rechercher les bibliothèques requises par votre code. Les versions dont vous avez besoin ne se trouvent peut-être pas dans les référentiels de votre distribution car votre distribution peut ne pas fournir de packages pour votre système cible, ou elle peut ne pas refléter tous les packages dans un emplacement pratique. Si le code que vous compilez est le vôtre, alors vous avez probablement une bonne idée de ce que sont ses dépendances et éventuellement où les trouver. Si le code est quelque chose que vous avez téléchargé et que vous devez compiler, vous n'êtes probablement pas aussi familier avec ses exigences. Dans ce cas, recherchez ce dont le code a besoin pour être construit correctement (ils sont généralement répertoriés dans les fichiers README ou INSTALL, et certainement dans le code source lui-même), puis rassemblez les composants.

Par exemple, si vous devez compiler du code C pour ARM, vous devez d'abord installer gcc-arm-linux-gnu (32 bits) ou gcc-aarch64-linux-gnu (64 bits) sur Fedora ou RHEL, ou arm-linux-gnueabi-gcc et binutils-arm-linux-gnueabi sur Ubuntu. Cela fournit les commandes et les bibliothèques dont vous avez besoin pour construire (au moins) un programme C simple. De plus, vous avez besoin de toutes les bibliothèques utilisées par votre code. Vous pouvez placer les fichiers d'en-tête à l'emplacement habituel (/usr/include sur la plupart des systèmes), ou vous pouvez les placer dans un répertoire de votre choix et y faire pointer GCC avec le -I option.

Lors de la compilation, n'utilisez pas le standard gcc ou g++ commande. Utilisez plutôt l'utilitaire GCC que vous avez installé. Par exemple :

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

Vérifiez ce que vous avez créé :

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

Bibliothèques et livrables

C'était un exemple simple d'utilisation de la compilation croisée. Dans la vraie vie, votre code source peut produire plus qu'un simple binaire. Bien que vous puissiez gérer cela manuellement, il n'y a probablement aucune bonne raison de le faire. Dans mon prochain article, je ferai une démonstration de GNU Autotools, qui effectue la majeure partie du travail nécessaire pour rendre votre code portable.


Linux
  1. Fin de vie de Plesk Onyx

  2. KeePassXC 2.6.4 est sorti avec le support Apple Silicon M1

  3. Lancement du pilote d'imprimante HP HPLIP 3.21.4 avec prise en charge de HP Envy 6400

  4. Vous recherchez un éditeur de fichiers Gui alternatif avec prise en charge de fichiers volumineux ?

  5. Kooha - Enregistreur d'écran avec prise en charge de Wayland

Redonnez vie à un vieux MacBook avec Linux

Redonnez vie à votre ancien matériel avec OpenBSD

Donnez une nouvelle vie à un vieux MacBook avec Linux

Mozilla Firefox 84.0 est sorti avec le support natif Apple Silicon

Améliorer la durée de vie de la batterie d'un ordinateur portable dans Ubuntu avec TLP

Éditeur de texte/journal avec prise en charge de l'actualisation automatique