ar
Sous Linux, ar
est l'archiveur GNU à usage général. (Il existe des variantes non GNU ar
dans d'autres systèmes d'exploitation de type Unix). Avec l'optionc
ar c... archive-name file...
Il crée une archive contenant des copies de file...
. Le archive-name
conventionnellement, mais pas nécessairement, a l'extension .a
(pour l' archive ). Chacun file...
peut être n'importe quel type de fichier, pas nécessairement un fichier objet.
Lorsque les fichiers archivés sont tous des fichiers objets, il est généralement prévu d'utiliser l'archive pour fournir cette sélection de fichiers objets dans la liaison de programmes ou DSO (Dynamic Shared Objects). Dans ce cas archive-name
, le préfixe sera également classiquement attribué lib
, par exemple
libfoo.a
, afin qu'il puisse être découvert en tant que fichier d'entrée de l'éditeur de liens via l'option de l'éditeur de liens -lfoo
.
Utilisé comme fichier d'entrée de l'éditeur de liens, il libfoo.a
est normalement appelé bibliothèque statique . Cette utilisation est une source perpétuelle de confusion pour les programmeurs inexpérimentés, car elle les amène à penser qu'une archive libfoo.a
est à peu près la même chose qu'un DSO libfoo.so
, normalement appelé bibliothèque dynamique / partagée , et à construire de fausses attentes sur cette base. En fait, une "bibliothèque statique" et une "bibliothèque dynamique" ne sont pas du tout des choses similaires et sont utilisées dans la liaison de manières totalement différentes.
Une différence notable est qu'une bibliothèque statique n'est pas produite par l' éditeur de liens , mais par ar
. Donc, aucun lien ne se produit, aucune résolution de symbole ne se produit. Les fichiers objets archivés sont inchangés: ils sont juste mis dans un sac.
Lorsqu'une archive est entrée dans le lien de quelque chose qui est produit par l'éditeur de liens - tel qu'un programme ou DSO - l'éditeur de liens regarde dans le sac pour voir s'il y a des fichiers objets qui fournissent des définitions pour les références de symboles non résolues qui se sont accumulées plus tôt dans la liaison. Si elle en trouve, il extrait les fichiers d'objets du sac et relie les dans le fichier de sortie, exactement comme s'ils ont été nommés individuellement dans la ligne de commande de liaison et l'archive ne mentionne pas du tout. Ainsi, le rôle entier d'une archive dans la liaison est comme un sac de fichiers objets à partir duquel l'éditeur de liens peut sélectionner ceux dont il a besoin pour poursuivre la liaison.
Par défaut, GNU ar
rend ses archives de sortie prêtes à être utilisées comme entrées de l'éditeur de liens. Il ajoute un "fichier" bidon à l'archive, avec un nom de fichier bidon magique, et dans ce fichier bidon, il écrit du contenu que l'éditeur de liens est capable de lire comme une table de recherche à partir des symboles globaux définis par n'importe quel fichier objet de l'archive. aux noms et positions de ces fichiers objets dans l'archive. Cette table de recherche permet à l'éditeur de liens de rechercher dans l'archive et d'identifier tous les fichiers d'objets qui définissent les références de symboles non résolues qu'il a en main.
Vous pouvez supprimer la création ou la mise à jour de cette table de recherche avec l' option q
(=
rapide ) - que vous avez en fait utilisée dans votre propre ar
exemple - et également avec l' option (majuscule) S
(= pas de table de symboles ). Et si vous invoquez ar
pour créer ou mettre à jour une archive qui n'a pas de table de symboles (à jour) pour une raison quelconque, vous pouvez lui en donner une avec l' s
option.
ranlib
ranlib
ne crée pas du tout de bibliothèques. Sous Linux, ranlib
est un programme hérité qui ajoute une table de symboles (à jour) à une ar
archive si elle n'en a pas. Son effet est exactement le même ar s
qu'avec GNU ar
. Historiquement, avant ar
était équipé pour générer une table de symboles elle-même, ranlib
était le kludge qui a injecté le fichier bidon magique dans une archive pour permettre à l'éditeur de liens de choisir des fichiers objet à partir de celui-ci. Dans les systèmes d'exploitation non GNU Unix, il ranlib
pourrait encore être nécessaire à cet effet. Votre exemple:
ar qc libgraphics.a *.o
ranlib libgraphics.a
dit:
- Créez
libgraphics.a
en ajoutant à une archive tous les *.o
fichiers du répertoire courant, sans table de symboles.
- Ajoutez ensuite une table de symboles à
libgraphics.a
Sous Linux, cela a le même effet net que:
ar cr libgraphics.a *.o
En soi, ar qc libgraphics.a *.o
crée une archive que l'éditeur de liens ne peut pas utiliser, car il n'a pas de table de symboles.
ld
Votre exemple:
ld -r -o libgraphics.a *.o
est en fait assez peu orthodoxe. Ceci illustre l'utilisation assez rare de l' éditeur de liens ,
ld
pour produire un fusionné fichier objet en reliant plusieurs fichiers d'entrée dans un seul fichier objet de sortie, dans laquelle la résolution des symboles a été fait dans la mesure du possible , étant donné les fichiers d'entrée. L' option -r
(= relocatable ) demande à l'éditeur de liens de produire une cible de fichier objet (plutôt qu'un programme ou DSO) en liant les entrées autant que possible et de ne pas faire échouer le linkaqe si des références de symboles non définies restent dans le fichier de sortie. Cette utilisation est appelée liaison partielle .
Le fichier de sortie de ld -r ...
est un fichier objet, pas une ar
archive , et spécifier un nom de fichier de sortie qui ressemble à celui d'une ar
archive n'en fait pas un. Votre exemple illustre donc une tromperie. Cette:
ld -r -o graphics.o *.o
serait véridique. Je ne sais pas quel pourrait être le but d'une telle tromperie, car même si un fichier objet ELF est appelé libgraphics.a
et est entré dans une liaison soit par ce nom, soit par -lgraphics
l'éditeur de liens l'identifiera correctement en tant que fichier objet ELF , pas une ar
archive, et le consommera comme il consomme n'importe quel fichier objet dans la ligne de commande: il le relie inconditionnellement au fichier de sortie, alors que le point d'entrée d'une archive authentique est de lier les membres de l'archive uniquement à condition qu'ils soient référencés . Peut-être avez-vous juste un exemple de lien mal informé ici.
Emballer...
En fait, nous n'avons vu qu'une seule façon de produire quelque chose qui est conventionnellement appelé une bibliothèque , et c'est la production d'une bibliothèque dite statique , en archivant certains fichiers objets et en mettant une table de symboles dans l'archive.
Et nous n'avons pas du tout vu comment produire l'autre type de chose le plus important que l'on appelle conventionnellement une bibliothèque , à savoir un objet partagé dynamique / bibliothèque partagée / bibliothèque dynamique.
Comme un programme, un DSO est produit par l'éditeur de liens . Un programme et un DSO sont des variantes du fichier binaire ELF que le chargeur du système d'exploitation comprend et peut utiliser pour assembler un processus en cours d'exécution. Habituellement , nous invoquons l'éditeur de liens via une une des interfaces de GCC ( gcc
, g++
, gfortran
, etc.):
Lier un programme:
gcc -o prog file.o ... -Ldir ... -lfoo ...
Lier un DSO:
gcc -shared -o libbar.so file.o ... -Ldir ... -lfoo ...
Les bibliothèques partagées et les bibliothèques statiques peuvent être proposées à l'éditeur de liens par le -lfoo
protocole uniforme , lorsque vous liez un autre programme ou DSO. Cette option demande à l'éditeur de liens d'analyser ses répertoires de recherche spécifiés ou par défaut pour trouver
libfoo.so
ou libfoo.a
. Par défaut, une fois qu'il a trouvé l'un d'eux, il entrera ce fichier dans la liaison, et s'il trouve les deux dans le même répertoire de recherche, il préférera libfoo.so
. Si libfoo.so
, est sélectionné, l'éditeur de liens ajoute ce DSO à la liste des dépendances d'exécution de n'importe quel programme ou DSO que vous créez. Si libfoo.a
est sélectionné, l'éditeur de liens utilise l'archive comme une sélection de fichiers objets à lier au fichier de sortie, si nécessaire, juste là et ensuite. Aucune dépendance d'exécution sur
libfoo.a
lui-même est possible; il ne peut pas être mappé dans un processus; cela ne signifie rien pour le chargeur du système d'exploitation.
Copié à partir de https://stackoverflow.com/a/47924864/195787 .