La commande ar
sous Linux est un outil puissant pour le développement logiciel, notamment pour la création de bibliothèques de fonctions. Cet article vous guidera à travers le processus de création, de modification et d’utilisation d’une bibliothèque statique, en fournissant un exemple de code concret.
La commande ar
est une fonctionnalité de longue date, datant de 1971. Son nom, ar
, fait référence à son utilisation initiale pour la création de fichiers d’archive. Un fichier d’archive est un fichier unique qui sert de conteneur pour d’autres fichiers, parfois un grand nombre d’entre eux. Ces fichiers peuvent être ajoutés, supprimés ou extraits de l’archive. Bien que ar
ne soit plus l’outil de choix pour cette fonctionnalité, remplacée par des utilitaires tels que tar
, il conserve son utilité pour des tâches spécifiques.
La commande ar
est encore largement utilisée pour la création de bibliothèques statiques, essentielles dans le développement logiciel. Elle sert également à créer des fichiers de package, tels que les fichiers « .deb » utilisés dans la distribution Debian Linux et ses dérivés comme Ubuntu.
Nous allons explorer les étapes nécessaires pour créer et modifier une bibliothèque statique, et montrer comment l’utiliser dans un programme. Pour cela, nous allons créer une bibliothèque statique dont le rôle est d’encoder et de décoder des chaînes de texte.
Il est important de noter qu’il s’agit d’une démonstration simplifiée. N’utilisez pas ce cryptage pour des informations sensibles. C’est une forme très basique de chiffre de substitution, où chaque lettre est simplement remplacée par la suivante (A devient B, B devient C, etc.).
Les fonctions cipher_encode()
et cipher_decode()
Nous allons travailler dans un répertoire nommé « bibliothèque », et plus tard, nous créerons un sous-répertoire appelé « test ».
Dans ce répertoire, nous avons deux fichiers. Le fichier cipher_encode.c
contient la fonction cipher_encode()
:
void cipher_encode(char *text) { for (int i=0; text[i] != 0x0; i++) { text[i]++; } } // fin de cipher_encode
La fonction correspondante cipher_decode()
se trouve dans un fichier nommé cipher_decode.c
:
void cipher_decode(char *text) { for (int i=0; text[i] != 0x0; i++) { text[i]--; } } // fin de cipher_decode
Les fichiers contenant des instructions de programmation sont appelés fichiers de code source. Nous allons créer un fichier de bibliothèque nommé libcipher.a
, qui contiendra les versions compilées de ces deux fichiers. Nous allons également créer un fichier d’en-tête, libcipher.h
, qui contiendra les définitions des fonctions de notre bibliothèque.
Avec la bibliothèque et le fichier d’en-tête, n’importe qui peut utiliser les fonctions dans ses propres programmes, sans avoir à les réécrire. Ils utiliseront simplement les copies de notre bibliothèque.
Compilation des fichiers cipher_encode.c
et cipher_decode.c
Pour compiler ces fichiers, nous allons utiliser gcc
, le compilateur GNU standard. L’option -c
(compiler, pas de lien) indique à gcc
de compiler les fichiers et de s’arrêter. Il produira un fichier intermédiaire pour chaque fichier source, appelé fichier objet. L’éditeur de liens de gcc
prend généralement ces fichiers objets et les lie pour créer un programme exécutable. Nous allons sauter cette étape, nous avons juste besoin des fichiers objets.
Commençons par vérifier que nous avons bien les fichiers que nous pensons avoir :
ls -l
Les deux fichiers de code source sont présents. Utilisons gcc
pour les compiler en fichiers objets :
gcc -c cipher_encode.c
gcc -c cipher_decode.c
Si tout se passe bien, gcc
ne devrait pas afficher de message.
Cela génère deux fichiers objets, avec la même nom que les fichiers de code source, mais avec l’extension « .o ». Ce sont ces fichiers que nous allons ajouter à notre bibliothèque.
ls -l
Création de la bibliothèque libcipher.a
Pour créer le fichier de bibliothèque – qui est en réalité un fichier d’archive – nous allons utiliser ar
.
Nous utiliserons l’option -c
(créer) pour créer le fichier, l’option -r
(ajouter avec remplacer) pour ajouter les fichiers à la bibliothèque, et l’option -s
(index) pour créer un index des fichiers contenus dans la bibliothèque.
Nous allons nommer le fichier de bibliothèque libcipher.a
. Ce nom doit être spécifié sur la ligne de commande, ainsi que les noms des fichiers objets à ajouter à la bibliothèque.
ar -crs libcipher.a cipher_encode.o cipher_decode.o
En listant les fichiers dans le répertoire, nous voyons que le fichier libcipher.a
est maintenant présent :
ls -l
Avec l’option -t
(table), nous pouvons visualiser les modules qui se trouvent à l’intérieur du fichier de bibliothèque :
ar -t libcipher.a
Création du fichier d’en-tête libcipher.h
Le fichier libcipher.h
sera inclus dans tout programme utilisant la bibliothèque libcipher.a
. Ce fichier doit contenir les définitions des fonctions qui se trouvent dans la bibliothèque.
Pour créer ce fichier, nous devons saisir les définitions de fonction dans un éditeur de texte tel que gedit
. Nommez le fichier libcipher.h
et enregistrez-le dans le même répertoire que le fichier libcipher.a
.
void cipher_encode(char *text); void cipher_decode(char *text);
Utilisation de la bibliothèque libcipher
La meilleure façon de tester notre nouvelle bibliothèque est d’écrire un petit programme qui l’utilise. Tout d’abord, créons un répertoire nommé test
.
mkdir test
Nous allons copier la bibliothèque et le fichier d’en-tête dans ce nouveau répertoire.
cp libcipher.* ./test
Puis nous nous déplaçons dans ce répertoire.
cd test
Vérifions que les deux fichiers sont bien présents :
ls -l
Nous devons créer un petit programme qui peut utiliser la bibliothèque et confirmer qu’elle fonctionne comme prévu. Saisissez les lignes suivantes dans un éditeur de texte. Enregistrez ce contenu dans un fichier nommé « test.c » dans le répertoire test.
#include#include #include "libcipher.h" int main(int argc, char *argv[]) { char text[]="toptips.fr loves Linux"; puts(text); cipher_encode(text); puts(text); cipher_decode(text); puts(text); exit (0); } // fin de main
Le déroulement du programme est très simple :
- Il inclut le fichier
libcipher.h
pour accéder aux définitions des fonctions de la bibliothèque. - Il crée une chaîne nommée « texte » et y stocke les mots « toptips.fr loves Linux ».
- Il affiche cette chaîne à l’écran.
- Il appelle la fonction
cipher_encode()
pour encoder la chaîne, et affiche la chaîne encodée. - Il appelle
cipher_decode()
pour décoder la chaîne et affiche la chaîne décodée.
Pour générer le programme de test, nous devons compiler le fichier test.c
et le lier à la bibliothèque. L’option -o
(sortie) indique à gcc
comment nommer le programme exécutable.
gcc test.c libcipher.a -o test
Si gcc
revient silencieusement à l’invite de commande, tout va bien. Testons maintenant le programme. Voici le moment de vérité :
./test
Nous voyons la sortie attendue. Le programme de test affiche le texte brut, le texte crypté, puis le texte décrypté. Il utilise les fonctions de notre nouvelle bibliothèque. Notre bibliothèque fonctionne.
Succès. Mais pourquoi s’arrêter là ?
Ajout d’un autre module à la bibliothèque
Ajoutons une autre fonction à la bibliothèque. Nous allons ajouter une fonction que le programmeur pourra utiliser pour afficher la version de la bibliothèque qu’il utilise. Nous devrons créer cette nouvelle fonction, la compiler et ajouter le fichier objet à la bibliothèque existante.
Saisissez les lignes suivantes dans un éditeur de texte. Enregistrez le contenu dans un fichier nommé cipher_version.c
dans le répertoire de la bibliothèque :
#includevoid cipher_version(void) { puts("toptips.fr :: VERY INSECURE Cipher Library"); puts("Version 0.0.1 Alphan"); } // fin de cipher_version
Nous devons aussi ajouter la définition de cette nouvelle fonction au fichier d’en-tête libcipher.h
. Ajoutez une ligne à la fin de ce fichier, de façon à ce qu’il ressemble à ceci :
void cipher_encode(char *text); void cipher_decode(char *text); void cipher_version(void);
Enregistrez le fichier libcipher.h
.
Il faut maintenant compiler le fichier cipher_version.c
pour obtenir le fichier objet cipher_version.o
:
gcc -c cipher_version.c
Ceci crée un fichier cipher_version.o
. Nous pouvons l’ajouter à la bibliothèque libcipher.a
avec la commande suivante. L’option -v
(verbeux) permet à la commande ar
, habituellement silencieuse, de nous indiquer ce qu’elle a fait.
ar -rsv libcipher.a cipher_version.o
Le nouveau fichier objet est ajouté à la bibliothèque. ar
affiche une confirmation. Le « a » signifie « ajouté ».
On peut utiliser l’option -t
(table) pour visualiser les modules qui se trouvent maintenant dans la bibliothèque :
ar -t libcipher.a
Il y a maintenant trois modules dans notre fichier de bibliothèque. Utilisons cette nouvelle fonction.
Utilisation de la fonction cipher_version()
Supprimons l’ancienne bibliothèque et le fichier d’en-tête du répertoire de test, puis copions les nouveaux fichiers et retournons dans le répertoire test :
Nous supprimons les anciennes versions des fichiers :
rm ./test/libcipher.*
Nous copions les nouvelles versions dans le répertoire test :
cp libcipher.* ./test
Et nous retournons dans le répertoire test :
cd test
Maintenant, nous pouvons modifier le programme test.c pour qu’il utilise la nouvelle fonction de la bibliothèque.
Nous ajoutons une ligne au programme test.c, qui appelle la fonction cipher_version()
, avant la première ligne puts(text)
:
#include#include #include "libcipher.h" int main(int argc, char *argv[]) { char text[]="toptips.fr loves Linux"; // nouvelle ligne ajoutée ici cipher_version(); puts(text); cipher_encode(text); puts(text); cipher_decode(text); puts(text); exit (0); } // fin de main
Enregistrez le fichier sous le nom test.c
. On peut maintenant le compiler et vérifier que la nouvelle fonction fonctionne.
gcc test.c libcipher.a -o test
Lançons la nouvelle version de test :
La nouvelle fonction fonctionne. On peut voir la version de la bibliothèque au début de la sortie du test.
Mais il peut y avoir un problème.
Remplacement d’un module dans la bibliothèque
Ce n’est pas la première version de la bibliothèque, c’est la deuxième. Notre numéro de version est incorrect. La première version ne contenait pas de fonction cipher_version()
. Celle-ci, oui. Elle devrait donc être la version « 0.0.2 ». Nous devons remplacer la fonction cipher_version()
dans la bibliothèque par une fonction corrigée.
Heureusement, ar
rend cela facile.
Tout d’abord, modifions le fichier cipher_version.c
dans le répertoire de la bibliothèque. Remplacez le texte « Version 0.0.1 Alpha » par « Version 0.0.2 Alpha ». Il devrait ressembler à ceci :
#includevoid cipher_version(void) { puts("toptips.fr :: VERY INSECURE Cipher Library"); puts("Version 0.0.2 Alphan"); } // fin de cipher_version
Enregistrez ce fichier. Nous devons le compiler à nouveau pour créer un nouveau fichier objet cipher_version.o
.
gcc -c cipher_version.c
Nous allons remplacer le fichier objet cipher_version.o
existant dans la bibliothèque, par notre nouvelle version compilée.
Nous avons déjà utilisé l’option -r
(ajouter avec remplacer) pour ajouter des modules à la bibliothèque. Lorsque nous l’utilisons avec un module qui existe déjà, ar
remplacera l’ancienne version par la nouvelle. L’option -s
(index) mettra à jour l’index de la bibliothèque et l’option -v
(verbeux) permettra à ar
de nous dire ce qu’il a fait.
ar -rsv libcipher.a cipher_version.o
Cette fois, ar
indique qu’il a remplacé le module cipher_version.o
. Le « r » signifie « remplacé ».
Utilisation de la fonction cipher_version()
mise à jour
Nous allons maintenant utiliser notre bibliothèque modifiée et vérifier qu’elle fonctionne.
Nous copions les fichiers de la bibliothèque dans le répertoire test :
cp libcipher.* ./test
Puis nous nous déplaçons dans le répertoire test :
cd ./test
Nous devons recompiler notre programme de test avec la nouvelle bibliothèque :
gcc test.c libcipher.a -o test
Et maintenant, nous pouvons lancer le programme :
./test
Le résultat du programme de test correspond à ce que nous attendions. Le numéro de version correct est affiché, et les routines de chiffrement et de déchiffrement fonctionnent.
Suppression de modules d’une bibliothèque
Après tout cela, il est dommage de le faire, mais supprimons le fichier cipher_version.o
de la bibliothèque.
Pour cela, nous allons utiliser l’option -d
(supprimer). Nous allons aussi utiliser l’option -v
(verbeux) pour que la commande ar
nous dise ce qu’elle a fait. Nous incluons aussi l’option -s
(index) pour mettre à jour l’index dans la bibliothèque.
ar -dsv libcipher.a cipher_version.o
ar
indique avoir supprimé le module. Le « d » signifie « supprimé ».
Si nous demandons à ar
de lister les modules qui sont dans la bibliothèque, nous voyons que nous sommes revenus à deux modules :
ar -t libcipher.a
Si vous supprimez des modules de votre bibliothèque, n’oubliez pas de supprimer leur définition du fichier d’en-tête de la bibliothèque.
Partager votre code
Les bibliothèques permettent de partager le code de manière pratique, tout en gardant le code source privé. Ceux à qui vous donnez la bibliothèque et le fichier d’en-tête pourront utiliser vos fonctions, sans avoir accès au code source.