2010-11-14 50 views
6

J'ai un programme, myprogram, qui est lié à une bibliothèque de commodité statique, appelez-le libconvenience.a, qui contient une fonction, func(). La fonction func() n'est appelée nulle part dans myprogram; il doit pouvoir être appelé depuis une bibliothèque de plugins, plugin.so.Les symboles de la bibliothèque de commodité ne sont pas exportés dans l'exécutable

Le symbole func() n'est pas exporté dynamiquement dans myprogram. Si je cours

nm myprogram | grep func 

Je n'ai rien. Cependant, il ne manque pas de libconvenience.a:

nm libconvenience/libconvenience.a | grep func
00000000 T func

J'utilise automake, mais si je fais la dernière étape de liaison à la main sur la ligne de commande à la place, il ne fonctionne pas non plus:

gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/libconvenience.a `pkg-config --libs somelibraries` 

Cependant, si je lier le programme comme celui-ci, en sautant l'utilisation d'une bibliothèque de commodité et de relier les fichiers objets qui sont passés en libconvenience.a directement, func() apparaît dans myprogram « symboles de comme il se doit:

gcc -Wl,--export-dynamic -o myprogram *.o libconvenience/*.o `pkg-config --libs somelibraries` 

Si j'ajoute un appel factice à func() quelque part dans myprogram, puis func() montre également dans myprogram » s symboles. Mais je pensais que --export-dynamic était censé exporter tous les symboles, qu'ils soient ou non utilisés dans le programme!

J'utilise automake 1.11.1 et 4.5.1 sur Fedora gcc 14. J'utilise aussi libtool 2.2.10 pour construire plugin.so (mais pas la bibliothèque de commodité.)

Je ne pas oublier de mettre -Wl,--export-dynamic à myprogram_LDFLAGS, ni ai-je oublié de mettre la source qui contient func() dans libconvenience_a_SOURCES (quelques recherches sur Google suggère que ce sont des causes fréquentes de ce problème.)

quelqu'un peut me aider à comprendre ce qui se passe ici?

Répondre

3

J'ai réussi à le résoudre. Ce fut cette note de John Calcote d'excellent livre Autotools qui m'a orienté dans la bonne direction:

Linkers ajouter au produit binaire chaque fichier objet spécifié explicitement sur la ligne de commande, mais ne fait qu'extraire des archives les fichiers d'objet sont réellement référencés dans le code lié.

Pour contrer ce comportement, vous pouvez utiliser l'indicateur --whole-archive sur libtool. Cependant, tous les symboles de toutes les bibliothèques système sont également entraînés, ce qui provoque de nombreuses erreurs de définition de symboles doubles.Donc, --whole-archive doit être juste avant libconvenience.a sur la ligne de commande de l'éditeur de liens, et il doit être suivi par --no-whole-archive afin que les autres bibliothèques ne soient pas traitées de cette façon. Ceci est un peu difficile car automake et libtool ne garantissent pas vraiment garder vos drapeaux dans le même ordre sur la ligne de commande, mais cette ligne Makefile.am a fait l'affaire:

myprogram_LDFLAGS = -Wl,--export-dynamic \ 
    -Wl,--whole-archive,libconvenience/libconvenience.a,--no-whole-archive 
0

Si vous avez besoin de func pour être dans plugin.so, vous devriez essayer de le localiser si possible. Les bibliothèques de commodité sont censées être juste cela - une commodité de lier à un exécutable ou lib comme une étape intermédiaire.

+0

vrai, mais je dois explicitement func _PAS_ être dans le plugin, car func fait partie d'une API que plusieurs plugins doivent appeler. Les plugins ont été écrits ailleurs et j'essaie d'éviter les modifications locales. – ptomato