Plusieurs bibliothèques glibc sur un seul hôte


171

Plusieurs bibliothèques glibc sur un seul hôte

Mon serveur Linux (SLES-8) a actuellement glibc-2.2.5-235, mais j'ai un programme qui ne fonctionnera pas sur cette version et qui nécessite la glibc-2.3.3.

Est-il possible d'installer plusieurs glibcs ​​sur le même hôte?

Voici l'erreur que j'obtiens lorsque j'exécute mon programme sur l'ancienne glibc:

./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./myapp)
./myapp: /lib/i686/libpthread.so.0: version `GLIBC_2.3.2' not found (required by ./myapp)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libxerces-c.so.27)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)

J'ai donc créé un nouveau répertoire appelé newglibc et copié les fichiers suivants dans:

libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so

et

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

Mais j'obtiens une erreur:

./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libpthread.so.0)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by libstdc++.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libm.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./newglibc/libc.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libc.so.6)

Il semble donc qu'ils sont toujours liés à / lib et ne reprennent pas d'où je les ai placés?

Merci


1
même problème avec le serveur SLES-11. Impossible de mettre à jour et besoin d'éléments récents. oh my ...
UmNyobe

FWIW, export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH a résolu le problème pour moi! Cela ne fonctionnera certainement pas pour tout le monde, mais c'est une solution facile si cela fonctionne! Merci! :)
rinogo

Réponses:


229

Il est très possible d'avoir plusieurs versions de la glibc sur le même système (nous le faisons tous les jours).

Cependant, vous devez savoir que la glibc se compose de nombreux éléments (plus de 200 bibliothèques partagées) qui doivent tous correspondre. L'un des éléments est ld-linux.so.2, et il doit correspondre à libc.so.6, sinon vous verrez les erreurs que vous voyez.

Le chemin absolu vers ld-linux.so.2 est codé en dur dans l'exécutable au moment de la liaison, et ne peut pas être facilement modifié une fois la liaison établie.

Pour créer un exécutable qui fonctionnera avec la nouvelle glibc, procédez comme suit:

g++ main.o -o myapp ... \
   -Wl,--rpath=/path/to/newglibc \
   -Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

L' -rpathoption de l'éditeur de liens permettra au chargeur d'exécution de rechercher des bibliothèques dans /path/to/newglibc(vous n'aurez donc pas à définir LD_LIBRARY_PATHavant de l'exécuter), et l' -dynamic-linkeroption "bake" le chemin pour corriger ld-linux.so.2dans l'application.

Si vous ne pouvez pas relier l' myappapplication (par exemple parce qu'il s'agit d'un binaire tiers), tout n'est pas perdu, mais cela devient plus compliqué. Une solution consiste à définir un chrootenvironnement approprié pour cela. Une autre possibilité est d'utiliser rtldi et un éditeur binaire .


3
Notez que -Wl,--dynamic-linker=file(prend deux '-') ne fonctionne que lors de la compilation pour les exécutables ELF. Check/sbin/ldconfig -p | grep ld
Tom

49
Vous pouvez maintenant utiliser un utilitaire pratique patchelf( nixos.org/patchelf.html ), qui vous permet de modifier rpath et l'interpréteur d'ELF déjà compilé.
Michael Pankov

10
Il convient de mentionner que spécifier le chemin d'accès à la nouvelle glibc en utilisant -Wl,--rpathplutôt que LD_LIBRARY_PATHpeut être important pour des raisons autres que de commodité: si le programme lance des processus enfants, la valeur de LD_LIBRARY_PATHsera généralement héritée par eux, mais s'ils ne sont pas également compilés pour être utilisés la nouvelle glibc (par exemple, si ce sont des fichiers binaires comme bash), ils ne seront pas lancés.
HighCommander4

13
Une autre option consiste à exécuter directement le nouveau ld.so, en lui passant votre programme binaire comme paramètre; cela remplacera effectivement ld.so utilisé sans la nécessité de recompiler le programme:/path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
maximk


67

Cette question est ancienne, les autres réponses sont anciennes. La réponse de "Employed Russian" est très bonne et informative, mais elle ne fonctionne que si vous avez le code source. Si vous ne le faites pas, les alternatives à l'époque étaient très délicates. Heureusement, de nos jours, nous avons une solution simple à ce problème (comme commenté dans l'une de ses réponses), en utilisant patchelf . Tout ce que tu dois faire est:

$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 --set-rpath /path/to/newglibc/ myapp

Et après cela, vous pouvez simplement exécuter votre fichier:

$ ./myapp

Pas besoin de chrootmodifier manuellement les binaires, heureusement. Mais n'oubliez pas de sauvegarder votre binaire avant de le patcher, si vous n'êtes pas sûr de ce que vous faites, car cela modifie votre fichier binaire. Après l'avoir corrigé, vous ne pouvez pas restaurer l'ancien chemin vers interpreter / rpath. Si cela ne fonctionne pas, vous devrez continuer à le corriger jusqu'à ce que vous trouviez le chemin qui fonctionnera réellement ... Eh bien, il n'est pas nécessaire que ce soit un processus d'essai et d'erreur. Par exemple, dans l'exemple d'OP, il en avait besoin GLIBC_2.3, donc vous pouvez facilement trouver quelle bibliothèque fournit cette version en utilisant strings:

$ strings /lib/i686/libc.so.6 | grep GLIBC_2.3
$ strings /path/to/newglib/libc.so.6 | grep GLIBC_2.3

En théorie, le premier grep serait vide parce que la libc système n'a pas la version qu'il veut, et le deuxième devrait afficher GLIBC_2.3 parce qu'il a la version myapputilisée, donc nous savons que nous pouvons patchelfutiliser notre binaire en utilisant ce chemin.

Lorsque vous essayez d'exécuter un binaire sous Linux, le binaire essaie de charger l'éditeur de liens, puis les bibliothèques, et elles devraient toutes être dans le chemin et / ou au bon endroit. Si votre problème concerne l'éditeur de liens et que vous souhaitez savoir quel chemin votre binaire recherche, vous pouvez le découvrir avec cette commande:

$ readelf -l myapp | grep interpreter
  [Requesting program interpreter: /lib/ld-linux.so.2]                                                                                                                                                                                   

Si votre problème concerne les bibliothèques, les commandes qui vous donneront les bibliothèques utilisées sont:

$ readelf -d myapp | grep Shared
$ ldd myapp 

Cela listera les bibliothèques dont votre binaire a besoin, mais vous connaissez probablement déjà celles qui posent problème, car elles génèrent déjà des erreurs comme dans le cas d'OP.

"patchelf" fonctionne pour de nombreux problèmes différents que vous pouvez rencontrer en essayant d'exécuter un programme, liés à ces 2 problèmes. Par exemple, si vous obtenez:, ELF file OS ABI invalidcela peut être corrigé en définissant un nouveau chargeur (la --set-interpreterpartie de la commande) comme je l'explique ici . Un autre exemple concerne le problème d'obtention No such file or directorylorsque vous exécutez un fichier qui est là et exécutable, comme illustré ici . Dans ce cas particulier, OP manquait un lien vers le chargeur, mais peut-être que dans votre cas, vous n'avez pas d'accès root et ne pouvez pas créer le lien. La configuration d'un nouvel interprète résoudrait votre problème.

Merci Employed Russian et Michael Pankov pour la perspicacité et la solution!


1
C'était le plus utile! J'ai patché le binaire python pour utiliser la nouvelle glibc pour tensorflow
faizan

C'est une solution intéressante (je n'avais pas connu auparavant patchelf), mais la phrase "Pas besoin de ... modifier les binaires" peut être un peu trompeuse (puisque vous éditez en fait vos binaires).
larsks

Là, fixe. ;)
msb

Utilité vraiment utile! Je vous remercie! Bien que je n'ai réussi à obtenir une erreur de segmentation qu'après des heures de résolution manuelle des dépendances, puis de tout correctif pour installer localement chrome sans privilèges d'administrateur ...
G.Bergeron

@fgiraldeau merci pour le compliment. :) mais la question a été posée, répondue et acceptée en 2009, je ne m'attendrais pas à ce que quelqu'un attende 8 ans avant d'accepter une réponse. heheh; D
msb

20

Utilisez LD_PRELOAD: placez votre bibliothèque quelque part hors des répertoires man lib et exécutez:

LD_PRELOAD='mylibc.so anotherlib.so' program

Voir: l'article Wikipedia


1
pensait que ce serait une bonne solution de contournement pour un Makefile complexe, mais cela n'a pas fonctionné pour moi
galactica

c'est utile en particulier ceux qui n'ont pas de source binaire.Merci
codeur

2
euh ... je me suis trompé, il semble que j'ai besoin de rpath le ld-linux.so vers / path / to / new / lib / frist pendant la compilation et la liaison des sources
codeur

1
Cela ne fonctionne pas si ld - #. ##. So (de votre système glibc lib) n'est pas la même version glibc que libc.so. # (de votre alternative glibc lib)
Andy

12

Tout d'abord, la dépendance la plus importante de chaque programme lié dynamiquement est l'éditeur de liens. Toutes les bibliothèques doivent donc correspondre à la version de l'éditeur de liens.

Prenons un exemple simple: j'ai le système newset ubuntu où j'exécute un programme (dans mon cas, il s'agit du compilateur D - ldc2). J'aimerais l'exécuter sur l'ancien CentOS, mais à cause de l'ancienne bibliothèque glibc, c'est impossible. j'ai eu

ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)
ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)

Je dois copier toutes les dépendances d'ubuntu vers centos. La bonne méthode est la suivante:

Tout d'abord, vérifions toutes les dépendances:

ldd ldc2-1.5.0-linux-x86_64/bin/ldc2 
    linux-vdso.so.1 =>  (0x00007ffebad3f000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f965f597000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f965f378000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f965f15b000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f965ef57000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f965ec01000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f965e9ea000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f965e60a000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f965f79f000)

linux-vdso.so.1 n'est pas une vraie bibliothèque et nous n'avons pas à nous en soucier.

/lib64/ld-linux-x86-64.so.2 est l'éditeur de liens, qui est utilisé par le linux pour lier l'exécutable à toutes les bibliothèques dynamiques.

Le reste des fichiers sont de vraies bibliothèques et tous avec l'éditeur de liens doivent être copiés quelque part dans les centos.

Supposons que toutes les bibliothèques et l'éditeur de liens se trouvent dans le répertoire "/ mylibs".

ld-linux-x86-64.so.2 - comme je l'ai déjà dit - est l'éditeur de liens. Ce n'est pas une bibliothèque dynamique mais un exécutable statique. Vous pouvez l'exécuter et voir qu'il a même des paramètres, par exemple --library-path (je vais y revenir).

Sur Linux, un programme lié dynamiquement peut être déjeuné simplement par son nom, par exemple

/bin/ldc2

Linux charge ce programme dans la RAM et vérifie quel éditeur de liens est défini pour lui. Habituellement, sur un système 64 bits, il s'agit de /lib64/ld-linux-x86-64.so.2 (dans votre système de fichiers, il s'agit d'un lien symbolique vers l'exécutable réel). Ensuite, linux exécute l'éditeur de liens et charge les bibliothèques dynamiques.

Vous pouvez également changer cela un peu et faire une telle astuce:

/mylibs/ld-linux-x86-64.so.2 /bin/ldc2

C'est la méthode pour forcer le Linux à utiliser un éditeur de liens spécifique.

Et maintenant, nous pouvons revenir au paramètre mentionné précédemment --library-path

/mylibs/ld-linux-x86-64.so.2 --library-path /mylibs /bin/ldc2

Il exécutera ldc2 et chargera les bibliothèques dynamiques depuis / mylibs.

C'est la méthode pour appeler l'exécutable avec les bibliothèques choisies (pas par défaut du système).


J'ai compilé un programme sur RH7 et j'en ai besoin pour fonctionner sur RH6. Je ne voulais pas créer un nouvel exécutable ou utiliser patchelf, c'est donc une excellente alternative.
Mark Rajcok

9

Configuration 1: compilez votre propre glibc sans GCC dédié et utilisez-la

Cette configuration peut fonctionner et est rapide car elle ne recompile pas toute la chaîne d'outils GCC, juste la glibc.

Mais il n'est pas fiable car il utilise des objets d' exécution hôte C tels que crt1.o, crti.oet crtn.ofourni par la glibc. Ceci est mentionné sur: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Ces objets effectuent une configuration précoce sur laquelle la glibc s'appuie, donc je ne serais pas surpris si les choses se plantaient merveilleusement et des manières incroyablement subtiles.

Pour une configuration plus fiable, voir Configuration 2 ci-dessous.

Construisez la glibc et installez localement:

export glibc_install="$(pwd)/glibc/build/install"

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
mkdir build
cd build
../configure --prefix "$glibc_install"
make -j `nproc`
make install -j `nproc`

Configuration 1: vérifier la construction

test_glibc.c

#define _GNU_SOURCE
#include <assert.h>
#include <gnu/libc-version.h>
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>

atomic_int acnt;
int cnt;

int f(void* thr_data) {
    for(int n = 0; n < 1000; ++n) {
        ++cnt;
        ++acnt;
    }
    return 0;
}

int main(int argc, char **argv) {
    /* Basic library version check. */
    printf("gnu_get_libc_version() = %s\n", gnu_get_libc_version());

    /* Exercise thrd_create from -pthread,
     * which is not present in glibc 2.27 in Ubuntu 18.04.
     * /programming/56810/how-do-i-start-threads-in-plain-c/52453291#52453291 */
    thrd_t thr[10];
    for(int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for(int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);
    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}

Compilez et exécutez avec test_glibc.sh:

#!/usr/bin/env bash
set -eux
gcc \
  -L "${glibc_install}/lib" \
  -I "${glibc_install}/include" \
  -Wl,--rpath="${glibc_install}/lib" \
  -Wl,--dynamic-linker="${glibc_install}/lib/ld-linux-x86-64.so.2" \
  -std=c11 \
  -o test_glibc.out \
  -v \
  test_glibc.c \
  -pthread \
;
ldd ./test_glibc.out
./test_glibc.out

Le programme produit les résultats attendus:

gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674

Commande adaptée de https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location mais l'a --sysrootfait échouer avec:

cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install

alors je l'ai enlevé.

lddLa sortie confirme que les lddbibliothèques et que nous venons de créer sont en fait utilisées comme prévu:

+ ldd test_glibc.out
        linux-vdso.so.1 (0x00007ffe4bfd3000)
        libpthread.so.0 => /home/ciro/glibc/build/install/lib/libpthread.so.0 (0x00007fc12ed92000)
        libc.so.6 => /home/ciro/glibc/build/install/lib/libc.so.6 (0x00007fc12e9dc000)
        /home/ciro/glibc/build/install/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc12f1b3000)

La gccsortie de débogage de compilation montre que mes objets d'exécution hôte ont été utilisés, ce qui est mauvais comme mentionné précédemment, mais je ne sais pas comment contourner cela, par exemple, il contient:

COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o

Configuration 1: modifier la glibc

Modifions maintenant la glibc avec:

diff --git a/nptl/thrd_create.c b/nptl/thrd_create.c
index 113ba0d93e..b00f088abb 100644
--- a/nptl/thrd_create.c
+++ b/nptl/thrd_create.c
@@ -16,11 +16,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */

+#include <stdio.h>
+
 #include "thrd_priv.h"

 int
 thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
 {
+  puts("hacked");
   _Static_assert (sizeof (thr) == sizeof (pthread_t),
                   "sizeof (thr) != sizeof (pthread_t)");

Puis recompilez et réinstallez la glibc, puis recompilez et relancez notre programme:

cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh

et nous voyons hackedimprimé quelques fois comme prévu.

Cela confirme en outre que nous avons effectivement utilisé la glibc que nous avons compilée et non l'hôte.

Testé sur Ubuntu 18.04.

Configuration 2: configuration vierge du crosstool-NG

Ceci est une alternative à la configuration 1, et il est le plus correct configuration que j'ai accompli jusqu'à présent: tout est correct pour autant que je peux observer, y compris l'exécution de C des objets tels que crt1.o, crti.oetcrtn.o .

Dans cette configuration, nous compilerons une chaîne d'outils GCC dédiée complète qui utilise la glibc que nous voulons.

Le seul inconvénient de cette méthode est que la construction prendra plus de temps. Mais je ne risquerais pas une configuration de production avec rien de moins.

crosstool-NG est un ensemble de scripts qui télécharge et compile tout à partir de la source pour nous, y compris GCC, glibc et binutils.

Oui, le système de construction de GCC est si mauvais que nous avons besoin d'un projet séparé pour cela.

Cette configuration n'est pas parfaite car crosstool-NG ne prend pas en charge la construction des exécutables sans -Wldrapeaux supplémentaires , ce qui semble étrange puisque nous avons construit GCC lui-même. Mais tout semble fonctionner, ce n'est donc qu'un inconvénient.

Obtenez crosstool-NG, configurez-le et construisez-le:

git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
git checkout a6580b8e8b55345a5a342b5bd96e42c83e640ac5
export CT_PREFIX="$(pwd)/.build/install"
export PATH="/usr/lib/ccache:${PATH}"
./bootstrap
./configure --enable-local
make -j `nproc`
./ct-ng x86_64-unknown-linux-gnu
./ct-ng menuconfig
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

La construction prend environ trente minutes à deux heures.

La seule option de configuration obligatoire que je peux voir est de faire correspondre la version de votre noyau hôte pour utiliser les en-têtes de noyau corrects. Trouvez la version de votre noyau hôte avec:

uname -a

ce qui me montre:

4.15.0-34-generic

donc dans menuconfigje fais:

  • Operating System
    • Version of linux

donc je sélectionne:

4.14.71

qui est la première version égale ou antérieure. Il doit être plus ancien car le noyau est rétrocompatible.

Configuration 2: configurations optionnelles

Le .configque nous avons généré avec ./ct-ng x86_64-unknown-linux-gnua:

CT_GLIBC_V_2_27=y

Pour changer cela, menuconfigfaites:

  • C-library
  • Version of glibc

sauver le .config et poursuivez la construction.

Ou, si vous souhaitez utiliser votre propre source glibc, par exemple pour utiliser la glibc à partir du dernier git, procédez comme suit :

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: défini sur true
  • C-library
    • Source of glibc
      • Custom location: dis oui
      • Custom location
        • Custom source location: pointez sur un répertoire contenant votre source glibc

où la glibc a été clonée comme:

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28

Configuration 2: testez-le

Une fois que vous avez construit la chaîne d'outils que vous souhaitez, testez-la avec:

#!/usr/bin/env bash
set -eux
install_dir="${CT_PREFIX}/x86_64-unknown-linux-gnu"
PATH="${PATH}:${install_dir}/bin" \
  x86_64-unknown-linux-gnu-gcc \
  -Wl,--dynamic-linker="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2" \
  -Wl,--rpath="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib" \
  -v \
  -o test_glibc.out \
  test_glibc.c \
  -pthread \
;
ldd test_glibc.out
./test_glibc.out

Tout semble fonctionner comme dans la configuration 1, sauf que maintenant les objets d'exécution corrects ont été utilisés:

COLLECT_GCC_OPTIONS=/home/ciro/crosstool-ng/.build/install/x86_64-unknown-linux-gnu/bin/../x86_64-unknown-linux-gnu/sysroot/usr/lib/../lib64/crt1.o

Configuration 2: échec de la tentative de recompilation efficace de la glibc

Cela ne semble pas possible avec le crosstool-NG, comme expliqué ci-dessous.

Si vous venez de reconstruire;

env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

alors vos modifications apportées à l'emplacement de la source glibc personnalisée sont prises en compte, mais il construit tout à partir de zéro, le rendant inutilisable pour le développement itératif.

Si nous faisons:

./ct-ng list-steps

cela donne un bon aperçu des étapes de construction:

Available build steps, in order:
  - companion_tools_for_build
  - companion_libs_for_build
  - binutils_for_build
  - companion_tools_for_host
  - companion_libs_for_host
  - binutils_for_host
  - cc_core_pass_1
  - kernel_headers
  - libc_start_files
  - cc_core_pass_2
  - libc
  - cc_for_build
  - cc_for_host
  - libc_post_cc
  - companion_libs_for_target
  - binutils_for_target
  - debug
  - test_suite
  - finish
Use "<step>" as action to execute only that step.
Use "+<step>" as action to execute up to that step.
Use "<step>+" as action to execute from that step onward.

par conséquent, nous voyons qu'il y a des étapes de la glibc entrelacées avec plusieurs étapes GCC, notamment libc_start_filesvient avant cc_core_pass_2, ce qui est probablement l'étape la plus coûteuse aveccc_core_pass_1 .

Afin de ne construire qu'une seule étape, vous devez d'abord définir l' .configoption "Enregistrer les étapes intermédiaires" dans l' option pour la construction initiale:

  • Paths and misc options
    • Debug crosstool-NG
      • Save intermediate steps

et ensuite vous pouvez essayer:

env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`

