Distcc/Кросс-компиляция

From Gentoo Wiki
< Distcc
Jump to:navigation Jump to:search
This page is a translated version of the page Distcc/Cross-Compiling and the translation is 93% complete.
Outdated translations are marked like this.


Данное руководство покажет, как настроить distcc для кросс-компиляции между различными архитектурами процессоров.

Кросс-компиляция с distcc

Введение

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

Этот руководство содержит указания как настроить distcc для компиляции на различных архитектурах

Устанавливаем необходимые утилиты

Сперва нужно установить crossdev на всех машинах, которые будут вовлечены в процесс компиляции. crossdev — это инструмент, облегчающий сборку кросс-платформенных toolchain’ов. Использовать его просто: crossdev -t sparc соберет полный cross-toolchain для архитектуры Sparc. Он включает binutils, gcc, glibc и linux-headers.

Вам необходимо установить подходящий toolchain для кросс-компиляции на все участвующие машины. Если вам нужно больше информации, попробуйте запустить crossdev --help.

Если вы хотите произвести более точную настройку cross-toolchain’а, то вот скрипт, который генерирует команду с точными версиями toolchain-пакетов для сборки на вспомогательных машинах (скрипт нужно запускать на целевой машине).

КОД Сценарий для тонкой настройки инструментов распределенной разработки
#!/bin/bash
BINUTILS_VER=$(qatom -F '%{PV}' $(qfile -v $(realpath /usr/bin/ld) | cut -d' ' -f1))
GCC_VER=$(qatom -F '%{PV}' $(qfile -v $(realpath /usr/bin/gcc) | cut -d' ' -f1))
KERNEL_VER=$(qatom -F '%{PV}' $(qlist -Ive sys-kernel/linux-headers))
LIBC_VER=$(qatom -F '%{PV}' $(qlist -Ive sys-libs/glibc))
echo "crossdev --b '~${BINUTILS_VER}' --g '~${GCC_VER}' --k '~${KERNEL_VER}' --l '~${LIBC_VER}' -t $(portageq envvar CHOST)"

Затем необходимо установить distcc на все машины, которые будут вовлечены в процесс. Это включает и машину, на которой будет запущен emerge, и машины с кросс-компиляторами. Посмотрите документацию Gentoo по Distcc для более подробной информации по настройке и использованию distcc.

Заметка
Текущие версии crossdev имеют флаг -S (--stable) для установки только стабильных версий компиляторов. (Т. е. crossdev -t i686-pc-linux-gnu --stable --ex-gcc --ex-gdb --portage --pretend). Без этой опции, crossdev установит пакет с последним экспериментальным компилятором! В противном случае, выше предложенный скрипт не нужен, если специальные версии инструментов и/или заголовков замаскированы.

Специфичные для архитектур замечания

Заметка
Получить имя архитектуры можно, взглянув на переменную CHOST с целями компилятора в /etc/make.conf. Когда идет искажение имени архитектуры для опции crossdev -t, crossdev будет устанавливать инструменты, используя искаженное имя для имен директорий в /usr (т. е. /usr/i686-pc-linux-gnu/, /usr/i686-linux-gnu/, ...). Что бы исправить это, определите каждое искаженное имя архитектуры/директории и удалите через crossdev --clean или вручную, удалив эти директории из системы.

Подархитектуры Intel x86

Если вы проводите кросс-компиляцию между различными субархитектурами процессоров Intel x86 (например, i586 и i686), то, как и в других случаях, вам нужно собрать полный cross-toolchain для желаемого CHOST, иначе компиляция завершится неудачей. Это потому, что субархитектурам i586 и i686 соответствуют разные CHOST, несмотря на то что обе относятся к "x86". Помните об этом, когда собираете свои cross-toolchain’ы. Если, например, целевая платформа — i586, то потребуется собрать cross-toolchain’ы для i586 на вспомогательных i686-машинах.

SPARC

При использовании crossdev -t sparc может появиться одна из следующих ошибок:

КОД Ошибки, появляющиеся при запуске crossdev -t sparc
linker with -z relro support required
support for the tls_model attribute is required
this configuration requires -mlong-double-128 support

Если это происходит, попробуйте использовать другую команду:

user $crossdev --lenv "CC=sparc-unknown-linux-gnu-gcc" -t sparc-unknown-linux-gnu

Настройка distcc для корректной кросс-компиляции

Заметка
The workaround as described in this section is not needed any more since distcc-3.2, as the functionality for replacing the calls to the compiler with the full compiler name has since then been implemented in distcc itself.

При настройках distcc по умолчанию кросс-компиляция не будет работать как положено. Проблема в том, что многие сборки вызывают просто gcc вместо полного имени компилятора (например, sparc-unknown-linux-gnu-gcc). Когда такая сборка распределяется на вспомогательную машину с distcc, вызывается нативный компилятор вместо вашего абсолютно нового кросс-компилятора.

