Distcc в Gentoo
– А где Gentoo, он еще не пришел? – Нет, он еще только собирается… © Byron, linux.org.ru
Небольшое введение. Как должно быть известно большинству читателей, замечательная во всех отношениях система Gentoo имеет одно весьма утомительное качество: время на сборку пакетов из исходных кодов может быть достаточно велико, особенно на слабых машинах.
Для решения этой проблемы существует два известных мне вменяемых способа. Первый – это использование бинарных пакетов (которые предварительно нужно собрать на другой машине). Второй – это использование распределенной компиляции. Оба метода имеют свои преимущества и недостатки, и оба совершенно не препятствуют друг другу.
В этой статье, как можно догадаться из названия, рассматривается второй способ.
В общих чертах смысл распределенной компиляции можно изложить таким образом: части исходных текстов (а точнее, отдельные .c или .cpp файлы) посылаются с “клиента” по сети вместе с заголовочными файлами и компилируются на удаленной машине. Полученный объектный файл возвращается к “клиенту”. В последствии все объектные файлы линкуются на машине “клиента”. Число удаленных машин (“серверов”) в принципе ничем не ограничено, разве что бюджетом ;)
Исходя из описаной схемы несложно догадаться, что все учавствующие в компиляции машины должны по меньшей собирать исходники под одну и ту же архитектуру, и крайне желательно – иметь одинаковые версии компонент тулчейна (binutils, glib, gcc, linux-headers), по очевидным причинам.
В этой статье я хочу рассмотреть “сферичиских коней в ваккууме”: “клиент” и все “серверы” имеют одну и ту же архитектуру, и одинаковые версии тулчейна.
Тогда, собственно, настройка distcc оказывается достаточно простой. Для начала, на каждом учавствующем в компиляции хосте (то есть и на “клиенте” и на “серверах”) нужно установить distcc
emerge -a distcc
Затем, настроить portage на использование distcc
nano /etc/make.conf
MAKEOPTS="-jN"
FEATURES="distcc"
Здесь N – это число, рассчитываемое в общем случае следующим образом: (число процессорных ядер учавствующих хостов)*2-2 Таким образом, если имеется две двухядерных машины (“клиент” и “сервер”), то N=6 Это не истина в последней инстанции и с другими значениями N результаты могут быть лучше.
Дальше нужно настроить “сервера”. На каждом из них нужно отредактировать файл /etc/conf.d/distccd дабы разрешить “клиенту” или, если уж на то пошло, “клиентам” подключаться к серверу компиляции:
nano /etc/conf.d/distccd
DISTCCD_OPTS="${DISTCCD_OPTS} --allow 192.168.0.0/24"
Ясно, что 192.168.0.0/24 нужно заменить на IP клиента или адрес Вашей подсети, или… в конфиге есть примеры, и эта операция не должна вызывать затруднений.
Далее, на каждом “сервере” нужно запустить distccd:
/etc/init.d/distccd start
По желанию так же можно запускать его вместе с системой:
rc-update add distccd
Наконец, последняя операция – настроить список “серверов” на “клиенте”. Проще всего это сделать, отредактировав файл /etc/distcc/hosts:
nano /etc/distcc/hosts
localhost
server1,lzo,cpp
server2,lzo,cpp
...
Здесь localhost – ключевое слово, означающее локальную компиляцию. На очень медленных машинах при наличии намного более быстрых серверов, эту строчку лучше убрать. server1, server2, … – имена или IP-адреса серверов. lzo включает пакование исходников перед пересылкой cpp включает препроцессинг на “серверах” (особо имеет смысл на слабых машинах), требует lzo
Собственно, с базовым случаем разобрались. Запускать emerge теперь, правда, придется через обертку:
pump emerge ...
Однако с этим можно и смириться.
Осталось только заметить, что понятия “клиент” и “сервер” не просто так взяты в кавычки. Дело в том, что совершенно ничто не мешает поднять на “клиенте” distccd, а “сервер” настроить и как “клиента”. На всякий случай приведу пример: имеются host1 и host2. На каждом запущен distccd, разрешающий подключения с другого. /etc/distcc/hosts на каждом имеет записи localhost и второго хоста. И на обоих portage настроен на distcc. В таком случае оба хоста при вызове emerge будут радостно использовать ресурсы соседа. Надеюсь, идея понятна.
Так же замечу, что совершенно ничто не препятствует использовать и банальный make с distcc. Для этого всего лишь надо изменить пути поиска таким образом, чтобы ссылки distcc находились раньше, чем gcc, но после ccache, если он установлен. Добиться этого можно, например, так:
export PATH="/usr/lib/ccache/bin:/usr/lib/distcc/bin:${PATH}"
Эту строку можно, например, добавить в .bashrc или куда-то в подобное место.
В следующей статье расскажу, как настроить распределенную кросс-компиляцию, то есть что делать, если один из хостов имеет архитектуру x86_64, а другой i386/i586/i686, или более экзотические варианты (как то комбинации ARM-SPARC-ia64).
Материалы по теме не по-русски: Gentoo Distcc Documentation man distcc Материалы по теме по-русски мне как-то не очень понравились. Поэтому решил сделать свое :)