Несколько библиотек glibc на одном хосте

На моем сервере linux (SLES-8) сейчас есть glibc-2.2.5-235, но у меня есть программа, которая не будет работать с этой версией и требует glibc-2.3.3.

Возможно ли установить несколько glibc на одном хосте?

Это ошибка, которую я получаю, когда запускаю свою программу на старом 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)

Итак, я создал новый каталог с именем newglibc и скопировал в него следующие файлы:

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

а также

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

Но получаю ошибку:

./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)

Таким образом, похоже, что они все еще ссылаются на /lib и не получают информацию с того места, где я их разместил.


person dogbane    schedule 11.05.2009    source источник
comment
такая же проблема с сервером SLES-11. Не могу обновить и нужны последние данные. о мой ...   -  person UmNyobe    schedule 14.09.2012
comment
FWIW, export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH действительно решил проблему для меня! Конечно, это не сработает для всех, но это легко исправить, если это сработает! Спасибо! :)   -  person rinogo    schedule 30.06.2017


Ответы (11)


Очень возможно иметь несколько версий glibc в одной системе (мы делаем это каждый день).

Однако вам нужно знать, что glibc состоит из множества частей (более 200 разделяемых библиотек), которые все должны совпадать. Одна из частей - ld-linux.so.2, и она должна соответствовать libc.so.6, иначе вы увидите ошибки, которые видите.

Абсолютный путь к ld-linux.so.2 жестко запрограммирован в исполняемый файл во время ссылки и не может быть легко изменен после создания ссылки (обновление: можно выполнить с помощью patchelf; см. этот ответ ниже).

Чтобы создать исполняемый файл, который будет работать с новым glibc, сделайте следующее:

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

Параметр компоновщика -rpath заставит загрузчик времени выполнения искать библиотеки в /path/to/newglibc (так что вам не нужно будет устанавливать LD_LIBRARY_PATH перед его запуском), а параметр -dynamic-linker запечет путь для исправления ld-linux.so.2 в приложение.

Если вы не можете повторно связать приложение myapp (например, потому что это сторонний двоичный файл), не все потеряно, но становится сложнее. Одно из решений - установить для него подходящую chroot среду. Другая возможность - использовать rtldi и двоичный редактор. Обновление: или вы можете использовать patchelf.

person Employed Russian    schedule 12.05.2009
comment
Обратите внимание, что -Wl,--dynamic-linker=file (занимает два '-') работает только при компиляции для исполняемых файлов ELF. Проверить /sbin/ldconfig -p | grep ld - person Tom; 28.05.2012
comment
Теперь вы можете использовать удобную утилиту patchelf (nixos.org/patchelf.html), которая позволяет изменить rpath и интерпретатор уже скомпилированного ELF. - person Michael Pankov; 13.02.2013
comment
Стоит упомянуть, что указание пути к новому glibc с использованием -Wl,--rpath, а не LD_LIBRARY_PATH может быть важно по причинам, не связанным с удобством: если программа запускает дочерние процессы, значение LD_LIBRARY_PATH обычно наследуется ими, но если они не также скомпилированы для использования более новой glibc (например, если это стандартные двоичные файлы, такие как bash), они не запускаются. - person HighCommander4; 05.06.2016
comment
Другой вариант - запустить новый ld.so напрямую, передав ему вашу двоичную программу в качестве параметра; это эффективно заменит ld.so, используемый без необходимости перекомпилировать программу: /path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp - person maximk; 14.09.2016
comment
Мне также понадобились -I и -L: stackoverflow.com/a/52454603/895245 - person Ciro Santilli 新疆再教育营六四事件ۍ 22.09.2018
comment
Как скачать и использовать glibc? Должен ли я скачать RPM и распаковать его, или мне нужно собрать его локально? Мне трудно ответить на эти вопросы - person Santosh Kale; 19.01.2021
comment
@SantoshKale Для параллельной установки необходимо configure --prefix /new/location и make && make install. Готовые RPM не будут работать. - person Employed Russian; 19.01.2021

