Il y a un TL;DR à la fin si le contexte est trop important !
Contexte
J'essaie de mettre à jour la version de la glibc qu'utilise un projet vers la 2.23 (je sais qu'elle est ancienne, c'est un autre problème). Pour ce faire, j'ai besoin d'échanger les bibliothèques et d'utiliser l'interpréteur associé.
J'ai rencontré des problèmes lors du remplacement de l'interpréteur qui ressemblaient à un changement d'ABI, j'ai donc pensé que c'était probablement parce que les fichiers d'en-tête avaient changé d'une manière ou d'une autre et j'ai commencé à travailler sur l'inclusion de ces fichiers dans le projet.
J'ai d'abord essayé d'utiliser -I
pour inclure les en-têtes, mais il a obtenu une erreur (voir ci-dessous). Plus tard, j'ai essayé de définir --sysroot
mais cela m'a rapidement semblé être la mauvaise façon de faire puisque je réinventais essentiellement ce que g++ faisait déjà avec les en-têtes du système. Plus tard, j'ai trouvé un autre mécanisme qui semblait plus prometteur (voir la section Problème).
S'agit-il d'un Problème XY ? Absolument, mais quoi qu'il en soit, le problème que je vois me semble étrange.
Problème
J'ai cherché à savoir s'il existait un mécanisme différent pour inclure les en-têtes des bibliothèques système, telles que glibc, dans gcc et g++. J'ai trouvé le drapeau -isystem
:
-isystem dir Search dir for header files, after all directories specified by -I but before the standard system directories. Mark it as a system directory, so that it gets the same special treatment as is applied to the standard system directories. If dir begins with "=", then the "=" will be replaced by the sysroot prefix; see --sysroot and -isysroot.
Je me suis dit que c'était probablement ce que l'on voulait et j'ai commencé à intégrer ce drapeau dans le système de construction du projet. La commande g++ résultante ressemble à ceci (simplifiée et divisée en plusieurs lignes) :
> /path/to/gcc-6.3.0/bin/g++
-c
-Wl,--dynamic-linker=/path/to/glibc-2.23/build/install/lib/ld-linux-x86-64.so.2
-Wl,--rpath=/path/to/glibc-2.23/build/install/lib
-isystem /path/to/glibc-2.23/build/install/include
-I.
-I/project-foo/include
-I/project-bar/include
-o example.o
example.cpp
Cela conduit à l'erreur suivante, suivie de nombreuses autres similaires :
In file included from /usr/include/math.h:71:0,
from /path/to/gcc-6.3.0/include/c++/6.3.0/cmath:45,
from example.cpp:42:
/path/to/glibc-2.23/build/install/include/bits/mathcalls.h:63:16: error: expected constructor, destructor, or type conversion before '(' token
__MATHCALL_VEC (cos,, (_Mdouble_ __x));
En examinant la question, il apparaît que cette math.h
est incompatible avec cette version de la glibc. Le fait qu'il essaie de l'utiliser me surprend, parce que l'option math.h
existe dans le répertoire glibc que j'ai spécifié ; pourquoi ne l'a-t-il pas utilisé ? Voici comment j'ai vérifié l'existence de ce fichier :
> ls /path/to/glibc-2.23/build/install/include/math.h
/path/to/glibc-2.23/build/install/include/math.h
Recherche
J'ai cherché sur Internet des personnes ayant un problème similaire et je suis tombé sur les éléments suivants :
- https://github.com/riscv/riscv-gnu-toolchain/issues/105
- https://askubuntu.com/questions/806220/building-ucb-logo-6-errors-in-mathcalls-h
- L'option -isystem sur un répertoire d'inclusion du système provoque des erreurs.
Le dernier de ces points est le plus prometteur ; il explique pourquoi -isystem
ne fonctionnera pas dans ce cas, car l'article spécial de la loi sur les #include_next
traverse le chemin d'inclusion d'une manière différente. Ici, la solution semble être "ne pas utiliser -isystem
mais depuis que j'ai essayé d'utiliser le système -I
Je ne suis pas sûr de savoir comment appliquer ce principe ici.
Édition originale
Lors de la compilation avec la nouvelle glibc, j'obtiens l'erreur suivante (notre processus de compilation finit par exécuter certains des programmes qu'il compile pour générer d'autres sources à compiler, d'où cette erreur d'exécution lors de la compilation) :
Inconsistency detected by ld.so: get-dynamic-info.h: 143: elf_get_dynamic_info: Assertion `info[DT_RPATH] == NULL' failed!
J'ai trouvé quelques informations pertinentes à ce sujet :
- https://www.linuxquestions.org/questions/linux-software-2/how-to-get-local-gcc-to-link-with-local-glibc-404087/
- https://www.linuxquestions.org/questions/programming-9/inconsistency-detected-by-ld-so-dynamic-link-h-62-elf_get_dynamic_info-assertion-621701/
La seule solution que je vois est de recompiler complètement gcc pour utiliser la nouvelle glibc. J'aimerais éviter cela si possible, et c'est ce qui m'a conduit sur la voie de l'inclusion.
Élimination du système de construction complexe
Pour essayer d'éliminer le système de construction complexe sur le "vrai" projet, j'ai reproduit le problème en utilisant ce qui suit test.cpp
fichier :
#include <cmath>
int main() {
}
Compilé à l'aide de :
> /path/to/gcc-6.3.0/bin/g++ test.cpp -Wl,--dynamic-linker=/path/to/glibc-2.23/build/install/lib/ld-linux-x86-64.so.2 -Wl,--rpath=/path/to/glibc-2.23/build/install/lib
L'exécution du programme donne lieu au même problème initial :
> ./a.out
Inconsistency detected by ld.so: get-dynamic-info.h: 143: elf_get_dynamic_info: Assertion `info[DT_RPATH] == NULL' failed!
En essayant d'utiliser les nouveaux en-têtes, on obtient le même problème d'inclusion :
> /path/to/gcc-6.3.0/bin/g++ test.cpp -Wl,--dynamic-linker=/path/to/glibc-2.23/build/install/lib/ld-linux-x86-64.so.2 -Wl,--rpath=/path/to/glibc-2.23/build/install/lib -isystem /path/to/glibc-2.23/build/install/include
In file included from /usr/include/math.h:71:0,
from /path/to/gcc-6.3.0/include/c++/6.3.0/cmath:45,
from test.cpp:1:
/path/to/glibc-2.23/build/install/include/bits/mathcalls.h:63:16: error: expected constructor, destructor, or type conversion before '(' token
__MATHCALL_VEC (cos,, (_Mdouble_ __x));
TL;DR
Comment faire pour que g++ inclue correctement les en-têtes de ma glibc, sans qu'il n'inclue accidentellement des fichiers incompatibles de /usr/include ?