mais malheureusement, le +requis comme mentionné à: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536

Notez cependant que le redémarrage à une étape intermédiaire réinitialise le répertoire d'installation à l'état qu'il avait lors de cette étape. Par exemple, vous aurez une libc reconstruite - mais pas de compilateur final construit avec cette libc (et par conséquent, pas de bibliothèques de compilateurs comme libstdc ++ non plus).

et rend fondamentalement encore la reconstruction trop lente pour être faisable pour le développement, et je ne vois pas comment surmonter cela sans patcher crosstool-NG.

De plus, à partir de l' libcétape ne semblait pas recopier la source Custom source location, ce qui rendait cette méthode inutilisable.

Bonus: stdlibc ++

Un bonus si vous êtes également intéressé par la bibliothèque standard C ++: Comment éditer et reconstruire la source de la bibliothèque standard C ++ libstdc ++ de GCC?


6

Pouvez-vous envisager d'utiliser Nix http://nixos.org/nix/ ?

Nix prend en charge la gestion des packages multi-utilisateurs: plusieurs utilisateurs peuvent partager un magasin Nix commun en toute sécurité, n'ont pas besoin de privilèges root pour installer un logiciel, et peuvent installer et utiliser différentes versions d'un package.


4

@msb donne une solution sûre.

J'ai rencontré ce problème lorsque je l'ai fait import tensorflow as tfdans un environnement conda dans CentOS 6.5lequel seulement glibc-2.12.

