Lien statique de la fonction de bibliothèque partagée dans gcc

138

Comment puis-je lier une fonction de bibliothèque partagée de manière statique dans gcc?

suresh
la source
14
Qu'entendez-vous par lié statiquement? Voulez-vous que votre exécutable soit distribué sans avoir besoin du .so?
Emiliano

Réponses:

108

Faire référence à:

http://www.linuxquestions.org/questions/linux-newbie-8/forcing-static-linking-of-shared-libraries-696714/

http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.apps/2004-05/0436.html

Vous avez besoin de la version statique de la bibliothèque pour la lier.

Une bibliothèque partagée est en fait un exécutable dans un format spécial avec des points d'entrée spécifiés (et quelques problèmes d'adressage persistants inclus). Il ne dispose pas de toutes les informations nécessaires pour établir un lien statique.

Vous ne pouvez pas lier statiquement une bibliothèque partagée (ou lier dynamiquement une bibliothèque statique).

Le drapeau -static forcera l'éditeur de liens à utiliser des bibliothèques statiques (.a) au lieu de celles partagées (.so). Mais les bibliothèques statiques ne sont pas toujours installées par défaut, vous devrez donc peut-être installer la bibliothèque statique vous-même.

Une autre approche possible consiste à utiliser un statificateur ou de l' hermine . Les deux outils prennent comme entrée un exécutable lié dynamiquement et comme sortie créent un exécutable autonome avec toutes les bibliothèques partagées incorporées.

Sam Liao
la source
11
Quelles informations la bibliothèque statique possède-t-elle, de sorte qu'elle puisse être liée statiquement, que la bibliothèque dynamique n'a pas?
kbolino
75

Si vous voulez lier, disons, libapplejuice statiquement, mais pas, disons, liborangejuice , vous pouvez créer un lien comme ceci:

gcc object1.o object2.o -Wl,-Bstatic -lapplejuice -Wl,-Bdynamic -lorangejuice -o binary

Il y a une mise en garde - si elle est liborangejuiceutilisée libapplejuice, elle libapplejuicesera également liée dynamiquement.

Vous devrez établir un lien liborangejuicestatique avec libapplejuicepour obtenir de la libapplejuicestatique.

Et n'oubliez pas de garder -Wl,-Bdynamicsinon vous finirez par lier tout ce qui est statique, y compris libc(ce qui n'est pas une bonne chose à faire).

Eugène Bujak
la source
2
N'y a-t-il pas un moyen de dire directement à gcc ce qu'il doit lier statiquement, et de ne pas le contourner et de parler avec l'éditeur de liens?
Elazar Leibovich
1
@ElazarLeibovich vous ne pouvez pas obtenir une combinaison de statique et de dynamique de cette façon.
Haozhun
@EugeneBujak: La mise en garde ne s'applique pas à mon système. Exemple: gcc -o main main.cc -Wl,-rpath=. -Wl,-Bdynamic -lB -Wl,-Bstatic -lA -Wl,-Bdynamic -L. libB utilise libA , il est lié et lddn'affiche pas de référence à libA . L'exécutable fonctionne bien. Testé avec g ++ 4.7.3.
radix
Une dépendance indirecte (imbriquée), statique, d'une dépendance directe et dynamique ne devient pas elle-même liée dynamiquement.
Vinny
Considérez ce qui suit: binA dépend de libB.so qui dépend de libC.a Comme d'autres l'ont déjà dit, les .so sont eux-mêmes exécutables, donc lorsqu'un objet partagé est lié, tous les dépendants de la bibliothèque statique sont traités par l'éditeur de liens de la même manière que si un exécutable était en cours de liaison: les seuls symboles extraits de la bibliothèque statique .a sont ceux référencés (et non résolus) par le .so. Cela signifie que si binA fait référence à un symbole dans libC.a, qui n'est référencé nulle part dans libB.so, alors même si binA est lié à libB.so, ce symbole sera indéfini (sauf si -Wl, - whole-archive est utilisé lors de la liaison libB.so).
Vinny
18

Si vous avez le fichier .a de votre bibliothèque partagée (.so), vous pouvez simplement l'inclure avec son chemin complet comme s'il s'agissait d'un fichier objet, comme ceci:

Cela génère main.o en compilant simplement:

gcc -c main.c

Cela relie ce fichier objet à la bibliothèque statique correspondante et crée l'exécutable (nommé "main"):

gcc main.o mylibrary.a -o main

Ou en une seule commande:

gcc main.c mylibrary.a -o main

Il peut également s'agir d'un chemin absolu ou relatif:

gcc main.c /usr/local/mylibs/mylibrary.a -o main
NeoEGM
la source
12

Oui, je sais que c'est une question vieille de 8 ans, mais on m'a dit qu'il était possible d'établir un lien statique avec une bibliothèque d'objets partagés et c'était littéralement le premier succès lorsque j'ai cherché plus d'informations à ce sujet.

Pour démontrer en fait que la liaison statique d'une bibliothèque d'objets partagés n'est pas possible avec ld( gccl'éditeur de liens) - par opposition à juste un groupe de personnes insistant sur le fait que ce n'est pas possible - utilisez la gcccommande suivante :

gcc -o executablename objectname.o -Wl,-Bstatic -l:libnamespec.so

(Bien sûr, vous devrez compiler à objectname.opartir de sourcename.c, et vous devriez probablement créer votre propre bibliothèque d'objets partagés également. Si vous le faites, utilisez -Wl,--library-path,.pour que ld puisse trouver votre bibliothèque dans le répertoire local.)

L'erreur réelle que vous recevez est:

/usr/bin/ld: attempted static link of dynamic object `libnamespec.so'
collect2: error: ld returned 1 exit status

J'espère que cela pourra aider.

Ian Moote
la source
10

Un peu tard mais ... j'ai trouvé un lien que j'ai sauvegardé il y a quelques années et j'ai pensé qu'il pourrait être utile pour vous les gars:

CDE: créer automatiquement des applications Linux portables

http://www.pgbovine.net/cde.html

  • Téléchargez simplement le programme
  • Exécutez le binaire en passant en argument le nom du binaire que vous souhaitez rendre portable, par exemple: nmap

    ./cde_2011-08-15_64bit nmap

Le programme lira toutes les bibliothèques liées à nmap et ses dépendances et les enregistrera toutes dans un dossier appelé cde-package / (dans le même répertoire que vous).

  • Enfin, vous pouvez compresser le dossier et déployer le binaire portable dans n'importe quel système.

N'oubliez pas que pour lancer le programme portable, vous devez exécuter le binaire situé dans cde-package / nmap.cde

Meilleures salutations

Francis
la source
2
Bien que ne fournissant pas exactement la réponse à la question, c'est une solution notable au problème.
razong
Le lien semble être mort maintenant.
sinan
0

Dans gcc, cela n'est pas pris en charge. En fait, cela n'est pris en charge dans aucun compilateur / éditeur de liens existant à ma connaissance.

pas jeter
la source
4
Pourriez-vous expliquer comment la liaison statique n'est prise en charge par aucun compilateur existant?
jww
5
@noloader, liaison statique d'une bibliothèque dynamique?
nothrow