На примере неподдерживаемого дистрибутива Linux и современного веб-браузера приводятся сведения, необходимые для создания среды выполнения приложений, требующих альтернативных версий системных библиотек
Быстрое развитие информационных технологий приводит к тому, что одно за другим сменяются поколения аппаратных платформ, а программные продукты стараются не отставать в этой гонке. Однако реальность такова, что устаревшие версии операционных систем продолжают эксплуатироваться. Причины этого могут лежать в нескольких плоскостях:
- экономической – отсутствие средств на модернизацию вычислительной техники;
- технологической – нужная программа работает только на конкретной версии операционной системы;
- психологической – пользователь привык к используемому программному обеспечению, которое он хорошо изучил и функциональность которого его полностью устраивает.
В этой статье на примере популярного в свое время дистрибутива Mandriva Linux 2008 рассматриваются действия, необходимые для запуска современного веб-браузера Pale Moon.
Исследование проблемы
Получить современный веб-браузер на устаревшем Linux можно как минимум двумя способами:
- Адаптировать исходные тексты веб-браузера для работы с пакетами тех версий, которые имеются в дистрибутиве.
- Создать в установленной системе среду, которая требуется для выполнения веб-браузера.
Первый путь – самый эстетичный, но практически неосуществимый. Веб-браузер представляет собой сложный комплекс модулей, в котором каждый модуль – это отдельный проект, разработкой которого занимается независимая команда. И если разработчики приняли решение об отказе от поддержки устаревших версий операционных систем, выполнять эту работу за них чрезвычайно сложно.
Создадим требуемую среду выполнения и избежим конфликтов различных версий динамических библиотек
Второй путь более реалистичный, тем более что он допускает два подхода:
- Обновить пакеты дистрибутива, которые не удовлетворяют требованиям современных веб-браузеров.
- Установить требуемые пакеты в качестве дополнительных и сконфигурировать веб-браузер на их использование.
Следование первому подходу может негативно отразиться на стабильности операционной системы, поскольку официальные обновления для дистрибутива уже не выпускаются, а провести всеобъемлющее тестирование системы с собранными самостоятельно пакетами практически так же сложно, как адаптировать браузер к системе.
При использовании второго подхода устанавливаемое программное обеспечение будет взаимодействовать только с веб-браузером, и стабильность системы не пострадает. В статье предпочтение отдано именно этому, более безопасному, подходу.
Динамически компонуемые программы
Программы в машинных кодах, предназначенные для выполнения в операционной системе Linux, при сборке из исходных текстов могут быть скомпонованы с вспомогательными библиотеками статически или динамически [1].
За загрузку динамически компонуемых программ (см. рис. 1) в операционной системе отвечает загрузчик, ссылка на который находится в файле /lib/ld-linux.so.2. Сам загрузчик скомпонован статически, в чем можно убедиться с помощью команды:
$ file /lib/ld-2.6.1.so
/lib/ld-2.6.1.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped
Для динамически компонуемых программ вывод команды file содержит текст dynamically linked (uses shared libs), например:
$ file palemoon/palemoon
$ palemoon/palemoon: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.18, dynamically linked (uses shared libs), stripped
Посмотреть, от каких конкретно динамических библиотек зависит исполняемый файл, можно с помощью команды:
$ ldd palemoon/palemoon
linux-gate.so.1 => (0xffffe000)
libpthread.so.0 => /lib/i686/libpthread.so.0 (0xb7f6d000)
libdl.so.2 => /lib/libdl.so.2 (0xb7f69000)
librt.so.1 => /lib/i686/librt.so.1 (0xb7f60000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e72000)
libm.so.6 => /lib/i686/libm.so.6 (0xb7e4d000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7e41000)
libc.so.6 => /lib/i686/libc.so.6 (0xb7d00000)
/lib/ld-linux.so.2 (0xb7f96000)
Перед выполнением динамически компонуемой программы загрузчик должен:
- загрузить код программы в оперативную память;
- отыскать файлы динамических библиотек и загрузить код модулей в оперативную память;
- исправить в загруженном коде программы ссылки на динамические модули в соответствии с их фактическим местонахождением.
По умолчанию поиск динамических библиотек, необходимых для работы программы, производится в следующем порядке (man 8 ld.so):
- в местах, указанных при компиляции программ;
- в каталогах, перечисленных в конфигурационном файле /etc/ld.so.conf, сведения из которого обрабатываются системной утилитой ldconfig и вносятся в файл двоичного формата /etc/ld.so.cache;
- в стандартных системных каталогах /usr/lib и /lib.
Временно описанный порядок поиска можно изменить, указав приоритетные пути в переменной окружения LD_LIBRARY_PATH:
$ env LD_LIBRARY_PATH=$HOME/usr/lib palemoon/palemoon
Заметим, что пути, которые указаны в п. 3, записаны в файл загрузчика при его компиляции. В этом можно легко убедиться:
$ strings /lib/ld-2.6.1.so | grep /lib
/lib/
/usr/lib/
При сборке пакета glibc из исходных текстов для установки в нестандартном каталоге эти пути могут быть другими, что будет показано в дальнейшем.
Веб-браузер Pale Moon
Загрузим с официального веб-сайта 32-битную версию веб-браузера Pale Moon, распакуем дистрибутивный архив и попробуем его выполнить:
$ tar jxf palemoon-28.1.0.linux-i686.tar.bz2
$ palemoon/palemoon
XPCOMGlueLoad error for file $HOME/palemoon/libxul.so:
/home/ussr/palemoon/libxul.so: ELF file OS ABI invalid
Couldn't load XPCOM.
Браузер не запустился, а из полученного сообщения становится понятно, что ошибка произошла при инициализации системы XPCOM. Сообщение ELF file OS ABI invalid характерно для подсистемы glibc, когда загрузчик динамических библиотек (/lib/ld-linux.so.2) не может идентифицировать интерфейс динамической библиотеки (в данном случае libxul.so).
Причиной подобной проблемы зачастую является:
- несоответствие версии динамической библиотеки архитектуре операционной системы (в том числе попытка использования 64-битных динамических библиотек на 32-битных операционных системах);
- несоответствие версии подсистемы glibc, установленной в операционной системе, той, которая необходима для выполнения программы.
Посмотрим сведения о динамических библиотеках пакета palemoon:
$ file -L palemoon/*.so
( . . . )
palemoon/libsmime3.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), stripped
palemoon/libsoftokn3.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), stripped
palemoon/libssl3.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), stripped
palemoon/libxul.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), stripped
Обнаружено различие в параметре OS ABI библиотеки palemoon/libxul.so (GNU/Linux) и остальных динамических библиотек (SYSV).
Спецификация SYSV традиционна для формата ELF и операционных систем семейства UNIX, тогда как соглашение OS ABI GNU/Linux было введено позже. К сожалению, загрузчик динамических библиотек, являющийся компонентом установленной в операционной системе подсистемы glibc, не смог распознать этот формат и сообщил об ошибке.
Решить возникшую проблему можно двумя способами:
- Обновить подсистему glibc используемого дистрибутива.
- Отыскать подходящую версию проблемной динамической библиотеки в поддерживаемом формате.
Второй способ проще в случае удачного поиска, но в долгосрочной перспективе может вызвать проблемы. Ведь выполняться будет уже не исходный, а модифицированный пакет веб-браузера, и после планового обновления его до новой версии может потребоваться повторная замена динамической библиотеки. Поэтому соберем подсистему glibc из исходных текстов.
Подготовка сред выполнения и сборки
Для решения поставленной в статье задачи решено задействовать три области размещения бинарных файлов (см. рис. 2):
- Штатные библиотеки дистрибутива /lib, /usr/lib и его исполняемые файлы /bin, /sbin, /usr/bin, /usr/sbin.
- Дополнительные библиотеки $HOME/usr/lib и исполняемые файлы $HOME/usr/bin, $HOME/usr/sbin, зависимости которых не выходят за рамки этих дополнительных библиотек и стандартных библиотек из п. 1.
- Новая версия библиотеки glibc и зависящие от нее библиотеки $HOME/glibc-2.16/lib, а также связанные с этими библиотеками исполняемые файлы $HOME/glibc-2.16/bin и $HOME/glibc-2.16/sbin.
Необходимость выделения библиотеки glibc 2.16 и зависимых от нее программ в отдельный каталог по отношению к $HOME/usr связана с существенными трудностями при конфигурировании среды сборки пакетов, зависящих от штатных библиотек дистрибутива и некоторых дополнительных библиотек (см. приложение 1). Спрятать новую версию glibc от средств разработки проще всего таким организационным методом, нежели задавать массу ключей для компилятора и компоновщика.
Файлы с исходными текстами для сборки пакетов программного обеспечения размещаются в каталоге $HOME/work. В нем создан подкаталог $HOME/work/obj для промежуточного хранения результатов сборки GCC и glibc.
Дело в том, что если большинство пакетов могут быть собраны с помощью классической последовательности команд:
./configure --prefix=$PREFIX; make; make install
выполненных из каталога с исходными текстами, то аналогичные команды для GCC и glibc должны выполняться из пустых подкаталогов.
Для подготовки среды сборки пакетов удобно использовать файл build.env с таким содержимым:
#!/bin/sh
PREFIX=$HOME/usr
PATH=$PREFIX/bin:$PATH
PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig
LD_LIBRARY_PATH=$PREFIX/lib:/lib:/usr/lib
export PKG_CONFIG_PATH LD_LIBRARY_PATH
Перед выполнением команд сборки этот файл нужно задействовать (однократно!) в сеансе терминала следующей командой:
$ source build.env
Подготовка инструментария
Основными инструментами разработки приложений в мире Linux являются компилятор GNU GCC и утилиты GNU Binutils, GNU Make и GNU Autoconf [2]. В дальнейшем изложении для сокращения текста префикс GNU будет опускаться.
Для решения задачи, поставленной в статье, нет необходимости в использовании утилит Autoconf, потому что исходные тексты всех задействованных пакетов доступны в виде версионированных tar-архивов. Версия установленной в дистрибутиве утилиты Make не вызвала никаких нареканий со стороны конфигурационных сценариев, поэтому тоже останется без изменений. Потребуется обновить лишь GCC и Binutils.
В первую очередь устанавливаются средства разработки, поставляемые дистрибутивом. Они объединены метапакетом kernel-desktop-devel-2.6.22-1mdv.
Отдельно устанавливается компилятор Си++, который представлен пакетом gcc-c++ 4.2.2-0.RC.1mdv2008.0. Если о нем забыть, то при сборке GCC будет выдано сообщение об ошибке:
configure: error: C++ compiler missing or inoperational
конфигуратор почему-то не обнаруживает этой проблемы, а для исправления ошибки надо удалить каталог с результатами частичной сборки, создать новый и после установки gcc-c++ заново выполнить конфигурирование.
Для сборки GCC в каталог с исходными текстами нужно распаковать вспомогательные пакеты точной и комплексной арифметики (ISL, GMP, MPFR и MPC) и создать в нем символические ссылки на версионированные папки:
$ ln -s mpc-1.0.3 mpc
$ ln -s mpfr-3.1.4 mpfr
$ ln -s isl-0.18 isl
$ ln -s gmp-6.1.0 gmp
Если не установить вспомогательные пакеты, то конфигурирование завершится с ошибкой:
configure: error: Building GCC requires GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+.
Сборку GCC нельзя производить в том же каталоге, где находятся исходные тексты пакета. Поэтому в каталоге obj создается подкаталог gcc-4.8.2, делается текущим, и уже из него дается команда на конфигурирование:
$ ../../gcc-4.8.2/configure --prefix=$PREFIX --enable-languages=c,c++
Ограничение списка поддерживаемых языков программирования способствует уменьшению времени сборки и занимаемого дискового пространства. После конфигурирования сборка и установка GCC производятся с помощью команд:
make; make install
Сборка пакета binutils-2.24 производится по стандартной схеме, с указанием на этапе конфигурирования пути к целевому каталогу.
Сборка glibc
Основная роль библиотеки glibc – реализация интерфейса между функциями стандарта POSIX и системными вызовами ядра операционной системы. Поэтому она находится в сильной зависимости от ядра. Если, например, в среде дистрибутива Mandriva 2008 можно без особенных проблем собрать самую современную версию компилятора GCC 8.2, то к выбору совместимой версии glibc нужно подходить с большой осмотрительностью, ориентируясь на период расцвета ядра версии 2.6. В результате ряда экспериментов была найдена подходящая версия для модернизации – glibc-2.16.0.
Сборку glibc рекомендуется осуществлять с указанием на заголовочные файлы самой современной версии ядра операционной системы из доступных. В ретроспективе «современность» означает доступность на момент выпуска glibc, в рассматриваемом примере это версия 2.6.38.8 (попытка сборки антикварной версии glibc со ссылкой на заголовочные файлы ядра четвертой или даже третьей версии GNU/Linux ни к чему хорошему не приведет).
Для установки заголовочных файлов нужно распаковать архив с исходными текстами linux-2.6.38.8.tar.bz2, сделать создавшийся при этом каталог текущим и выполнить команды:
$ HEADERS=$HOME/work/kernel-2.6.38.8-headers
$ make headers_install arch=i686 INSTALL_HDR_PATH=$HEADERS
где значение переменной HEADERS задает целевой каталог для заголовочных файлов.
Для сборки пакета glibc, как и для GCC, нужно создать отдельный подкаталог obj/glibc-2.16.0 и сделать его текущим. После этого можно выполнять конфигурирование:
$ ../../glibc-2.16.0/configure --prefix=$HOME/glibc-2.16 i686-pc-linux CFLAGS='-O2 -march=i686' --with-headers=$HEADERS/include --enable-kernel=2.6.22
Параметр enable-kernel задает минимальную версию ядра, которая будет поддерживаться библиотекой glibc, а параметры, содержащие i686, позволяют произвести на современном компьютере сборку пакета для устаревшей архитектуры. Если в параметре with-headers указать неправильный путь, то конфигурирование может пройти успешно, но при сборке будет выведена серия сообщений об ошибках вида:
#include <.../... .h> Фатальная ошибка: .../... .h Нет такого файла или каталога
Если же в перечне флагов компилятора CFLAGS не указать опцию -O2, то сборка будет прервана ошибкой:
# error "glibc cannot be compiled without optimization"
Процесс сборки запускается командой:
$ make
Установка производится с помощью команды:
$ env LANGUAGE=C LC_ALL=C make install
Свежесобранный загрузчик динамически компонуемых программ в качестве стандартного пути поиска динамических библиотек будет использовать единственный каталог $HOME/glibc-2.16/lib, в чем легко убедиться:
$strings $HOME/glibc-2.16/lib/ld-2.16.so | grep /lib
$HOME/glibc-2.16/lib/
Поэтому теперь нужно создать файл $HOME/usr/etc/ld.so.conf с перечнем дополнительных путей поиска динамических библиотек:
/lib
/usr/lib
/usr/lib/vmware-tools/lib32/libgio-2.0.so.0
и выполнить команду индексирования перечисленных каталогов:
$ $HOME/usr/sbin/ldconfig.
Запуск программы с новой версией glibc
На данном этапе в системе установлены две версии glibc:
- поставлявшаяся вместе с дистрибутивом 2.6.1 и находящаяся в каталоге /lib (с загрузчиком динамических библиотек /lib/ld-linux.so.2 -> /lib/ld-2.6.1.so);
- новая 2.16.0, находящаяся в каталоге $HOME/glibc-2.16/lib (с загрузчиком динамических библиотек $HOME/glibc-2.16/lib/ld-linux.so.2 -> ld-2.16.0.so).
Если сейчас попытаться запустить веб-браузер командой:
$ env LD_LIBRARY_PATH=$HOME/glib-2.16/lib palemoon/palemoon
то будет выдано сообщение об ошибке:
palemoon/palemoon: error while loading shared libraries: $HOME/glib-2.16/lib/libm.so.6: ELF file OS ABI invalid
Дело в том, что при запуске программы palemoon/palemoon был задействован загрузчик динамических библиотек /lib/ld-2.6.1.so, которому не знаком новый формат динамической библиотеки libm.so.6. Система не применила новую версию загрузчика из $HOME/glib-2.16/lib/ld-2.16.0.so, потому что путь к загрузчику прописывается в исполняемом файле при компиляции и, как правило, представлен ссылкой /lib/ld-linux.so.2.
Для запуска программы с помощью конкретной версии загрузчика можно воспользоваться такой командой:
$HOME/glibc-2.16/lib/ld-linux.so.2 --library-path $HOME/glibc-2.16/lib:$HOME/usr/lib palemoon/palemoon
В параметре --library-path прописаны приоритетные пути поиска динамических библиотек. Теперь ошибка выглядит так:
XPCOMGlueLoad error for file /home/ussr/palemoon/libxul.so:
libX11-xcb.so.1: cannot open shared object file: No such file or directory
Couldn't load XPCOM.
Полученное сообщение говорит о том, что системе не удалось обнаружить файл динамической библиотеки libX11-xcb.so.1, который нужен модулю libxul.so. Это небольшая интерфейсная библиотека, которую проще всего взять в готовом двоичном виде для архитектуры i386 из дистрибутива Debian и записать файлы libX11-xcb.so.1 и libX11-xcb.so.1.0.0 в каталог $HOME/usr/lib. После этого попытка запуска веб-браузера palemoon прервется сообщением:
(pale moon:27834): Gtk-WARNING **: Locale not supported by C library.
Using the fallback 'C' locale.
palemoon/palemoon: symbol lookup error: /home/ussr/palemoon/libxul.so: undefined symbol: gdk_x11_set_sm_client_id
Ссылка на отсутствующий символ gdk_x11_set_sm_client_id говорит о том, что установленная в дистрибутиве версия библиотеки GTK+ 2.12 не соответствует минимальным требованиям веб-браузера относительно GTK+ >= 2.24. Выполним установку требуемой версии GTK+.
Сборка GTK+
С учетом изложенных выше сведений сборка пакета GTK+ 2.24 из исходных текстов превращается в рутинную процедуру. Желающие могут ее повторить, предварительно установив из дистрибутива следующие пакеты:
- zlib1-devel 1.2.3-8mdv2008.0;
- libpng-devel 1.2.19-2mdv2008.0;
- libfreetype6-devel 2.3.5-2mdv2008.0;
- libx11_6-devel 1.1.3-2mdv2008.0;
- libxrandr2-devel 1.2.2-1 mdv2008.0.
Без последнего пакета конфигуратор GTK+ будет завершаться с сообщением об ошибке:
checking for XOpenDisplay... no
configure: error: *** libX11 not found. Check 'config.log' for more details.
Перед сборкой остальных пакетов нужно сконфигурировать среду (если она еще не была сконфигурирована) с помощью файла build.env, как было описано выше. Сборка выполняется посредством классической последовательности команд:
./configure --prefix=$PREFIX; make; make install
в соответствии с деревом зависимостей (см. приложение 2):
GTK+ [2.24.20]
glib-2.0 [2.34.3]
libffi [3.2.1]
gettext [0.18.3.2]
atk [2.8.0]
pango [1.30.1]
cairo [1.10.2]
pixman [0.32.4]
expat [2.1.0]
fontconfig [2.10.94]
gdk-pixbuf-2.0 [2.28.2]
libtiff [3.9.7]
libjpeg [9c]]
Если у платформы, на которой выполняется сборка, нет доступа к интернету, то при конфигурировании пакета glib-2.0 нужно отключить генерацию файлов документации, указав параметр --disable-man, во избежание ошибок:
GEN glib-gettextize.1
I/O error : Attempt to load network entity http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl
warning: failed to load external entity http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl
cannot parse http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl
После установки GTK+ веб-браузер palemoon-28.1 успешно запускается командой (см. рис. 3):
$ $HOME/glibc-2.16/lib/ld-linux.so.2 --library-path $HOME/glibc-2.16/lib:$HOME/usr/lib palemoon/palemoon &
Цель, поставленная в начале статьи, достигнута.
Запуск современных приложений может быть выполнен под управлением устаревших неподдерживаемых версий операционных систем (и наоборот), если для них будет создано необходимое окружение. С помощью приемов, которые описаны в этой статье, можно создать требуемую среду выполнения и избежать конфликтов различных версий динамических библиотек.
Приведем список тезисов, которыми предлагается руководствоваться при решении проблем, связанных с работой динамически компонуемых программ:
- Для выполнения динамически компонуемых программ операционная система задействует загрузчик динамических библиотек.
- Загрузчик динамических библиотек является частью пакета glibc и представляет собой статически скомпонованную программу.
- Путь к загрузчику на этапе компиляции программы записывается в файл с е-двоичным кодом: /lib/ld-linux.so.2.
- Для запуска программы альтернативным загрузчиком нужно выполнить сам загрузчик, передав ему в качестве параметров имя запускаемой программы и приоритетные пути поиска динамических библиотек.
- Основные пути поиска динамических библиотек задаются в конфигурационном файле /etc/ld.so.conf, на основе которого с помощью команды:/sbin/ldconfig
строится индексный файл /etc/ld.so.cache, используемый загрузчиком. - Приоритетные пути поиска динамических библиотек могут быть заданы через переменную окружения PKG_CONFIG_PATH.
- Приоритетный путь поиска runtime-библиотек, с которыми компилятор связывает код программы, может быть изменен с помощью опции компоновщика -rpath, которая может быть передана через переменную параметров компилятора в виде: CFLAGS='-Wl,-rpath,ПУТЬ'
- Порядок обхода путей системой сборки в поисках динамических библиотек может быть изменен и дополнен посредством указания: CFLAGS='-L Путь1 -L Путь2'
Описанные в статье приемы и методы могут быть использованы для решения задачи запуска произвольных программ под различными операционными системами семейства Linux.
- Ян Шилдс. Управление общими библиотеками – https://www.ibm.com/developerworks/ru/library/l-lpic1-v3-102-3/.
- Дж. Фуско. Linux. Руководство программиста. – СПб.: Питер, 2011.
Приложение 1. Зачем нужно выделять glibc?
Возникает вопрос: «А нельзя ли для единообразия установить новую версию glibc в каталог $HOME/usr вместе со всеми дополнительными программами и библиотеками?» Давайте рассмотрим, с какими проблемами придется столкнуться при таком варианте и как их можно решать.
При сборке программы из исходных текстов компилятор записывает в исполняемый файл путь к каталогу, в котором загрузчик будет искать файлы библиотек времени выполнения (runtime libraries) в первую очередь. Как правило, это каталог $PREFIX/lib. Если при конфигурировании не указывать параметр --prefix, то в качестве $PREFIX будет использовано значение по умолчанию: /usr/local.
Во вновь установленном дистрибутиве каталог /usr/local/lib пуст, поэтому при запуске собранной из исходных текстов программы будет задействована библиотека /lib/libc.so.6 в соответствии с правилом поиска динамических библиотек.
Но в описываемой ситуации, когда программное обеспечение конфигурируется с параметром --prefix=$HOME/usr, при запуске исполняемых файлов будут подключаться динамические библиотеки из каталога $HOME/usr/lib, который содержит новую версию библиотеки glibc.
Это не всегда желательно. Если, например, в такой конфигурации собрать пакет xz-5.2.4, который необходим для распаковки xz-архивов, то при запуске утилиты xz будет выдаваться уже знакомая ошибка:
xz: error while loading shared libraries: $HOME/usr/lib/libc.so.6: ELF file OS ABI invalid
Привязки динамических библиотек можно увидеть с помощью команды:
$ $HOME/usr/lib/ld-linux.so.2 --list $HOME/usr/bin/xz
...
libc.so.6 => $HOME/usr/lib/libc.so.6 (0xb7de4000)
/lib/ld-linux.so.2 => $HOME/usr/lib/ld-linux.so.2 (0x80000000)
Причину произошедшего демонстрирует команда:
$ strings $HOME/usr/bin/xz | grep lib
/lib/ld-linux.so.2
...
libc.so.6
__libc_start_main
$HOME/usr/lib
liblzma %s
Чтобы такой ситуации избежать, нужно в команде конфигурирования указать приоритетные пути для поиска библиотек компоновщиком (man ld):
$ ./configure --prefix=$HOME/usr LDFLAGS='-Wl,-rpath,/lib'
После сборки утилита запускается и работает нормально благодаря компоновке с заданными версиями динамических библиотек:
$ ldd $HOME/usr/bin/xz
...
libc.so.6 => /lib/i686/libc.so.6 (0xb7df2000)
/lib/ld-linux.so.2 (0xb7f7f000)
Убедиться в результативности произведенной настройки можно с помощью команды:
$ strings $HOME/usr/bin/xz | grep lib
/lib/ld-linux.so.2
...
libc.so.6
__libc_start_main
/lib:$HOME/usr/lib
liblzma %s
При сборке из исходных текстов динамических библиотек (например, libffi-3.2.1, которая необходима пакету GTK+) можно столкнуться с проблемой иного рода. Новый компилятор GCC, установленный в каталог $HOME/usr/bin, обнаруживает новую версию библиотеки glibc и собирает целевую динамическую библиотеку с присвоением ей зависимости от версии новой библиотеки:
$ $HOME/usr/bin/ldd $HOME/usr/lib/libffi.so
$HOME/usr/lib/libffi.so: /lib/i686/libc.so.6: version 'glibc_2.7' not found (required by $HOME/usr/lib/libffi.so)
linux-gate.so.1 (0xffffe000)
libc.so.6 => /lib/i686/libc.so.6 (0xb7e62000)
$HOME/usr/lib/ld-linux.so.2 (0x80000000)
Из сообщения видно, что для libffi.so задействуется штатная версия glibc: /lib/i686/libc.so.6, но ожидается версия не ниже glibc_2.7. Справиться с этой проблемой помогает указание приоритетных путей для поиска библиотек системой сборки:
$ ./configure --prefix=$PREFIX LDFLAGS='-L/lib -L/usr/lib'
Суммируя сказанное, если собираемому пакету не требуется новая версия библиотеки glibc, при конфигурировании исходных текстов перед сборкой можно создать переменную LDFLAGS со значением '-Wl,-rpath,/lib,-L/lib -L/usr/lib'.
Это позволяет обойти многие проблемы, но, к сожалению, не все. Некоторые программы требуют дополнительные библиотеки при старой версии glibc. Сложность конфигурирования инструментов сборки для таких случаев существенно превышает эстетические неудобства от вынесения новой версии glibc в отдельный каталог.
Приложение 2. Использованные пакеты программного обеспечения
- Mandriva Linux 2008 – ftp://ftp.linuxcenter.ru/mirrors/ftp.mandriva.ru/mandriva/official/iso/2008.0/
- gcc-4.8.2 – https://gcc.gnu.org/pub/gcc/releases/
- mpc-1.0.3 – https://gcc.gnu.org/pub/gcc/infrastructure/
- isl-0.18 – https://gcc.gnu.org/pub/gcc/infrastructure/
- gmp-6.1.0 – https://gcc.gnu.org/pub/gcc/infrastructure/
- binutils-2.24 – https://gcc.gnu.org/pub/binutils/releases/
- glibc-2.16.0 – http://ftp.gnu.org/gnu/libc/
- gtk+-2.24.20 – https://download.gnome.org/sources/gtk+/
- glib-2.34.3 – https://download.gnome.org/sources/glib/
- libffi-3.2.1 – https://sourceware.org/libffi/
- gettext-0.18.3.2 – http://ftp.gnu.org/gnu/gettext/
- atk-2.8.0 – https://download.gnome.org/sources/atk/
- pango-1.30.1 – https://download.gnome.org/sources/pango/
- cairo-1.10.2 – https://cairographics.org/releases/
- pixman-0.32.4 – https://www.cairographics.org/releases/
- fontconfig-2.10.94 – https://www.freedesktop.org/software/fontconfig/release/
- gdk-pixbuf-2.28.2 – https://download.gnome.org/sources/gdk-pixbuf/
- tiff-3.9.7 – http://download.osgeo.org/libtiff/old/
Ключевые слова: приложения, операционные системы, динамические библиотеки, компиляторы.