Cet article de blog est assez inexact.
Pour autant que je sache, les modifications de l'ABI C++ ont été introduites avec chaque version majeure de GCC (c'est-à-dire celles dont les composants ont un numéro de première ou de deuxième version différent).
C'est faux. Les seules modifications de l'ABI C++ introduites depuis GCC 3.4 ont été rétrocompatibles, ce qui signifie que l'ABI C++ est stable depuis près de neuf ans.
Pour aggraver les choses, la plupart des distributions Linux majeures utilisent des snapshots GCC et/ou patchent leurs versions de GCC, ce qui rend pratiquement impossible de savoir exactement quelles sont les versions de GCC auxquelles vous avez affaire lorsque vous distribuez des binaires.
Les différences entre les versions corrigées de GCC des distributions sont mineures et ne changent pas l'ABI. Par exemple, la version 4.6.3 20120306 de Fedora (Red Hat 4.6.3-2) est compatible avec l'ABI des versions 4.6.x en amont de la FSF et presque certainement avec toute version 4.6.x de n'importe quelle autre distribution.
Sous GNU/Linux, les bibliothèques d'exécution de GCC utilisent le versionnement des symboles ELF. Il est donc facile de vérifier les versions des symboles nécessaires aux objets et aux bibliothèques, et si vous avez un fichier libstdc++.so
qui fournit ces symboles, il fonctionnera, peu importe s'il s'agit d'une version patchée légèrement différente d'une autre version de votre distro.
mais aucun code C++ (ou tout code utilisant le support d'exécution C++) ne peut être lié dynamiquement pour que cela fonctionne.
Ce n'est pas vrai non plus.
Cela dit, l'établissement d'un lien statique vers libstdc++.a
est une option pour vous.
La raison pour laquelle cela pourrait ne pas fonctionner si vous chargez dynamiquement une bibliothèque (en utilisant dlopen
) est que les symboles de libstdc++ dont il dépend peuvent ne pas avoir été nécessaires à votre application lorsque vous l'avez liée (statiquement), donc ces symboles ne seront pas présents dans votre exécutable. Cela peut être résolu en liant dynamiquement la bibliothèque partagée à libstdc++.so
(ce qui est la bonne chose à faire de toute façon s'il en dépend). L'interposition des symboles ELF signifie que les symboles présents dans votre exécutable seront utilisés par la bibliothèque partagée, mais que les autres symboles non présents dans votre exécutable seront trouvés dans n'importe quelle bibliothèque partagée. libstdc++.so
vers lequel il renvoie. Si votre application n'utilise pas dlopen
tu n'as pas besoin de te soucier de ça.
Une autre option (et celle que je préfère) consiste à déployer la nouvelle version de la solution libstdc++.so
le long de votre application et s'assurer qu'elle est trouvée avant le système par défaut libstdc++.so
ce qui peut être fait en forçant l'éditeur de liens dynamiques à chercher au bon endroit, soit à l'aide de la fonction $LD_LIBRARY_PATH
au moment de l'exécution, ou en définissant une variable d'environnement RPATH
dans l'exécutable au moment de la liaison. Je préfère utiliser RPATH
car il n'est pas nécessaire que l'environnement soit correctement défini pour que l'application fonctionne. Si vous liez votre application avec '-Wl,-rpath,$ORIGIN'
(notez les guillemets simples pour empêcher l'interpréteur de commandes d'essayer de développer $ORIGIN
), alors l'exécutable aura un RPATH
de $ORIGIN
qui indique à l'éditeur de liens dynamiques de rechercher les bibliothèques partagées dans le même répertoire que l'exécutable lui-même. Si vous mettez le nouveau libstdc++.so
dans le même répertoire que l'exécutable, il sera trouvé au moment de l'exécution, problème résolu. (Une autre option consiste à placer l'exécutable dans le répertoire /some/path/bin/
et la plus récente libstdc++.so dans /some/path/lib/
et le lien avec '-Wl,-rpath,$ORIGIN/../lib'
ou tout autre emplacement fixe relatif à l'exécutable, et définir le RPATH relatif à $ORIGIN
)