Comment inclure toujours les symboles d’une bibliothèque statique?

Supposons que je dispose d’une bibliothèque statique libx.a. Comment puis-je faire en sorte que certains symboles (pas tous) de cette bibliothèque soient toujours présents dans les liens binarys avec ma bibliothèque? La raison est que j’ai besoin que ces symboles soient disponibles via dlopen + dlsym. Je suis au courant du commutateur –whole-archive linker, mais il oblige tous les fichiers objects de l’archive de bibliothèque à être liés au binary résultant, et ce n’est pas ce que je veux …

Observations jusqu’à présent (CentOS 5.4, 32bit) (mise à jour : ce paragraphe est faux; je n’ai pas pu reproduire ce comportement)

ld main.o libx.a 

sera heureux de supprimer tous les symboles non référencés, tandis que

 ld main.o -L. -lx 

reliera toute la bibliothèque. Je suppose que cela dépend de la version de binutils utilisée, et que les nouveaux éditeurs de liens pourront sélectionner des objects individuels dans une bibliothèque statique.

Une autre question est de savoir comment obtenir le même effet sous Windows?

Merci d’avance. Tout conseil sera grandement apprécié.

Imaginez que vous ayez un projet composé des trois fichiers C suivants dans le même dossier;

 // ---- jam.h int jam_badger(int); // ---- jam.c #include "jam.h" int jam_badger(int a) { return a + 1; } // ---- main.c #include "jam.h" int main() { return jam_badger(2); } 

Et vous le construisez avec un fichier bjam boost-build comme celui-ci;

 lib jam : jam.c static ; lib jam_badger : jam ; exe demo : jam_badger main.c ; 

Vous obtiendrez une erreur comme celle-ci.

 undefined reference to `jam_badger' 

(J’ai utilisé bjam ici parce que le fichier est plus facile à lire, mais vous pouvez utiliser tout ce que vous voulez)

La suppression du fichier statique produit un fichier binary qui fonctionne, tout comme l’ajout de données statiques à l’autre bibliothèque, ou l’utilisation de la bibliothèque unique (plutôt que de l’enveloppement idiot dans l’autre bibliothèque).

La raison en est que ld est assez intelligent pour ne sélectionner que les parties de l’archive qui sont réellement utilisées, ce qui n’est pas le cas dans ce cas.

La solution consiste à entourer les archives statiques avec -Wl, – archive-entier et -Wl, – sans-ensemble-archive, comme ceci;

 g++ -o "libjam_candle_badger.so" -Wl,--whole-archive libjam_badger.a Wl,--no-whole-archive 

Pas tout à fait sûr de savoir comment obtenir du boost-build pour le faire pour vous, mais vous avez l’idée.

Tout d’abord, ld main.o libx.a ne ld main.o libx.a pas d’exécutable valide. En général, vous ne devez jamais utiliser ld pour lier quelque chose directement; utilisez toujours le pilote de compilation correct ( gcc dans ce cas) à la place.

En outre, "ld main.o libx.a" et "ld main.o -L. -lx" doivent être exactement équivalents. Je doute fort que vous ayez obtenu des résultats différents de ces deux commandes.

Maintenant, pour répondre à votre question: si vous voulez que foo , bar et baz soient exportés depuis votre a.out , faites ceci:

 gcc -Wl,-u,foo,-u,bar,-u,baz main.o -L. -lx -rdynamic 

Mettre à jour:
votre déclaration: “les symboles que je veux inclure sont utilisés par la bibliothèque uniquement en interne” n’a pas beaucoup de sens: si les symboles sont internes à la bibliothèque, pourquoi voulez-vous les exporter? Et si quelque chose d’autre les utilise (via dlsym), alors ils ne sont pas internes à la bibliothèque – ils font partie de l’API publique de la bibliothèque.

Vous devriez clarifier votre question et expliquer ce que vous essayez vraiment de réaliser. Fournir un exemple de code ne nuira pas non plus.

Je commencerais par séparer les symboles dont vous avez toujours besoin dans une bibliothèque séparée, en ne conservant que les options de libx.a

Prenez une adresse du symbole à inclure.

Si l’optimiseur de gcc l’élimine de toute façon, faites quelque chose avec cette adresse – cela devrait suffire.