Этот вопрос старый, другие ответы старые. Ответ трудоустроенных россиян очень хороший и информативный, но он работает, только если у вас есть исходный код. Если вы этого не сделаете, тогда альтернативы были очень сложными. К счастью, в настоящее время у нас есть простое решение этой проблемы (как указано в одном из его ответов), используя patchelf. Все, что вам нужно сделать, это:

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

И после этого вы можете просто запустить свой файл:

$ ./myapp

К счастью, не нужно chroot или вручную редактировать двоичные файлы. Но не забудьте сделать резервную копию вашего двоичного файла перед его исправлением, если вы не уверены, что делаете, потому что это изменяет ваш двоичный файл. После того, как вы его исправите, вы не сможете восстановить старый путь к интерпретатору / rpath. Если это не сработает, вам придется продолжать исправлять его, пока вы не найдете путь, который действительно будет работать ... Что ж, это не обязательно должен быть процесс проб и ошибок. Например, в примере OP ему нужен GLIBC_2.3, поэтому вы можете легко найти, какая библиотека предоставляет эту версию, используя strings:

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

Теоретически первый grep будет пустым, потому что у системной libc нет нужной ему версии, а второй должен вывести GLIBC_2.3, потому что он имеет версию, которую использует myapp, поэтому мы знаем, что можем patchelf использовать этот двоичный файл. дорожка. Если вы получили ошибку сегментации, прочтите примечание в конце.

Когда вы пытаетесь запустить двоичный файл в Linux, двоичный файл пытается загрузить компоновщик, а затем библиотеки, и все они должны быть в пути и / или в нужном месте. Если ваша проблема связана с компоновщиком, и вы хотите узнать, какой путь ищет ваш двоичный файл, вы можете узнать это с помощью этой команды:

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

Если ваша проблема связана с библиотеками, команды, которые предоставят вам используемые библиотеки:

$ readelf -d myapp | grep Shared
$ ldd myapp 

Это перечислит библиотеки, которые нужны вашему двоичному файлу, но вы, вероятно, уже знаете проблемные, поскольку они уже вызывают ошибки, как в случае OP.

patchelf работает для множества различных проблем, с которыми вы можете столкнуться при попытке запустить программу, связанных с этими двумя проблемами. Например, если вы получили: ELF file OS ABI invalid, это можно исправить, установив новый загрузчик (часть --set-interpreter команды), как я объясняю здесь. Другой пример - проблема получения No such file or directory при запуске файла, который есть и исполняемый, как показано на примере здесь. В этом конкретном случае OP отсутствовала ссылка на загрузчик, но, возможно, в вашем случае у вас нет root-доступа и вы не можете создать ссылку. Установка нового интерпретатора решит вашу проблему.

Спасибо Employed Russian и Михаилу Панкову за понимание и решение!


Примечание для ошибки сегментации: вы можете оказаться в том случае, когда myapp использует несколько библиотек, и большинство из них в порядке, а некоторые - нет; затем вы patchelf его в новый каталог и получаете ошибку сегментации. Когда вы patchelf свой двоичный файл, вы меняете путь к нескольким библиотекам, даже если некоторые из них изначально находились на другом пути. Взгляните на мой пример ниже:

$ ldd myapp
./myapp: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by ./myapp)
./myapp: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./myapp)
        linux-vdso.so.1 =>  (0x00007fffb167c000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9a9aad2000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9a9a8ce000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9a9a6af000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9a9a3ab000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9a99fe6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f9a9adeb000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9a99dcf000)

