Эмуляция архитектур, отличных от x86_64

!!! Пользователь, помни, трансляция одних процессорных команд в другие является очень ресурсоёмкой операцией. Если можешь - пользуйся кросс-компилятором. !!!

Для того, чтобы произвести сборку пакетов под не родную архитектуру на Gentoo, например на хосте amd64 для arm64, требуется собрать qemu с хитрыми флагами, а так же наложить один интересный “патч” на пакеты внутри билдера, но обо всё по порядку.

Сборка системы виртуализации

Рассказывать про то, что виртуализация должна быть включена в ядре и прочие очевидные вещи я, пожалуй, в этом топике не буду, так что перейдём сразу к сборке qemu. Итак, сначала добавляем USE флаг static-user, а так же указываем требуемые нам архитектуры QEMU, которые будем использовать:

# echo 'app-emulation/qemu static-user' > /etc/portage/package.use/qemu
# echo 'QEMU_SOFTMMU_TARGETS="aarch64 arm x86_64"' >> /etc/portage/make.conf
# echo 'QEMU_USER_TARGETS="aarch64 arm x86_64"' >> /etc/portage/make.conf

После чего как обычно собираем пакет:

# emerge -avq qemu

В процессе конечно могут вылезти всякие блокировки и прочие интересные моменты в плане маскировки пакетов, но emerge достаточно детально пишет почему и что произошло, так что разобраться не составит труда.

Если приложение успешно вкатилось в систему - делаем из него пакет:

# quickpkg qemu

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

# zgrep 'CONFIG_BINFMT_MISC' /proc/config.gz

Если в выхлопе мы видим 'CONFIG_BINFMT_MISC=y' или 'CONFIG_BINFMT_MISC=m', то всё хорошо. (В случае, когда m, надо убедиться, что модуль binfmt загружен, через lsmod)

Если на данный момент все условия, описанные выше, выполнены, то остаётся только запустить сервис binfmt и зарегистрировать нужные архитектуры с помощью команды:

# service binfmt start
# rc-update add binfmt boot
# echo ':aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-aarch64:' > /proc/sys/fs/binfmt_misc/register

Подготовка root для сборки

Здесь всё тоже достаточно просто - качаем нужный stage3

# wget http://mirror.yandex.ru/gentoo-distfiles/experimental/arm64/stage3-arm64-arm64-20170223.tar.bz2

Дальше подготавливаем директорию для chroot и выливаем содержимое архива

# mkdir -p /usr/aarch64-unknown-linux && cd /usr/aarch64-unknown-linux && tar -xvf /stage3-arm64-arm64-20170223.tar.bz2

Следующим шагом делаем скрипт, который будет монтировать нам нужные директории:

mount.sh
#!/bin/bash
 
mount --bind /usr/portage usr/portage
mount --bind /proc proc
mount --bind /sys sys
mount --bind /dev dev
mount --bind /dev/pts dev/pts

Кладём его в chroot, делаем его исполняемым и запускаем, после чего проверяем mount на наличие всех нужных разделов.

Устанавливаем внутрь недавно собранный нами qemu:

# ROOT=/usr/aarch64-unknown-linux/ emerge --usepkgonly --oneshot --nodeps qemu

Собственно момент истины:

# chroot /usr/aarch64-unknown-linux /bin/bash --login

После выполнения данной команды PWD должен смениться на /, а в uname -a должна светиться архитектура arm64. Поздравляю, билдер для arm64 готов.

Подводные камни

Готов, да не готов, у emerge внутри qemu для arm64 есть небольшая проблема - seccomp, который не реализован в qemu. (Пруфы) Фиксится это выключением флага seccomp у pax-utils и его пересборкой, но, опять же, и тут не так всё просто - пересобрать с emerge не получится, так что просто берём и собираем пакет с помощью ebuild.

Смотрим версию текущего pax-utils:

# emerge -pvq pax-utils

Идём в директорию портов:

# cd /usr/portage/app-misc/pax-utils

И собираем нужный нам пакет:

# ebuild pax-utils-1.1.7.ebuild merge

После этого emerge должен начать нормально работать.