К счастью, для этой небольшой проблемы существует обходное решение. Все, что требуется, это оберточный скрипт и несколько символьных ссылок на компьютере, с которого вызывается emerge. Будем использовать в качестве примера компьютер архитектуры Sparc. Ниже, где бы вы ни видели текст sparc-unknown-linux-gnu, подразумевается ваше значение CHOST (x86_64-pc-linux-gnu для AMD64, к примеру). Каталог /usr/lib/distcc/bin после первой установки distcc выглядит следующим образом:

Заметка
Следующие инструкции предназначены для выполнения на тех компьютерах, где будет запускаться emerge. Не выполняйте эти шаги на вспомогательных хостах.
root #cd /usr/lib/distcc/bin
root #ls -l
total 0
lrwxrwxrwx  1 root root 15 Dec 23 20:13 c++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 cc -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 g++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 gcc -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 sparc-unknown-linux-gnu-c++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 sparc-unknown-linux-gnu-g++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 sparc-unknown-linux-gnu-gcc -> /usr/bin/distcc

Проделаем следующие шаги:

root #rm c++ g++ gcc cc

Затем создадим новый скрипт на этой машине. Запустите свой любимый текстовый редактор и создайте файл со следующим текстом, сохранив его как sparc-unknown-linux-gnu-wrapper. Помните о том, что значение CHOST (в данном случае sparc-unknown-linux-gnu) нужно заменить на реальный CHOST данного компьютера, т. е. того, на котором будет запускаться emerge.

КОД Новый оберточный скрипт
#!/bin/bash
exec /usr/lib/distcc/bin/sparc-unknown-linux-gnu-g${0:$[-2]} "$@"

Далее, сделаем скрипт исполняемым и создадим соответствующие символьные ссылки:

root #chmod a+x sparc-unknown-linux-gnu-wrapper
root #ln -s sparc-unknown-linux-gnu-wrapper cc
root #ln -s sparc-unknown-linux-gnu-wrapper gcc
root #ln -s sparc-unknown-linux-gnu-wrapper g++
root #ln -s sparc-unknown-linux-gnu-wrapper c++

После этого /usr/lib/distcc/bin будет выглядеть следующим образом:

root #ls -l
total 4
lrwxrwxrwx  1 root root 25 Jan 18 14:20 c++ -> sparc-unknown-linux-gnu-wrapper
lrwxrwxrwx  1 root root 25 Jan 18 14:20 cc -> sparc-unknown-linux-gnu-wrapper
lrwxrwxrwx  1 root root 25 Jan 18 14:20 g++ -> sparc-unknown-linux-gnu-wrapper
lrwxrwxrwx  1 root root 25 Jan 18 14:20 gcc -> sparc-unknown-linux-gnu-wrapper
lrwxrwxrwx  1 root root 15 Nov 21 10:42 sparc-unknown-linux-gnu-c++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Nov 21 10:42 sparc-unknown-linux-gnu-g++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Jul 27 10:52 sparc-unknown-linux-gnu-gcc -> /usr/bin/distcc
-rwxr-xr-x  1 root root 70 Jan 18 14:20 sparc-unknown-linux-gnu-wrapper
Заметка
В новых версиях distcc следующие шаги не нужны. Можно установить distcc на клиенте с USE-флагом crossdev чтобы получить тот же самый результат.

Далее нужно позаботиться о том, чтобы обертки оставались доступными после обновлений distcc, поскольку символьные ссылки при обновлении перезаписываются. Можно сделать это с помощью файла /etc/portage/bashrc, примерно такого:

ФАЙЛ /etc/portage/bashrc
case ${CATEGORY}/${PN} in
                 sys-devel/distcc | sys-devel/gcc | sys-devel/clang)
			if [ "${EBUILD_PHASE}" == "postinst" ]; then
				/usr/local/sbin/distcc-fix &
			fi
		;;
esac

Затем создайте этот файл:

ФАЙЛ /usr/local/sbin/distcc-fix
#!/bin/bash                     
sleep 20
# We extract $TUPLE from make.conf to avoid editing the script for each architecture.
TUPLE=$(portageq envvar CHOST)
GCC_VER=$(gcc-config -c|cut -d "-" -f5)
cd /usr/lib/distcc/bin
rm cc c++ gcc g++ gcc-${GCC_VER} g++-${GCC_VER} ${TUPLE}-wrapper
echo '#!/bin/bash' > ${TUPLE}-wrapper
echo "exec ${TUPLE}-g\${0:\$[-2]}" "\"\$@\"" >> ${TUPLE}-wrapper
chmod 755 ${TUPLE}-wrapper
ln -s ${TUPLE}-wrapper cc
ln -s ${TUPLE}-wrapper c++
ln -s ${TUPLE}-wrapper gcc
ln -s ${TUPLE}-wrapper g++
ln -s ${TUPLE}-wrapper gcc-${GCC_VER}
ln -s ${TUPLE}-wrapper g++-${GCC_VER}

