2 votes

Comment faire en sorte que g++ utilise correctement les en-têtes de ma propre version de la glibc ?

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 :

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 :

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 ?

1voto

Florian Weimer Points 15524

Dans votre version de GCC, <cmath> utilise #include_next ce qui signifie que vous devez vous assurer que le répertoire qui contient le fichier cmath le dossier arrive avant (sur le chemin de recherche de l'inclusion) le répertoire contenant le code math.h pour la version de la glibc avec laquelle vous construisez.

Vous pouvez utiliser g++ -v pour afficher le chemin de recherche. Dans votre cas, il ressemble probablement à ceci :

#include "..." search starts here:
#include <...> search starts here:
 .
 /project-foo/include
 /project-bar/include
 /path/to/glibc-2.23/build/install/include
 /usr/include/c++/6
 /usr/include/x86_64-linux-gnu/c++/6
 /usr/lib/gcc/x86_64-linux-gnu/6/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include

Si vous configurez la glibc avec --prefix=/usr et l'installer avec DESTDIR=/path/to/glibc-2.23/build/install ses fichiers d'en-tête seront installés dans le répertoire /path/to/glibc-2.23/build/install/usr/include . Cela signifie que vous devriez être en mesure d'utiliser le -isysroot qui réécrit la valeur par défaut de l'option /usr/include ce qui permet d'ordonner correctement le chemin de recherche :

#include "..." search starts here:
#include <...> search starts here:
 .
 /project-foo/include
 /project-bar/include
 /usr/include/c++/6
 /usr/include/x86_64-linux-gnu/c++/6
 /usr/include/c++/6/backward
 /usr/lib/gcc/x86_64-linux-gnu/6/include
 /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
 /path/to/glibc-2.23/build/install/usr/include

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X