J'ai besoin d'optimiser sévèrement la taille de mon exécutable ( ARM
développement) et j'ai remarqué que dans mon schéma de construction actuel ( gcc
+ ld
) les symboles inutilisés ne sont pas supprimés.
L'utilisation de arm-strip --strip-unneeded
pour les exécutables / bibliothèques résultants ne change pas la taille de sortie de l'exécutable (je ne sais pas pourquoi, peut-être que cela ne peut tout simplement pas) .
Quelle serait la façon (si elle existe) de modifier mon pipeline de construction, de sorte que les symboles inutilisés soient supprimés du fichier résultant?
Je n'y penserais même pas, mais mon environnement embarqué actuel n'est pas très "puissant" et économise même 500K
des 2M
résultats dans une très belle amélioration des performances de chargement.
Mettre à jour:
Malheureusement, la gcc
version actuelle que j'utilise n'a pas l' -dead-strip
option et le -ffunction-sections... + --gc-sections
for ld
ne donne aucune différence significative pour la sortie résultante.
Je suis choqué que cela soit même devenu un problème, car j'étais sûr que cela gcc + ld
devrait automatiquement supprimer les symboles inutilisés (pourquoi doivent-ils même les conserver?).
boost
bibliothèques, le.exe
fichier résultant contient de nombreux fichiers objets inutilisés et en raison des spécifications de mon runtime intégré actuel , le démarrage d'une10mb
application prend beaucoup plus de temps que, par exemple, le démarrage d'une500k
application.Réponses:
Pour GCC, cela se fait en deux étapes:
Commencez par compiler les données, mais dites au compilateur de séparer le code en sections distinctes au sein de l'unité de traduction. Cela sera fait pour les fonctions, les classes et les variables externes en utilisant les deux indicateurs de compilateur suivants:
Liez les unités de traduction ensemble à l'aide de l'indicateur d'optimisation de l'éditeur de liens (cela oblige l'éditeur de liens à supprimer les sections non référencées):
Donc, si vous aviez un fichier appelé test.cpp qui contenait deux fonctions déclarées, mais que l'une d'elles n'était pas utilisée, vous pouvez omettre le fichier inutilisé avec la commande suivante à gcc (g ++):
(Notez que -Os est un indicateur de compilateur supplémentaire qui indique à GCC d'optimiser la taille)
la source
mingw
cela ne fonctionne pas lors de la liaison statiquement statique de libstdc ++ et libgcc avec l'indicateur-static
. L'option de l'éditeur de liens-strip-all
aide un peu, mais l'exécutable généré (ou dll) est environ 4 fois plus grand que ce que Visual Studio générerait. Le fait est que je n'ai aucun contrôle sur la façon dont alibstdc++
été compilé. Il devrait y avoir uneld
seule option.Si l' on en croit ce thread , vous devez fournir le
-ffunction-sections
et-fdata-sections
à gcc, qui placera chaque fonction et objet de données dans sa propre section. Ensuite, vous donnez et--gc-sections
à GNU ld pour supprimer les sections inutilisées.la source
Vous voudrez vérifier vos documents pour votre version de gcc & ld:
Cependant pour moi (OS X gcc 4.0.1) je trouve ceux-ci pour ld
Et cette option utile
Il y a aussi une note dans le manuel gcc / g ++ que certains types d'élimination de code mort ne sont effectués que si l'optimisation est activée lors de la compilation.
Bien que ces options / conditions ne soient pas valables pour votre compilateur, je vous suggère de rechercher quelque chose de similaire dans vos documents.
la source
mingw
.-dead_strip
n'est pas unegcc
option.Les habitudes de programmation pourraient également aider; par exemple, ajouter
static
aux fonctions qui ne sont pas accessibles en dehors d'un fichier spécifique; utiliser des noms plus courts pour les symboles (peut aider un peu, probablement pas trop); utiliserconst char x[]
dans la mesure du possible; ... cet article , bien qu'il parle d'objets partagés dynamiques, peut contenir des suggestions qui, si elles sont suivies, peuvent aider à réduire la taille de votre sortie binaire finale (si votre cible est ELF).la source
.so
sous Linux), donc les noms de symboles doivent être conservés afin que les API comme lectypes
module FFI de Python puissent les utiliser pour rechercher des symboles par nom au moment de l'exécution.La réponse est
-flto
. Vous devez le transmettre à la fois à vos étapes de compilation et de lien, sinon cela ne fait rien.Cela fonctionne très bien - réduit la taille d'un programme de microcontrôleur que j'ai écrit à moins de 50% de sa taille précédente!
Malheureusement, cela semblait un peu bogué - j'ai eu des exemples de choses qui n'étaient pas construites correctement. Cela peut être dû au système de construction que j'utilise (QBS; c'est très nouveau), mais dans tous les cas, je vous recommande de ne l'activer que pour votre version finale si possible, et de tester cette construction à fond.
la source
-flto
je ne comprends pas ce qu'il fait en coulisse.-flto
cela ne compile pas chaque fichier en assemblage, il les compile en LLVM IR, puis le lien final les compile comme s'ils étaient tous dans une seule unité de compilation. Cela signifie qu'il peut éliminer les fonctions inutilisées et les non-static
uns inline , et probablement d'autres choses aussi. Voir llvm.org/docs/LinkTimeOptimization.htmlBien que ce ne soit pas strictement sur les symboles, si vous choisissez la taille, compilez toujours avec les indicateurs
-Os
et-s
.-Os
optimise le code résultant pour la taille minimale de l'exécutable et-s
supprime la table de symboles et les informations de déplacement de l'exécutable.Parfois - si une petite taille est souhaitée - jouer avec différents indicateurs d'optimisation peut - ou non - avoir une signification. Par exemple, basculer
-ffast-math
et / ou-fomit-frame-pointer
peut parfois vous faire économiser même des dizaines d'octets.la source
-ffast-math
des ravages dans un code C ++ entièrement conforme aux normes, donc je ne le recommanderais jamais.Il me semble que la réponse fournie par Nemo est la bonne. Si ces instructions ne fonctionnent pas, le problème peut être lié à la version de gcc / ld que vous utilisez, comme exercice, j'ai compilé un exemple de programme en utilisant les instructions détaillées ici
Ensuite, j'ai compilé le code en utilisant des commutateurs de suppression de code mort de plus en plus agressifs:
Ces paramètres de compilation et de liaison ont produit des exécutables de taille 8457, 8164 et 6160 octets, respectivement, la contribution la plus importante provenant de la déclaration «strip-all». Si vous ne pouvez pas produire de réductions similaires sur votre plate-forme, alors peut-être que votre version de gcc ne prend pas en charge cette fonctionnalité. J'utilise gcc (4.5.2-8ubuntu4), ld (2.21.0.20110327) sur Linux Mint 2.6.38-8-generic x86_64
la source
strip --strip-unneeded
ne fonctionne que sur la table des symboles de votre exécutable. Il ne supprime en fait aucun code exécutable.Les bibliothèques standard obtiennent le résultat que vous recherchez en divisant toutes leurs fonctions en fichiers objets séparés, qui sont combinés à l'aide de
ar
. Si vous liez ensuite l'archive résultante en tant que bibliothèque (c'est-à-dire donnez l'option-l your_library
à ld) alors ld n'inclura que les fichiers objets, et donc les symboles, qui sont réellement utilisés.Vous pouvez également trouver certaines des réponses à cette question d'utilisation similaire .
la source
Je ne sais pas si cela vous aidera dans votre situation actuelle car il s'agit d'une fonctionnalité récente, mais vous pouvez spécifier la visibilité des symboles de manière globale. Passer
-fvisibility=hidden -fvisibility-inlines-hidden
à la compilation peut aider l'éditeur de liens à se débarrasser plus tard des symboles inutiles. Si vous produisez un exécutable (par opposition à une bibliothèque partagée), il n'y a plus rien à faire.Plus d'informations (et une approche plus fine pour les bibliothèques par exemple) sont disponibles sur le wiki GCC .
la source
Extrait du manuel GCC 4.2.1, section
-fwhole-program
:la source
-flto
.Vous pouvez utiliser strip binary sur un fichier objet (ex. Exécutable) pour en retirer tous les symboles.
Remarque: il change le fichier lui-même et ne crée pas de copie.
la source