Обратите внимание, что большинство библиотек находятся в /lib/x86_64-linux-gnu/, но проблемная (libstdc++.so.6) находится в /usr/lib/x86_64-linux-gnu. После того, как я исправил myapp, чтобы указать на /path/to/mylibs, у меня возникла ошибка сегментации. По какой-то причине библиотеки не полностью совместимы с двоичным файлом. Поскольку myapp не жаловался на исходные библиотеки, я скопировал их с /lib/x86_64-linux-gnu/ на /path/to/mylibs2, а также скопировал libstdc++.so.6 с /path/to/mylibs. Затем я пропатчил его до /path/to/mylibs2, и myapp теперь работает. Если ваш двоичный файл использует разные библиотеки и у вас разные версии, может случиться так, что вы не сможете исправить свою ситуацию. :( Но если это возможно, смешайте библиотеки. Это не идеально, но возможно сработает. Удачи!

person msb    schedule 22.06.2017
comment
Это было самым полезным! Я пропатчил двоичный файл python, чтобы использовать новый glibc для тензорного потока - person faizan; 22.07.2017
comment
Это изящное решение (я раньше не знал о patchelf), но фраза Нет необходимости ... редактировать двоичные файлы может немного ввести в заблуждение (поскольку вы фактически редактируете свои двоичные файлы). - person larsks; 04.12.2017
comment
Там исправлено. ;) - person msb; 04.12.2017
comment
Действительно полезная утилита! Спасибо! Хотя мне удалось получить ошибку сегментации только после нескольких часов ручного разрешения зависимостей, а затем исправления всего, чтобы локально установить хром без прав администратора ... - person G. Bergeron; 06.06.2018
comment
@fgiraldeau спасибо за комплимент. :) но вопрос был задан, ответил и принят в 2009 году, я бы не ожидал, что кто-то будет ждать 8 лет, прежде чем принять ответ. хе-хе; D - person msb; 22.09.2018
comment
привет, по иронии судьбы я получаю ./patchelf: /lib64/libstdc++.so.6: version GLIBCXX_3.4.21 'not found (требуется ./patchelf) `Я думаю, что проверю другое решение - person Welgriv; 14.03.2019
comment
Страница patchelf указывает на исходный код по адресу github.com/NixOS/patchelf, поэтому теоретически вы можете скомпилируйте его в своей системе ... но это может вызвать собственный набор проблем. ржу не могу :( - person msb; 28.05.2019
comment
@Welgriv, вам нужно сделать это на компьютере, на котором вы скомпилировали как patchelf, так и ваше приложение. Позже этот перенос на другой компьютер. - person bbruno5; 18.09.2019
comment
Я наконец нашел это. ^ _ ^ - person coolder; 06.11.2020

Используйте LD_PRELOAD: поместите свою библиотеку где-нибудь из каталогов man lib и запустите:

LD_PRELOAD='mylibc.so anotherlib.so' program

См. статью в Википедии

person PiedPiper    schedule 11.05.2009
comment
подумал, что это будет хороший обходной путь для сложного Makefile, но у меня это не сработало - person galactica; 23.05.2017
comment
это особенно полезно для тех, у кого нет исходного двоичного кода. спасибо - person coder; 06.08.2017
comment
гм ... я был неправ, похоже, мне нужен rpath ld-linux.so к / path / to / new / lib / frist, пока исходный код компилируется и компоновка - person coder; 06.08.2017
comment
Это не работает, если ld - #. ##. So (из вашей системной библиотеки glibc) не совпадает с версией glibc, что и libc.so. # (из вашей альтернативной библиотеки glibc) - person Andy; 14.08.2019

Прежде всего, наиболее важной зависимостью каждой динамически связанной программы является компоновщик. Все так библиотеки должны соответствовать версии компоновщика.

Возьмем простой пример: у меня есть система newset ubuntu, в которой я запускаю какую-то программу (в моем случае это компилятор D - ldc2). Я бы хотел запустить его на старой CentOS, но из-за старой библиотеки glibc это невозможно. я получил

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)

Мне нужно скопировать все зависимости с ubuntu на centos. Правильный метод следующий:

Сначала проверим все зависимости:

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 - это не настоящая библиотека, и нам не нужно о ней заботиться.

/lib64/ld-linux-x86-64.so.2 - это компоновщик, который используется Linux и связывает исполняемый файл со всеми динамическими библиотеками.

Остальные файлы являются настоящими библиотеками, и все они вместе с компоновщиком должны быть скопированы где-нибудь в centos.

Предположим, что все библиотеки и компоновщик находятся в каталоге «/ mylibs».

ld-linux-x86-64.so.2, как я уже сказал, является компоновщиком. Это не динамическая библиотека, а статический исполняемый файл. Вы можете запустить его и увидеть, что у него даже есть некоторые параметры, например --library-path (я вернусь к нему).

В Linux динамически скомпонованная программа может запускаться только по ее имени, например

/bin/ldc2

Linux загружает такую ​​программу в оперативную память и проверяет, какой компоновщик для нее установлен. Обычно в 64-битной системе это /lib64/ld-linux-x86-64.so.2 (в вашей файловой системе это символическая ссылка на реальный исполняемый файл). Затем Linux запускает компоновщик и загружает динамические библиотеки.

Вы также можете немного изменить это и проделать такой трюк:

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

Это метод принуждения Linux к использованию определенного компоновщика.

А теперь мы можем вернуться к упомянутому ранее параметру --library-path

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

Он запустит ldc2 и загрузит динамические библиотеки из / mylibs.

Это метод вызова исполняемого файла с выбранными (не системными по умолчанию) библиотеками.

person Arkadiusz Rychliński    schedule 04.11.2017
comment
Я скомпилировал программу на RH7, и мне нужно, чтобы она работала на RH6. Я не хотел создавать новый исполняемый файл или использовать patchelf, так что это отличная альтернатива. - person Mark Rajcok; 22.01.2018
comment
Попытка использовать этот подход для компиляции mongo db v4 с настраиваемым gcc 5.3 на debian jessie, но получить ошибку сегментации, запускающую компоновщик прямо здесь: stackoverflow.com/questions/65256105/ не могли бы вы помочь ? - person Boris Rybalkin; 27.12.2020

Настройка 1: скомпилируйте свой собственный glibc без выделенного GCC и используйте его

Эта установка может работать и выполняется быстро, поскольку она не перекомпилирует всю цепочку инструментов GCC, а только glibc.

Но это ненадежно, так как он использует объекты среды выполнения C, такие как crt1.o, crti.o и crtn.o, предоставленные glibc. Это упоминается по адресу: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Эти объекты выполняют раннюю настройку, на которую полагается glibc, поэтому я не удивлюсь, если что-то выйдет из строя чудесным и удивительно тонким образом.

Для более надежной настройки см. Настройка 2 ниже.

Скомпилируйте glibc и установите локально:

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`

Настройка 1: проверьте сборку

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.
     * https://stackoverflow.com/questions/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);
}

Скомпилируйте и запустите с 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

Программа выводит ожидаемые:

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

Команда адаптирована из https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location, но --sysroot завершился ошибкой:

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

поэтому я удалил это.

ldd вывод подтверждает, что ldd и библиотеки, которые мы только что создали, действительно используются должным образом:

+ 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)

Выходные данные отладки компиляции gcc показывают, что использовались объекты среды выполнения моего хоста, что, как упоминалось ранее, плохо, но я не знаю, как обойти это, например это содержит:

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

Настройка 1: изменить glibc

Теперь давайте изменим glibc с помощью:

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)");

Затем перекомпилируйте и переустановите glibc, перекомпилируйте и повторно запустите нашу программу:

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

и мы видим, что hacked напечатано несколько раз, как и ожидалось.

Это еще раз подтверждает, что мы действительно использовали скомпилированную glibc, а не хост.

Проверено на Ubuntu 18.04.

Настройка 2: первоначальная настройка кросс-стула-NG

Это альтернатива настройке 1, и это наиболее правильная настройка, которую я когда-либо достиг: насколько я могу судить, все правильно, включая объекты времени выполнения C, такие как crt1.o, crti.o и crtn.o.

В этой настройке мы скомпилируем полную специализированную цепочку инструментов GCC, которая использует glibc, который нам нужен.

Единственным недостатком этого метода является то, что сборка займет больше времени. Но я бы не стал рисковать производственной установкой на меньшее.

crossstool-NG - это набор скриптов, который загружает и компилирует для нас все из исходного кода, включая GCC, glibc и binutils.

Да, система сборки GCC настолько плоха, что нам нужен отдельный проект для этого.

Эта установка не идеальна только потому, что crossstool-NG не поддерживает сборку исполняемых файлов без дополнительных -Wl flags, что кажется странным, поскольку мы создали сам GCC. Но вроде все работает, так что это только неудобства.

Получите crossstool-NG, настройте и соберите его:

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`