ImportError: /lib64/libc.so.6: version `GLIBC_2.16' not found (required by /home/

Je souhaite fournir quelques détails:

Installez d'abord glibcdans votre répertoire personnel:

mkdir ~/glibc-install; cd ~/glibc-install
wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz
tar -zxvf glibc-2.17.tar.gz
cd glibc-2.17
mkdir build
cd build
../configure --prefix=/home/myself/opt/glibc-2.17  # <-- where you install new glibc
make -j<number of CPU Cores>  # You can find your <number of CPU Cores> by using **nproc** command
make install

Deuxièmement, suivez la même méthode pour installer patchelf ;

Troisièmement, corrigez votre Python:

[myself@nfkd ~]$ patchelf --set-interpreter /home/myself/opt/glibc-2.17/lib/ld-linux-x86-64.so.2 --set-rpath /home/myself/opt/glibc-2.17/lib/ /home/myself/miniconda3/envs/tensorflow/bin/python

comme mentionné par @msb

Maintenant je peux utiliser tensorflow-2.0 alphadansCentOS 6.5 .

réf: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/


2

Je ne suis pas sûr que la question soit toujours d'actualité, mais il existe un autre moyen de résoudre le problème: Docker. On peut installer un conteneur presque vide de la distribution source (la distribution utilisée pour le développement) et copier les fichiers dans le conteneur. De cette façon, vous n'avez pas besoin de créer le système de fichiers nécessaire au chroot.


1

Si vous regardez attentivement la deuxième sortie, vous pouvez voir que le nouvel emplacement des bibliothèques est utilisé. Peut-être qu'il manque encore des bibliothèques faisant partie de la glibc.

Je pense également que toutes les bibliothèques utilisées par votre programme devraient être compilées avec cette version de la glibc. Si vous avez accès au code source du programme, une nouvelle compilation semble être la meilleure solution.


1

"Employé russe" est l'une des meilleures réponses, et je pense que toutes les autres réponses suggérées peuvent ne pas fonctionner. La raison en est simplement que lorsqu'une application est créée pour la première fois, toutes les API dont elle a besoin sont résolues au moment de la compilation. En utilisant "ldd", vous pouvez voir toutes les dépendances liées statiquement:

ldd /usr/lib/firefox/firefox
    linux-vdso.so.1 =>  (0x00007ffd5c5f0000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f727e708000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f727e500000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f727e1f8000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f727def0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f727db28000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f727eb78000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f727d910000)

Mais au moment de l'exécution, Firefox chargera également de nombreuses autres bibliothèques dynamiques, par exemple (pour Firefox) il y a beaucoup de bibliothèques étiquetées "glib" chargées (même s'il n'y en a pas de lien statique):

 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2
 /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0
 /usr/lib/x86_64-linux-gnu/libavahi-glib.so.1.0.2

Plusieurs fois, vous pouvez voir les noms d'une version liée à une autre version. Par exemple:

lrwxrwxrwx 1 root root     23 Dec 21  2014 libdbus-glib-1.so.2 -> libdbus-glib-1.so.2.2.2
-rw-r--r-- 1 root root 160832 Mar  1  2013 libdbus-glib-1.so.2.2.2

Cela signifie donc que différentes versions de "bibliothèques" existent dans un système - ce qui n'est pas un problème car il s'agit du même fichier, et cela fournira des compatibilités lorsque les applications ont plusieurs dépendances de versions.

Par conséquent, au niveau du système, toutes les bibliothèques sont presque interdépendantes les unes des autres, et le simple fait de changer la priorité de chargement des bibliothèques en manipulant LD_PRELOAD ou LD_LIBRARY_PATH n'aidera pas - même si elle peut se charger, elle risque toujours de planter.

http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc

La meilleure alternative est chroot (brièvement mentionnée par ER): mais pour cela, vous devrez recréer tout l'environnement dans lequel se trouve l'exécutable binaire d'origine - généralement à partir de / lib, / usr / lib /, / usr / lib / x86 etc. Vous pouvez soit utiliser "Buildroot", soit YoctoProject, soit simplement tar depuis un environnement Distro existant. (comme Fedora / Suse, etc.).


0

Quand je voulais lancer un navigateur chrome sur Ubuntu précis (glibc-2.15), j'ai reçu le message (typique) "... libc.so.6: version` GLIBC_2.19 'not found ... ". J'ai pris en compte le fait que les fichiers ne sont pas nécessaires en permanence, mais uniquement pour commencer. J'ai donc rassemblé les fichiers nécessaires pour le navigateur et sudo et créé un environnement mini-glibc-2.19-, démarré le navigateur, puis copié à nouveau les fichiers d'origine. Les fichiers nécessaires sont dans la RAM et la glibc d'origine est la même.

