Nous avons récemment demandé d'expédier une version Linux de l'un de nos bibliothèques, auparavant, nous avons développé sous Linux et expédiés pour Windows où le déploiement des bibliothèques est généralement beaucoup plus facile. Le problème que nous avons trouvé est en dépouillant les symboles exportés vers le bas pour seulement ceux dans l'exposé de l'interface. Il y a trois bonnes raisons de vouloir le faire
- Afin de protéger les droits de propriété de notre technologie de l'exposition à travers les symboles exportés.
- Pour empêcher les utilisateurs ayant des problèmes de conflit noms de symbole.
- Afin d'accélérer le chargement de la bibliothèque (au moins je me dit).
En prenant un exemple simple alors:
test.cpp
#include <cmath>
float private_function(float f)
{
return std::abs(f);
}
extern "C" float public_function(float f)
{
return private_function(f);
}
compilé avec g++ 4.3.2, ld 2.18.93.20081009)
g++ -shared -o libtest.so test.cpp -s
et d'inspecter les symboles avec
nm -DC libtest.so
donne
w _Jv_RegisterClasses
0000047c T private_function(float)
000004ba W std::abs(float)
0000200c A __bss_start
w __cxa_finalize
w __gmon_start__
0000200c A _edata
00002014 A _end
00000508 T _fini
00000358 T _init
0000049b T public_function
manifestement inadéquat. Donc nous redeclare la fonction publique
extern "C" float __attribute__ ((visibility ("default")))
public_function(float f)
et compiler avec
g++ -shared -o libtest.so test.cpp -s -fvisibility=hidden
ce qui donne
w _Jv_RegisterClasses
0000047a W std::abs(float)
0000200c A __bss_start
w __cxa_finalize
w __gmon_start__
0000200c A _edata
00002014 A _end
000004c8 T _fini
00000320 T _init
0000045b T public_function
ce qui est bon, sauf que std::abs est exposée. Plus problématique, c'est lorsque nous avons commencer à relier à d'autres (statique) des bibliothèques à l'extérieur de notre contrôle, tous les symboles que nous utilisons à partir de ces bibliothèques exportés. En outre, lorsque nous commençons à utiliser des conteneurs STL:
#include <vector>
struct private_struct
{
float f;
};
void other_private_function()
{
std::vector<private_struct> v;
}
nous nous retrouvons avec de nombreux autres exportations à partir de la bibliothèque C++
00000b30 W __gnu_cxx::new_allocator<private_struct>::deallocate(private_struct*, unsigned int)
00000abe W __gnu_cxx::new_allocator<private_struct>::new_allocator()
00000a90 W __gnu_cxx::new_allocator<private_struct>::~new_allocator()
00000ac4 W std::allocator<private_struct>::allocator()
00000a96 W std::allocator<private_struct>::~allocator()
00000ad8 W std::_Vector_base<private_struct, std::allocator<private_struct> >::_Vector_impl::_Vector_impl()
00000aaa W std::_Vector_base<private_struct, std::allocator<private_struct> >::_Vector_impl::~_Vector_impl()
00000b44 W std::_Vector_base<private_struct, std::allocator<private_struct> >::_M_deallocate(private_struct*, unsigned int)
00000a68 W std::_Vector_base<private_struct, std::allocator<private_struct> >::_M_get_Tp_allocator()
00000b08 W std::_Vector_base<private_struct, std::allocator<private_struct> >::_Vector_base()
00000b6e W std::_Vector_base<private_struct, std::allocator<private_struct> >::~_Vector_base()
00000b1c W std::vector<private_struct, std::allocator<private_struct> >::vector()
00000bb2 W std::vector<private_struct, std::allocator<private_struct> >::~vector()
NB: Avec des optimisations sur vous devrez vous assurer que le vecteur est effectivement utilisé de sorte que le compilateur n'a pas d'optimiser le solde non utilisé des symboles à partir.
Je crois que mon collègue a réussi à construire un groupe ad-hoc solution impliquant les fichiers de la version et de la modification de la STL en-têtes (!) qui semble fonctionner, mais je voudrais vous demander:
Est-il un moyen propre à la bande de tous les inutiles symboles (c'est à dire ceux qui ne font pas partie de l'exposé de la bibliothèque de la fonctionnalité) à partir d'une bibliothèque partagée? J'ai essayé tout un tas d'options à la fois g++ et ld avec peu de succès donc je préfère des réponses qui sont connus pour travailler plutôt que cru.
En particulier:
- Les symboles de (closed-source) les bibliothèques statiques ne sont pas exportés.
- Les symboles de la bibliothèque standard ne sont pas exportés.
- Non-public des symboles à partir des fichiers de l'objet ne sont pas exportés.
Notre exporté interface est C.
Je suis conscient des autres questions similaires sur DONC:
- http://stackoverflow.com/questions/1638073/not-sharing-all-classes-with-shared-library
- http://stackoverflow.com/questions/1931626/how-to-really-strip-a-binary-in-macos
- http://stackoverflow.com/questions/792195/gnu-linker-alternative-to-version-script-to-list-exported-symbols-at-the-comma
mais ils ont eu peu de succès avec les réponses.