Сборка занимает от тридцати минут до двух часов.

Единственная обязательная опция конфигурации, которую я вижу, - это согласование версии ядра вашего хоста для использования правильных заголовков ядра. Найдите версию ядра вашего хоста с помощью:

uname -a

который показывает мне:

4.15.0-34-generic

so in menuconfig I do:

  • Operating System
    • Version of linux

поэтому я выбираю:

4.14.71

которая является первой равной или более старой версией. Он должен быть старше, поскольку ядро ​​обратно совместимо.

Настройка 2: дополнительные конфигурации

.config, который мы создали с помощью ./ct-ng x86_64-unknown-linux-gnu, имеет:

CT_GLIBC_V_2_27=y

Чтобы изменить это, в menuconfig выполните:

  • C-library
  • Version of glibc

сохраните .config и продолжите сборку.

Или, если вы хотите использовать свой собственный источник glibc, например чтобы использовать glibc из последней версии git, выполните вот так:

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: set to true
  • C-library
    • Source of glibc
      • Custom location: say yes
      • Custom location
        • Custom source location: point to a directory containing your glibc source

где glibc был клонирован как:

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

Настройка 2: проверьте это

После того, как вы создали нужный набор инструментов, протестируйте его с помощью:

#!/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

Кажется, все работает как в настройке 1, за исключением того, что теперь использовались правильные объекты среды выполнения:

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

Установка 2: неудачная попытка эффективной перекомпиляции glibc

Как поясняется ниже, это невозможно с crossstool-NG.

Если вы просто перестроите;

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

тогда ваши изменения в пользовательском местоположении исходного кода glibc учитываются, но он строит все с нуля, что делает его непригодным для итеративной разработки.

If we do:

./ct-ng list-steps

он дает хороший обзор этапов сборки:

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.

поэтому мы видим, что есть шаги glibc, переплетенные с несколькими шагами GCC, в первую очередь libc_start_files предшествует cc_core_pass_2, что, вероятно, является самым дорогостоящим шагом вместе с cc_core_pass_1.

Чтобы построить только один шаг, вы должны сначала установить параметр «Сохранить промежуточные шаги» в .config опции для начальной сборки:

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

а затем вы можете попробовать:

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

но, к сожалению, требуется +, как указано на странице: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536.

Однако обратите внимание, что перезапуск на промежуточном этапе сбрасывает каталог установки до состояния, которое было на этом этапе. То есть у вас будет перестроенная библиотека libc, но не будет финального компилятора, построенного с этой libc (и, следовательно, нет библиотек компилятора, таких как libstdc ++).

и, по сути, по-прежнему делает перестройку слишком медленной, чтобы ее можно было реализовать в разработке, и я не вижу, как это преодолеть без исправления crossstool-NG.

Более того, начиная с шага libc, похоже, не происходило повторного копирования источника из Custom source location, что еще больше сделало этот метод непригодным для использования.

Бонус: stdlibc ++