If you ARE using clang:

ФАЙЛ /usr/local/sbin/distcc-fix
#!/bin/bash	                
#clang aware, now your >chromium-65 ebuilds will use distcc just like before ;) 
sleep 20
# We extract $TUPLE from make.conf to avoid editing the script for each architecture.
TUPLE=$(portageq envvar CHOST)
GCC_VER=$(gcc-config -c|cut -d "-" -f5)
CLANG_VER=$(clang --version|grep version|cut -d " " -f3|cut -d'.' -f1,2)
cd /usr/lib/distcc/bin
rm cc c++ gcc g++ gcc-${GCC_VER} g++-${GCC_VER} clang clang++ clang-${CLANG_VER} clang++-${CLANG_VER} ${TUPLE}-wrapper ${TUPLE}-clang-wrapper 
echo '#!/bin/bash' > ${TUPLE}-wrapper
echo "exec ${TUPLE}-g\${0:\$[-2]}" "\"\$@\"" >> ${TUPLE}-wrapper
echo '#!/bin/bash' > ${TUPLE}-clang-wrapper
echo "exec ${TUPLE}-\$(basename \${0}) \"\$@\"" >> ${TUPLE}-clang-wrapper
chmod 755 ${TUPLE}-wrapper
chmod 755 ${TUPLE}-clang-wrapper
ln -s ${TUPLE}-wrapper cc
ln -s ${TUPLE}-wrapper c++
ln -s ${TUPLE}-wrapper gcc
ln -s ${TUPLE}-wrapper g++
ln -s ${TUPLE}-wrapper gcc-${GCC_VER}
ln -s ${TUPLE}-wrapper g++-${GCC_VER}
ln -s ${TUPLE}-clang-wrapper clang
ln -s ${TUPLE}-clang-wrapper clang++
ln -s ${TUPLE}-clang-wrapper clang-${CLANG_VER}
ln -s ${TUPLE}-clang-wrapper clang++-${CLANG_VER}

Назначьте правильные разрешения:

root #chmod 755 /usr/local/sbin/distcc-fix

Поздравляем! Теперь у вас (надеемся) есть работающая установка cross-distcc.

Как это работает

При вызове distcc проверяет, как его вызвали (например, i686-pc-linux-gnu-gcc, sparc-unknown-linux-gnu-g++, и т. п.). Затем, когда distcc распределяет компиляцию на вспомогательную машину, он передает название, с которым был вызван. Далее, демон distcc на вспомогательной машине ищет исполняемый файл с подобным именем. Если он видит только gcc, то будет искать gcc, что, скорее всего, будет нативным компилятором вспомогательной машины. Это сработает только если на ней такая же архитектура, как и на компьютере, с которого запускался emerge. Когда отправляется полное имя компилятора, (например, sparc-unknown-linux-gnu-gcc), путаница исключена.

Устранение проблем

В этом разделе приведены распространенные проблемы, связанные с использованием distcc для кросс-компиляции.

Ошибки компиляции в distccd на удаленном компьютере

При получении сообщения COMPILE ERRORS в файле /var/log/distccd.log на удаленном компьютере, посмотрите описанные выше заметки касательно определения корректного имени архитектуры (т. е. crossdev -t $TARGET).

Другое решение заключается в удалении и переустановке crossdev, используя опцию crossdev --clean, или в полной переустановке кросс компилятора, перед которой нужно убедиться, что /usr/$TARGET больше нет.

Возможно так же поступить мудро и, просмотрев файл /usr/$TARGET/etc/portage/make.conf на удаленном компьютере, убедиться в том, что переменная CFLAGS аналогична на всех компьютерах или хостах, выполняющих операции компилятора. Также убедитесь, что USE-флаги достаточны для кросс-компилятора: например, если собрали GCC с USE=graphite на клиенте, то также необходима строка на вроде cross-i686-pc-linux-gnu/gcc graphite в /etc/portage/package.use.

Failed to exec $TARGET-unknown-linux-gnu-gcc: No such file or directory

Скрипты могут не запуститься, даже с корректными разрешениями:

КОД Ошибка выполнения скриптов
distcc[6195] (dcc_execvp) ERROR: failed to exec i686-unknown-linux-gnu-gcc: No such file or directory

Для разрешения этого, убедитесь, что скрипты созданы с полным именем архитектуры:

user $ls -alh /usr/lib/distcc/bin/c++
/usr/lib/distcc/bin/c++ ->./i686-pc-linux-gnu-wrapper

См. также

  • Crossdev — a set of bash scripts that utilize emerge to provide a system integrated cross-compilation capability.

This page is based on a document formerly found on our main website gentoo.org.
The following people contributed to the original document: Andrew Gaffney, Joshua Saddler
They are listed here because wiki history does not allow for any external attribution. If you edit the wiki article, please do not add yourself here; your contributions are recorded on each article's associated history page.