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

171

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

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

Можно ли установить несколько glibcs ​​на одном хосте?

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

Спасибо

кендырь
источник
1
та же проблема с сервером SLES-11. Не могу обновить и нужны последние вещи. о боже ...
UmNyobe
FWIW, export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH действительно решил проблему для меня! Это, конечно, не будет работать для всех, но это легко исправить, если это работает! Спасибо! :)
Риного

Ответы:

229

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

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

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

Чтобы создать исполняемый файл, который будет работать с новым 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 и бинарный редактор .

Занятый русский
источник
3
Обратите внимание, что -Wl,--dynamic-linker=file(принимает два '-') работает только при компиляции для исполняемых файлов ELF. Проверка/sbin/ldconfig -p | grep ld
Том
49
Теперь вы можете использовать удобную утилиту patchelf( nixos.org/patchelf.html ), которая позволяет изменять rpath и интерпретатор уже скомпилированного ELF.
Михаил Панков
10
Стоит отметить, что указание пути к новому glibc с помощью, -Wl,--rpathа не LD_LIBRARY_PATHможет быть важным по причинам, не связанным с удобством: если программа запускает дочерние процессы, их значение LD_LIBRARY_PATHобычно наследуется, но если они также не скомпилированы для использования более новый glibc (например, если они как стоковые двоичные файлы bash), они не будут запускаться.
HighCommander4
13
Другой вариант - запустить новый ld.so напрямую, передав в качестве параметра вашу двоичную программу; это эффективно заменит ld.so, используемый без необходимости перекомпиляции программы:/path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
maximk
Мне также нужно -Iи -L: stackoverflow.com/a/52454603/895245
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
67

Этот вопрос старый, остальные ответы старые. Ответ «Занятого русского» очень хороший и информативный, но он работает только при наличии исходного кода. Если нет, то альтернативы тогда были очень хитрыми. К счастью, в настоящее время у нас есть простое решение этой проблемы (как прокомментировано в одном из его ответов) с использованием 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 и Михаилу Панкову за понимание и решение!

MSB
источник
1
Это было самым полезным! Я исправил двоичный файл Python, чтобы использовать новый glibc для тензорного потока
faizan
Это изящное решение (о котором я раньше не знал patchelf), но фраза «Нет необходимости ... редактировать двоичные файлы» может немного вводить в заблуждение (поскольку вы фактически редактируете свои двоичные файлы).
Жаворонки
Там исправлено. ;)
MSB
Действительно полезная утилита! Спасибо! Хотя мне удалось получить ошибку сегментации только после нескольких часов ручного разрешения зависимостей и последующего исправления всего, чтобы локально установить Chrome без прав администратора ...
Г. Бержерон
@fgiraldeau спасибо за комплимент. :) но вопрос был задан, отвечен и принят в 2009 году, я не ожидал, что кто-то подождет 8 лет, прежде чем принять ответ. хехех, D
MSB
20

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

LD_PRELOAD='mylibc.so anotherlib.so' program

Смотрите: статья в Википедии

Крысолов
источник
1
Я подумал, что это будет хороший обходной путь для сложного Makefile, но у меня это не сработало
galactica
это особенно полезно для тех, у кого нет исходного кода. Спасибо
кодер
2
хм ... я был неправ, похоже, мне нужен rpath файла ld-linux.so в / path / to / new / lib / frist, пока исходная компиляция и компоновка
кодер
1
Это не работает, если ld - #. ##. Поэтому (из вашей системы glibc lib) не та же версия glibc, что и libc.so. # (из вашей альтернативной
Энди
12

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

Давайте рассмотрим простой пример: у меня есть система Ubuntu Newset, на которой я запускаю какую-то программу (в моем случае это 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.

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

Аркадиуш Рыхлинский
источник
Я скомпилировал программу на RH7 и мне нужно, чтобы она работала на RH6. Я не хотел создавать новый исполняемый файл или использовать patchelf, так что это отличная альтернатива.
Марк Райкок
9

Настройка 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.
     * /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);
}

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

поэтому я убрал его.

lddoutput подтверждает, что 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: первоначальная настройка crosstool-NG

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

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

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

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

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

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

Получите crosstool-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

так что menuconfigя делаю:

  • 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: установить в true
  • C-library
    • Source of glibc
      • Custom location: скажи да
      • Custom location
        • Custom source location: указать каталог, содержащий ваш исходный код glibc

где 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

Это не представляется возможным с Crosstool-NG, как объяснено ниже.

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

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

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

Если мы делаем:

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

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

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

Бонус: stdlibc ++

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

Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник
6

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

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


источник
4

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

Я столкнулся с этой проблемой, когда я сделал import tensorflow as tfв среде Конда, в 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.

ссылка: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/

Belter
источник
2

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

user1396055
источник
1

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

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

rsarro
источник
1

«Занятый русский» - один из лучших ответов, и я думаю, что все другие предложенные ответы могут не сработать. Причина в том, что когда приложение создается впервые, все необходимые ему 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 и т. д.).

Питер Теох
источник
0

Когда я захотел запустить браузер chromium в Ubuntu (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
дуда
источник