Путь джедая: компилируем GNU/Linux пакеты вручную
Зачем в наш век apt-get'ов и прочих rpm'ов собирать ПО для Linux вручную? Причин может быть несколько.
Во-первых, создатели репозитариев не сразу реагируют на появление новых версий популярных программ. Тот, кто хочет иметь самый свежий софт, может собрать что-то из исходников и раньше всех получить новые, более быстрые и стабильно работающие программы.
Во-вторых, компилируя из исходников знакомишься с культурой GNU, заглядываешь в код продвинутых прогеров и чему-то у них учишься. При этом не обязательно в совершенстве знать C, достаточно азов, но в процессе сборки эти азы здорово совершенствуются.
В-третьих, иногда быстрее найти ПО в исходниках, чем в репозитариях, да и далеко не всё в последних есть. К тому же в пакетах «от производителей» многие программы собраны в обширные коллекции, а нужен всего лишь маленький кусочек.
В-четвертых, сборка их исходников — своеобразный квест, пройти который становится делом чести, когда упираешься в какую-то, на первый взгляд, уж очень запутанную проблему.
Рассмотрим процесс на примере сборки свежей верcии gcc (компилятора для Linux) и убедимся, что не так это страшно, как кажется.
На кой черт меня понесло собирать компилятор из исходников? Дело в том, что не все новые программы обрабатываются старыми компиляторами. К тому же новые версии gcc делают код более оптимизированным, а значит быстрым, эффективным. Разве плохо, если программы на компьютере будут работать пусть даже на 2-3% быстрее? С миру по нитке — голому рубашка ;).
Итак, что нужно знать о процессе компиляции.
1) ПО для Linux распространяется в виде исходных кодов, т.е. тех самых текстов, которые программисты пишут на разных языках (в основном на C). Исходные коды собираются в архивы, включающие в себя большое количество файлов, а также скрипты для правильной сборки и установки программ.
2) Такие архивы в формате tar.gz или tar.bz2 (тарболы) скачиваются из Интернета и распаковываются в специальную директорию — /usr/src:
3) Для сборки пакетов из исходников нужны компилятор (gcc) и сборщик (make). Они присутствуют в любом дистрибутиве, хотя иногда из соображений безопасности их отключают (чтобы хакеры, в случае удаленного проникновения на машину, не смогли откомпилировать вредоносный код). Мы в качестве примера будем как раз собирать новый компилятор… посредством старого, установленного из пакетов.
4) Самым главным из сборочных скриптов каждого пакета является ./configure. Это исполняемый файл на языке bash, который проверяет: все ли условия для благополучной компиляции данного пакета есть на вашем компьютере (библиотеки, утилиты, характеристики ядра):
5) Если чего-то не хватает — ./configure выдаст сообщение об ошибке. Вам придется скачивать и компилировать другие пакеты, пока ./configure не отработает без ошибок. Результатом его работы должен стать файл с названием Makefile.
6) Следующая команда, которую нужно запустить —
На этом этапе ошибок бывает гораздо меньше, чем на предыдущем. Но все-таки они случаются и приходится изучать зависимости пакетов, что-то подправлять вручную. При наличии достаточного количества «масла в башке», а также доступа в Интернет проблемы, как правило, удается разрулить. Единственный инструмент, который для этого нужен — текстовой редактор.
7) Далее запускается
Эта команда раскладывает откомпилированные программы и прочие файлы по каталогам системы: настройки в /etc, библиотеки в /usr/lib, бинарники в /usr/bin и т.п. На этом этапе ошибок почти не бывает.
Очень часто никаких проблем при сборке не возникает, да и сами команды можно запустить одной строкой:
Естественно, делать это нужно из каталога, где лежат исходники собираемой программы. Кроме того, make install запускается от имени root, т.к. нужно создавать файлы в доступных на запись только корневому пользователю каталогах.
Конечно, компилирование из исходников занимает много времени. Иногда несколько десятков минут, а если собирать что-нибудь типа wine, а тем более ядро, то и несколько часов. И все-таки, это ни с чем не сравнимый кайф, когда из нескольких десятков мегабайт чьих-то заархивированных текстов получаются программы, точно подогнанные именно под данный компьютер. Такие системы работают стабильнее и эффективнее, чем вытянутые из репозитариев.
Итак, рассмотрим весь процесс на примере сборки нового компилятора gcc. Получить его исходники можно по адресу
ftp://gcc.gnu.org/pub/gcc/releases/gcc-4.5.0/gcc-4.5.0.tar.bz2
Батюшки! Да здесь же 64 с лишним мегабайта! Неужели это всё соберется без ошибок? Конечно, с первого раза не соберется, но танцев с бубном не так уж и много для такого объема. Очень вероятно, что ./configure ругнется на отсутствие или устаревшие версии библиотек gmp, mpfr и mpc. Что это за звери? Да хрен его знает. Вроде что-то для работы с примитивами. Не ломая особо голову, скачиваем, распаковываем, устанавливаем (для каждого пакета распаковка в /usr/src, затем ./configure && make && sudo make install).
ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-4.3.2.tar.bz2
ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-2.4.2.tar.bz2
ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-0.8.1.tar.gz
Некоторые пакеты устанавливаются в особую директорию — /usr/local. А другие пакеты не могут их там найти. Здесь могут помочь символические ссылки, а также команда
Итак, зависимости распаковали, установили, возвращаемся в каталог с исходниками gcc. Запускаем ./configure и, ощущая нехилый выброс адреналина в кровь, ждем: потребует еще что-то или нет? Надо же, больше ничего не нужно! Запускаем make и опять мандражируем до окончания процесса. Любителем Counter Strike такие ощущения и не снились Каждый раз во время очередной ошибки облом, поиск выхода, какие-то исправления, снова make. Но на этот раз повезло: огромный компилятор скомпилировался (каламбурчик-с) не пикнув. Делаем make install, убеждаемся, что работает (на уровне демонстрации версии):
Может я и поторопился заявить, что всё работает. Сначала нужно бы удалить старый компилятор, но это детали, которые каждый может решить самостоятельно.
Итак, компилятор собран и демонстрирует признаки жизни. Попробуем воспользоваться им, например, собрать самую главную библиотеку большинства дистрибутивов Linux — glibc. Скачиваем последнюю версию, распаковываем, запускаем ./configure… Обана! Вылетает с ошибкой. Причем непонятно, в чем она заключается. Написано, что детально сообщение о ней можно посмотреть в файле config.log. Что-ж, смотрим что в нем, обнаруживаем строку, где сказано, что невозможно запустить некую программу со странным именем as. Немного гугления — и вот уже понятно, что as — это GNU Ассемблер и получить его можно в составе пакета
ftp.gnu.org/gnu/binutils/binutils-2.20.1.tar.bz2
Скачиваем, распаковываем, собираем, устанавливаем.
На этот раз дело пошло повеселее: ./configure… Проскочили без ошибок? Нет Пишет, что сборку нужно вести в каком-то особом каталоге. Небывалое дело… Гуглим, выясняем, что
Ну? Опять двадцать пять! Пишет, что нужно указать каталог установки /usr, а не /usr/local (по умолчанию). ОК, нам не жалко. Вспоминаем нужный ключ с помощью
Ага, вот как надо:
Пошло дело? Да нет, есть еще проблемка: не найдены исходники ядра. Значит нужно указать в опциях:
Уф… ./configure проскочили. Как насчет make? Вот блин… Выдает какую-то ошибку про неверные строки в каких-то ассемблерных файлах.
Копируем сообщение об ошибке в строку Google, немного вкуриваем сообщения разнообразных буржуйских форумов — и вот уже понятно, что не только у нас такое случалось. Нужно применить к библиотеке патч, касающийся модели процессора. Вот текст патча (выкладываю для отечественных пользователей, поскольку на русском нет вообще ничего толкового об этой ошибке):
Признаюсь честно: я не умею уверенно работать с патчами. Зато я умею соображать головой При анализе этого диковатого кода можно догадаться, что в файл nptl/sysdeps/pthread/pt-initfini.c нужно в районе 45-й строки добавить строки
а в файле sysdeps/unix/sysv/linux/i386/sysdep.h — строки
Что они обозначают — понятия не имею ;) Знаю только, что после внесения правки процесс компиляции совершился без ошибок (как раз пока я писал этот топик).
Осталось выполнить make install, но мы не только выполним, но и перевыполним: создадим модуль для Slax:
Ну как квест? Это вам не ботов по бассейну шугать
Если новички не поняли этот топик до конца — ничего страшного, дело наживное. И все-таки при случае попробуйте собрать какой-нибудь несложный пакет. В случае удачи будете чувствовать себя в мире Linux гораздо увереннее.
Во-первых, создатели репозитариев не сразу реагируют на появление новых версий популярных программ. Тот, кто хочет иметь самый свежий софт, может собрать что-то из исходников и раньше всех получить новые, более быстрые и стабильно работающие программы.
Во-вторых, компилируя из исходников знакомишься с культурой GNU, заглядываешь в код продвинутых прогеров и чему-то у них учишься. При этом не обязательно в совершенстве знать C, достаточно азов, но в процессе сборки эти азы здорово совершенствуются.
В-третьих, иногда быстрее найти ПО в исходниках, чем в репозитариях, да и далеко не всё в последних есть. К тому же в пакетах «от производителей» многие программы собраны в обширные коллекции, а нужен всего лишь маленький кусочек.
В-четвертых, сборка их исходников — своеобразный квест, пройти который становится делом чести, когда упираешься в какую-то, на первый взгляд, уж очень запутанную проблему.
Рассмотрим процесс на примере сборки свежей верcии gcc (компилятора для Linux) и убедимся, что не так это страшно, как кажется.
На кой черт меня понесло собирать компилятор из исходников? Дело в том, что не все новые программы обрабатываются старыми компиляторами. К тому же новые версии gcc делают код более оптимизированным, а значит быстрым, эффективным. Разве плохо, если программы на компьютере будут работать пусть даже на 2-3% быстрее? С миру по нитке — голому рубашка ;).
Итак, что нужно знать о процессе компиляции.
1) ПО для Linux распространяется в виде исходных кодов, т.е. тех самых текстов, которые программисты пишут на разных языках (в основном на C). Исходные коды собираются в архивы, включающие в себя большое количество файлов, а также скрипты для правильной сборки и установки программ.
2) Такие архивы в формате tar.gz или tar.bz2 (тарболы) скачиваются из Интернета и распаковываются в специальную директорию — /usr/src:
wget ftp://gcc.gnu.org/pub/gcc/releases/gcc-4.5.0/gcc-4.5.0.tar.bz2
cp ~/gcc-4.5.0.tar.bz2 /usr/src
cd /usr/src
tar xvf gcc-4.5.0.tar.bz2
3) Для сборки пакетов из исходников нужны компилятор (gcc) и сборщик (make). Они присутствуют в любом дистрибутиве, хотя иногда из соображений безопасности их отключают (чтобы хакеры, в случае удаленного проникновения на машину, не смогли откомпилировать вредоносный код). Мы в качестве примера будем как раз собирать новый компилятор… посредством старого, установленного из пакетов.
4) Самым главным из сборочных скриптов каждого пакета является ./configure. Это исполняемый файл на языке bash, который проверяет: все ли условия для благополучной компиляции данного пакета есть на вашем компьютере (библиотеки, утилиты, характеристики ядра):
cd /usr/src/gcc-4.5.0
./configure
5) Если чего-то не хватает — ./configure выдаст сообщение об ошибке. Вам придется скачивать и компилировать другие пакеты, пока ./configure не отработает без ошибок. Результатом его работы должен стать файл с названием Makefile.
6) Следующая команда, которую нужно запустить —
make
На этом этапе ошибок бывает гораздо меньше, чем на предыдущем. Но все-таки они случаются и приходится изучать зависимости пакетов, что-то подправлять вручную. При наличии достаточного количества «масла в башке», а также доступа в Интернет проблемы, как правило, удается разрулить. Единственный инструмент, который для этого нужен — текстовой редактор.
7) Далее запускается
make install
Эта команда раскладывает откомпилированные программы и прочие файлы по каталогам системы: настройки в /etc, библиотеки в /usr/lib, бинарники в /usr/bin и т.п. На этом этапе ошибок почти не бывает.
Очень часто никаких проблем при сборке не возникает, да и сами команды можно запустить одной строкой:
./configure && make && sudo make install
Естественно, делать это нужно из каталога, где лежат исходники собираемой программы. Кроме того, make install запускается от имени root, т.к. нужно создавать файлы в доступных на запись только корневому пользователю каталогах.
Конечно, компилирование из исходников занимает много времени. Иногда несколько десятков минут, а если собирать что-нибудь типа wine, а тем более ядро, то и несколько часов. И все-таки, это ни с чем не сравнимый кайф, когда из нескольких десятков мегабайт чьих-то заархивированных текстов получаются программы, точно подогнанные именно под данный компьютер. Такие системы работают стабильнее и эффективнее, чем вытянутые из репозитариев.
Итак, рассмотрим весь процесс на примере сборки нового компилятора gcc. Получить его исходники можно по адресу
ftp://gcc.gnu.org/pub/gcc/releases/gcc-4.5.0/gcc-4.5.0.tar.bz2
Батюшки! Да здесь же 64 с лишним мегабайта! Неужели это всё соберется без ошибок? Конечно, с первого раза не соберется, но танцев с бубном не так уж и много для такого объема. Очень вероятно, что ./configure ругнется на отсутствие или устаревшие версии библиотек gmp, mpfr и mpc. Что это за звери? Да хрен его знает. Вроде что-то для работы с примитивами. Не ломая особо голову, скачиваем, распаковываем, устанавливаем (для каждого пакета распаковка в /usr/src, затем ./configure && make && sudo make install).
ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-4.3.2.tar.bz2
ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-2.4.2.tar.bz2
ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-0.8.1.tar.gz
Некоторые пакеты устанавливаются в особую директорию — /usr/local. А другие пакеты не могут их там найти. Здесь могут помочь символические ссылки, а также команда
export LD_LIBRARY_PATH=/lib,/usr/lib,/usr/local/lib
Итак, зависимости распаковали, установили, возвращаемся в каталог с исходниками gcc. Запускаем ./configure и, ощущая нехилый выброс адреналина в кровь, ждем: потребует еще что-то или нет? Надо же, больше ничего не нужно! Запускаем make и опять мандражируем до окончания процесса. Любителем Counter Strike такие ощущения и не снились Каждый раз во время очередной ошибки облом, поиск выхода, какие-то исправления, снова make. Но на этот раз повезло: огромный компилятор скомпилировался (каламбурчик-с) не пикнув. Делаем make install, убеждаемся, что работает (на уровне демонстрации версии):
Может я и поторопился заявить, что всё работает. Сначала нужно бы удалить старый компилятор, но это детали, которые каждый может решить самостоятельно.
Итак, компилятор собран и демонстрирует признаки жизни. Попробуем воспользоваться им, например, собрать самую главную библиотеку большинства дистрибутивов Linux — glibc. Скачиваем последнюю версию, распаковываем, запускаем ./configure… Обана! Вылетает с ошибкой. Причем непонятно, в чем она заключается. Написано, что детально сообщение о ней можно посмотреть в файле config.log. Что-ж, смотрим что в нем, обнаруживаем строку, где сказано, что невозможно запустить некую программу со странным именем as. Немного гугления — и вот уже понятно, что as — это GNU Ассемблер и получить его можно в составе пакета
ftp.gnu.org/gnu/binutils/binutils-2.20.1.tar.bz2
Скачиваем, распаковываем, собираем, устанавливаем.
На этот раз дело пошло повеселее: ./configure… Проскочили без ошибок? Нет Пишет, что сборку нужно вести в каком-то особом каталоге. Небывалое дело… Гуглим, выясняем, что
mkdir /glibc-build
cd /glibc-build
/glicb-2.11.1/configure
Ну? Опять двадцать пять! Пишет, что нужно указать каталог установки /usr, а не /usr/local (по умолчанию). ОК, нам не жалко. Вспоминаем нужный ключ с помощью
/glicb-2.11.1/configure --help
Ага, вот как надо:
/glicb-2.11.1/configure --prefix=/usr
Пошло дело? Да нет, есть еще проблемка: не найдены исходники ядра. Значит нужно указать в опциях:
/glicb-2.11.1/configure --prefix=/usr CPPFLAGS="-I/usr/src/linux/include"
Уф… ./configure проскочили. Как насчет make? Вот блин… Выдает какую-то ошибку про неверные строки в каких-то ассемблерных файлах.
./sysdeps/i386/fpu/s_frexp.S: Assembler messages:
./sysdeps/i386/fpu/s_frexp.S:66: Error: invalid identifier for ".ifdef"
Копируем сообщение об ошибке в строку Google, немного вкуриваем сообщения разнообразных буржуйских форумов — и вот уже понятно, что не только у нас такое случалось. Нужно применить к библиотеке патч, касающийся модели процессора. Вот текст патча (выкладываю для отечественных пользователей, поскольку на русском нет вообще ничего толкового об этой ошибке):
diff -Naur glibc-2.11.1-orig/nptl/sysdeps/pthread/pt-initfini.c
glibc-2.11.1/nptl/sysdeps/pthread/pt-initfini.c
--- glibc-2.11.1-orig/nptl/sysdeps/pthread/pt-initfini.c 2009-12-08 20:10:20.000000000 +0000
+++ glibc-2.11.1/nptl/sysdeps/pthread/pt-initfini.c 2010-04-17 02:24:02.000000000 +0100
@@ -45,6 +45,11 @@
/* Embed an #include to pull in the alignment and .end directives. */
asm ("\n#include \"defs.h\"");
+asm ("\n#if defined __i686 && defined __ASSEMBLER__");
+asm ("\n#undef __i686");
+asm ("\n#define __i686 __i686");
+asm ("\n#endif");
+
/* The initial common code ends here. */
asm ("\n/*...@header_ends*/");
diff -Naur glibc-2.11.1-orig/sysdeps/unix/sysv/linux/i386/sysdep.h
glibc-2.11.1/sysdeps/unix/sysv/linux/i386/sysdep.h
--- glibc-2.11.1-orig/sysdeps/unix/sysv/linux/i386/sysdep.h 2009-12-08 20:10:20.000000000 +0000
+++ glibc-2.11.1/sysdeps/unix/sysv/linux/i386/sysdep.h 2010-04-17 02:24:02.000000000 +0100
@@ -29,6 +29,10 @@
#include <dl-sysdep.h>
#include <tls.h>
+#if defined __i686 && defined __ASSEMBLER__
+#undef __i686
+#define __i686 __i686
+#endif
Признаюсь честно: я не умею уверенно работать с патчами. Зато я умею соображать головой При анализе этого диковатого кода можно догадаться, что в файл nptl/sysdeps/pthread/pt-initfini.c нужно в районе 45-й строки добавить строки
asm ("\n#if defined __i686 && defined __ASSEMBLER__");
asm ("\n#undef __i686");
asm ("\n#define __i686 __i686");
asm ("\n#endif");
а в файле sysdeps/unix/sysv/linux/i386/sysdep.h — строки
+#if defined __i686 && defined __ASSEMBLER__
+#undef __i686
+#define __i686 __i686
+#endif
Что они обозначают — понятия не имею ;) Знаю только, что после внесения правки процесс компиляции совершился без ошибок (как раз пока я писал этот топик).
Осталось выполнить make install, но мы не только выполним, но и перевыполним: создадим модуль для Slax:
mkdir /tmp/glibc
sudo make DESTDIR=/tmp/glibc install
dir2lzm /tmp/glibc $SLAX_HOME/slax/base/glibc.lzm
Ну как квест? Это вам не ботов по бассейну шугать
Если новички не поняли этот топик до конца — ничего страшного, дело наживное. И все-таки при случае попробуйте собрать какой-нибудь несложный пакет. В случае удачи будете чувствовать себя в мире Linux гораздо увереннее.
Комментарии (23)
RSS свернуть / развернутьПотом конечно hardcore action, но бывают вещи и похуже для компиляции, например, сборка из исходников OpenCASCADE и т.п. специализированных больших платформ
Sergei_T
Комп PC 386 вот памяти сколько был не помню. Около 50 зависимостей часть из которых вылезала на этапе сборки + пришлось пару скриптов дл я сборки руками править. Окончательная компиляция занимала около 6-8 часов.
А еще сборка пакета FElt, собирал его на разных платформах (Linux, Solaris, Windows, Cygwin) всек время что-нибудь вылазило с зависимосттями глубиной на 3-4 уровня.
Engineer
Sergei_T
Теперь я морально готов поставить openFoam))))
ksandras
Sergei_T
yababay
Ну я в последнее время редко что компилирую. А прирост производительности кстати чтобы был — нужно тебе поиграться с флагами оптимизации
Sergei_T
FREExLOADER
Sergei_T
FREExLOADER
Sergei_T
Только в моем случае — Slackware. Это Gentoo для ленивых .
yababay
Sergei_T
Ответ гентушников:
Помогло Почувствуйте разницу, как говорится
yababay
или где-то левый include
Sergei_T
+#undef __i686
+#define __i686 __i686
+#endif
Перевод:
Если уже были предопределены функции(в машинных кодах)
__i686 И __ASSEMBLER__, ТО
Исключить из сборки модуль __i686
И ПОДКЛючить модуль __i686__i686
все.
Markony
Если определены одновременно макросы __i686 и __ASSEMBLER__, то значение идентификатора __i686 обнулить (сделать пустым), а потом положить туда вместо какой-то прежней неправильной байды буковки "__i686". Как они будут обрабатываться дальше — тайна сия велика есть (для меня по крайней мере).
Я не силен в препроцессинге C и меня эта конструкция несколько удивляет — идентификатору _i686 присваивается значение _i686. Но это реально работает .
yababay
Если есть два способа, простой и сложный, то выбирай сложный, так как он проще простого способа, который тоже сложный, но ещё и кривой
bash.org.ru/quote/406702
yababay
Markony
KAK-TO TAK ...
Markony
yababay
Markony
Вправьте кто-нибудь топик!
ahmetzyanov_d
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.