J'ai un projet de bibliothèque partagée qui est construit à partir de 4 bibliothèques statiques (.a
) Et d'un fichier objet (.o
). J'essaie d'ajouter l'option -fvisibility=hidden
Pour restreindre les symboles dans la sortie à ceux que je marque dans la source avec un __attribute__.
J'ai ajouté l'option -fvisibility=hidden
Aux options de compilation pour le projet .so
(Qui couvre le fichier .o
) Et pour les projets .a
.
Les symboles du fichier objet sont supprimés comme prévu dans le .so
Final. Cependant, les symboles des projets .a
Sont toujours dans le fichier final .so
. L'ajout de l'option -fvisibility=hidden
À la commande de lien .so
N'a aucun effet.
Qu'est-ce que je fais mal?
Mon but ici est de supprimer du .so
Tous les symboles à l'exception des fonctions d'interface avec la bibliothèque.
EDIT: J'ai utilisé un version map pour résoudre ce problème pour l'instant. Cependant, cela nécessite une maintenance continue du script de version à mesure que les symboles externes changent. La réponse acceptée a une meilleure idée.
Fondamentalement, la visibilité est gérée lors de la liaison, et l'éditeur de liens ne semble pas l'imposer aux archives statiques. Une question connexe (mais pas en double) a été posée le SO ici .
Ce que je vous conseille de faire est de remplacer votre étape de liaison: gcc -shared -o mylib.so foo.o libbar.a
en deux étapes où vous récupérez les fichiers objets:
ar x libbar.a
(éventuellement dans un répertoire vide approprié)gcc -fvisibility=hidden -shared -o mylib.so foo.o tempdir/*.o
Passez simplement -Wl,--exclude-libs,ALL
à gcc
Cela indiquera à l'éditeur de liens de transformer tous les symboles des bibliothèques statiques en masqués.
--exclude-libs
accepte également une liste d'archives (c'est-à-dire les noms de bibliothèques statiques) pour une granularité plus fine sur laquelle les bibliothèques doivent cacher les symboles.
Remarque: cela ne fonctionnera que dans les systèmes utilisant GNU binutils (par exemple Linux) ou avec un éditeur de liens prenant en charge --exclude-libs
(par exemple, il ne fonctionnera pas avec le ld64 d'OSX)
Ceci est une réponse au problème pour OS X.
Le Mac ld
ne prend pas en charge --exclude-libs
, mais il prend en charge -exported_symbol sym
et il le fait applique ceci aux fichiers objets dans les bibliothèques statiques. Et lorsque vous filtrez vers une API publique, la liste blanche est suffisamment petite pour le préciser.
Je me suis retrouvé avec ce qui suit dans mon Makefile pour générer un -Wl,-exported_symbol,_api_func_1
drapeau pour chaque symbole exporté:
SYMBOLS = api_func_1 api_func_2 api_func_3 api_func_4
SYMBOLS += api_func_5 # add more as necessary
COMMA = ,
LDFLAGS += $(addprefix -Wl$(COMMA)-exported_symbol$(COMMA)_,$(SYMBOLS))
# ...
libmyapi.so: # ...
$(CC) -shared -o $@ ... $(LDFLAGS)
Ensuite, vous pouvez if-gate entre cette version des drapeaux et la version GNU ld après avoir détecté l'éditeur de liens du système).