as root
the files (*-2.15.so) already exist 

mkdir -p /glibc-2.19/i386-linux-gnu

/glibc-2.19/ld-linux.so.2 -> /glibc-2.19/i386-linux-gnu/ld-2.19.so
/glibc-2.19/i386-linux-gnu/libc.so.6 -> libc-2.19.so
/glibc-2.19/i386-linux-gnu/libdl.so.2 -> libdl-2.19.so
/glibc-2.19/i386-linux-gnu/libpthread.so.0 -> libpthread-2.19.so

mkdir -p /glibc-2.15/i386-linux-gnu

/glibc-2.15/ld-linux.so.2 -> (/glibc-2.15/i386-linux-gnu/ld-2.15.so)
/glibc-2.15/i386-linux-gnu/libc.so.6 -> (libc-2.15.so)
/glibc-2.15/i386-linux-gnu/libdl.so.2 -> (libdl-2.15.so)
/glibc-2.15/i386-linux-gnu/libpthread.so.0 -> (libpthread-2.15.so)

le script pour exécuter le navigateur:

#!/bin/sh
sudo cp -r /glibc-2.19/* /lib
/path/to/the/browser &
sleep 1
sudo cp -r /glibc-2.15/* /lib
sudo rm -r /lib/i386-linux-gnu/*-2.19.so
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.