Бонус, если вас также интересует стандартная библиотека C ++: Как отредактировать и пересобрать исходный код стандартной библиотеки GCC libstdc ++ C ++?

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 22.09.2018

Можете ли вы рассмотреть возможность использования Nix http://nixos.org/nix/?

Nix поддерживает многопользовательское управление пакетами: несколько пользователей могут безопасно пользоваться общим хранилищем Nix, им не нужны привилегии root для установки программного обеспечения, и они могут устанавливать и использовать разные версии пакета.

person Community    schedule 31.08.2014

@msb дает безопасное решение.

Я столкнулся с этой проблемой, когда делал import tensorflow as tf в среде conda в CentOS 6.5, где есть только glibc-2.12.

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

Я хочу сообщить некоторые подробности:

Сначала установите glibc в свой домашний каталог:

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

Во-вторых, следуйте тому же самому способу установки patchelf;

В-третьих, исправьте свой 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

как упомянуто @msb

Теперь я могу использовать tensorflow-2.0 alpha в CentOS 6.5.

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

person Belter    schedule 13.04.2019

Не уверен, что вопрос по-прежнему актуален, но есть другой способ решить проблему: Docker. Можно установить почти пустой контейнер Source Distribution (Дистрибутив, используемый для разработки) и скопировать файлы в Контейнер. Таким образом, вам не нужно создавать файловую систему, необходимую для chroot.

person user1396055    schedule 19.07.2018

Если вы внимательно посмотрите на второй результат, вы увидите, что используется новое расположение библиотек. Возможно, все еще отсутствуют библиотеки, которые являются частью glibc.

Я также считаю, что все библиотеки, используемые вашей программой, должны быть скомпилированы для этой версии glibc. Если у вас есть доступ к исходному коду программы, новая компиляция будет лучшим решением.

person rsarro    schedule 11.05.2009

«Работающий русский» - один из лучших ответов, и я думаю, что все остальные предложенные варианты могут не сработать. Причина проста в том, что при первом создании приложения все его API-интерфейсы разрешаются во время компиляции. Используя "ldd", вы можете увидеть все статически связанные зависимости:

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)

Но во время выполнения firefox также загрузит множество других динамических библиотек, например (для firefox) загружено много библиотек с пометкой «glib» (хотя статически связанных библиотек их нет):

 /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

Часто вы можете видеть, как названия одной версии мягко связаны с другой версией. Например:

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

Следовательно, это означает, что в одной системе существуют разные версии «библиотек», что не является проблемой, поскольку это один и тот же файл, и он обеспечит совместимость, когда приложения имеют зависимости от нескольких версий.

Следовательно, на системном уровне все библиотеки почти взаимозависимы друг от друга, и простое изменение приоритета загрузки библиотек с помощью манипуляций с LD_PRELOAD или LD_LIBRARY_PATH не поможет - даже он может загружаться, во время выполнения он все равно может дать сбой.

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

Лучшая альтернатива - chroot (кратко упоминается ER): но для этого вам нужно будет воссоздать всю среду, в которой выполняется исходный двоичный файл - обычно начиная с / lib, / usr / lib /, / usr / lib / x86 и т. Д. Вы можете использовать Buildroot, YoctoProject или просто tar из существующей среды Distro. (например, Fedora / Suse и т. д.).

person Peter Teoh    schedule 08.07.2015

Когда я хотел запустить Chrome-браузер на Ubuntu Precision (glibc-2.15), я получил (типичное) сообщение "... libc.so.6: версия` GLIBC_2.19 'не найдена ... ". Считал, что файлы нужны не постоянно, а только для начала. Итак, я собрал файлы, необходимые для браузера и sudo, и создал среду mini-glibc-2.19-, запустил браузер, а затем снова скопировал исходные файлы. Необходимые файлы находятся в ОЗУ, и исходный glibc такой же.

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)

сценарий для запуска браузера:

#!/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
person dudu    schedule 29.05.2018