Usando multiarch en debian para emular binarios de RISC-V

2020/03/22

TL;DR: El enfoque descripto a continuación no funcionó como era esperado respecto a la reinstalación de paquetes en arquitectura riscv64.

NO UTILIZAR

Motivación

Como seguro quedó manifestado en posts anteriores estoy interesado en el ISA RISC-V. Para evaluar el avance de la arquitectura RISC-V en debian que se lleva adelante en debian ports -y eventualmente ayudar con el reporte de bugs- es que decidí habilitar el soporte multiarch de debian para RISC-V.

Cambio a debian sid

El primer requerimiento fuerte en el sistema operativo es la necesidad de pasar a debian sid ya que el repositorio de RISC-V en debian ports solo tiene disponibles las distribuciones sid y experimental.

Respecto al cambio anterior los motivos a favor (PROS) y en contra (CONS) evaluados fueron entre otros:

PROS:

CONS:

Si bien no muy estrictas o profundas los motivos anteriores está claro que no conviene pasar a sid y es mejor seguir en debian stable o en su defecto testing.

Para pasar el sistema a sid se comienza con debian stable o testing, se modifican los repositorios, reempazando las lineas en /etc/apt/sources.list por

deb [arch=amd64] http://deb.debian.org/debian sid main non-free contrib

Luego se actualizan las listas de paquetes y se realiza un dist-upgrade:

$ sudo apt-get clean
$ sudo apt-get update
$ sudo apt-get dist-upgrade -V --purge --autoremove

Si bien en la wiki de debian se indica realiza un full-upgrade, en la documentación de apt-get esta opción ya no se encuentra, siendo la opción equivalente dist-upgrade.

Luego de pasar a sid es posible que sea necesario ajustar el sistema, más especificamente el marcar que paquetes fueron instalados automáticamente y cuales de forma manual. En mi caso, muchas librerías o paquetes que deberían estar marcados como instalados automáticamente estaban marcados como instalados de forma manual.

Algunos tips para corregir la situación anterior utilizando los programas apt-mark y aptitude:

Lo malo de tener que revisar los paquetes instalados: unas tres horas revisando todos los paquetes del sistema. Lo bueno: se tiene un mejor conocimiento del sistema, los paquetes instalados en este y para que son utilizados.

Se instalan como es sugerido en la wiki de debian unstable los paquetes apt-listbugs y apt-listchanges para verificar que una actualización no romperá el sistema:

$ sudo apt-get install -V apt-listbugs apt-listchanges

Luego al empezar a utilizar debian sid ya empezaron los problemas:

Ejecución de programas compilados para RISC-V utilizando QEMU

Ya que la arquitectura del sistema es amd64 y queremos ejecutar programas compilados para la arquitectura riscv debemos instalar QEMU para que los programas sean emulados. También se debe utilizar el módulo del kernel binfmt-support que según la cabecera de un archivo utiliza un programa que haya sido registrado previamente para asociado para ejecutarlo.

$ sudo apt-get install -V qemu-user-static binfmt-support
$ sudo update-binfmts --display | grep riscv
qemu-riscv32 (enabled):
 interpreter = /usr/bin/qemu-riscv32-static
qemu-riscv64 (enabled):
 interpreter = /usr/bin/qemu-riscv64-static

En las lineas anteriores instalamos los programas necesarios y nos aseguramos que qemu sea utilizado para ejecutar binarios de RISC-V.

Se prefirió instalar el paquete qemu-user-static en lugar de qemu-user por el caso en que se utilice un chroot para ejecutar un binario de RISC-V. Por más detalles al respecto ver por ejemplo el post Transparently running binaries from any architecture in Linux with QEMU and binfmt_misc.

Agregado de architectura RISC-V de debian ports en el sistema

Anteriormente se configuró el sistema para que puedan ejecutarse directamente programas compilados para RISC-V. Ahora falta configurar el sistema para agregar la arquitectura riscv64 al sistema y que puedan instalarse paquetes de los repositorios. Ya que la arquitectura riscv64 no está soportada “oficialmente” sinó a través de debian ports debe agregarse primero el keyring, luego agregarse la arquitectura y por último el repositorio de debian ports:

$ sudo apt-get install -Vy debian-ports-archive-keyring
$ sudo dpkg --add-architecture riscv64
$ echo 'deb [arch=riscv64] http://ftp.ports.debian.org/debian-ports/ sid main' \
    | sudo tee /etc/apt/sources.list.d/riscv64.list > /dev/null
$ sudo apt-get update

Notas:

  1. ftp.ports.debian.org es más rápido al descargar que deb.debian.org
  2. No se instalan los paquetes libc6:riscv64 y libstdc++6:riscv64 ya que cuando algún ejecutable dependa de ellos deberían ser instalados por defecto, aunque en algunas guías de multiarquitectura son instalados.

Prueba de instalación y ejecución de programa de arquitectura riscv64

Como prueba se instalará y ejecutará el programa ed (editor de lineas, predecesor de vi).

$ sudo apt-get install -V ed:riscv64
$ ed

En otra terminal se verifica que está ejecutandose ed con qemu:

$ ps aux | grep /bin/ed
jmpc       21832  0.0  0.0 126780  7860 pts/1    Sl+  02:29   0:00 /usr/bin/qemu-riscv64-static /usr/bin/ed
jmpc       21848  0.0  0.0   6156   908 pts/3    S+   02:30   0:00 grep /bin/ed

Problemas al querer instalar programas

Ya que no es muy común que utilice el programa ed, intenté reinstalar el programa Eye of Mate. Para ello primero eliminé la versión instalada de arquitectura amd64 y pasé a instalar la versión de arquitectura riscv64:

$ sudo apt purge -V eom
$ sudo apt install -V eom:riscv64
Reading package lists... Done
Building dependency tree-------
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 eom:riscv64 : Depends: eom-common:riscv64 (= 1.24.0-1) but it is not installable
               Depends: gir1.2-eom-1.0:riscv64 but it is not going to be installed
               Depends: librsvg2-common:riscv64 (>= 2.36.2) but it is not going to be installed
               Depends: mate-desktop-common:riscv64 but it is not installable
               Depends: libgl1-mesa-glx:riscv64 but it is not going to be installed or
                        libgl1:riscv64 but it is not going to be installed
               Depends: libgdk-pixbuf2.0-0:riscv64 (>= 2.25.2) but it is not going to be installed
               Depends: libgtk-3-0:riscv64 (>= 3.21.5) but it is not going to be installed
               Depends: libjpeg62-turbo:riscv64 (>= 1.3.1) but it is not going to be installed
               Depends: libmate-desktop-2-17:riscv64 (>= 1.18) but it is not going to be installed
               Depends: libpeas-1.0-0:riscv64 (>= 1.0.0) but it is not going to be installed
               Depends: librsvg2-2:riscv64 (>= 2.36.2) but it is not going to be installed
               Depends: libxml2:riscv64 (>= 2.7.4) but it is not going to be installed
E: Unable to correct problems, you have held broken packages.

Y aquí esta el problema: ¿porqué eom-common:riscv64 es no instalable si es de arquitectura all y no tiene archivos que dependan de la arquitectura?.

La respuesta puede encontrarse bajo el punto Dependencies involving Architecture: all packages, de la wiki MultiarchSpec:

Dependencies involving Architecture: all packages

Pre-multiarch, architecture-dependent packages may depend on Architecture: all packages and assume that the transitive dependencies will be resolved using packages of the same architecture or other packages that are Architecture: all. To avoid breaking this assumption, Architecture: all packages will, at least initially, be treated as equivalent to packages of the native architecture for all dependency resolution. This means that for an Architecture: all package to satisfy the dependencies of a foreign-architecture package, it must be marked Multi-Arch: foreign or Multi-Arch: allowed.

De lo anterior, si un paquete con datos tiene en los campos del archivo de control Architecture: all pero le falta Multi-Arch: foreign, se tomará como que su arquitectura es la del sistema. En el caso del paquete eom-common, se tiene en https://sources.debian.org/src/eom/1.24.0-1/debian/control/:

Package: eom-common
Architecture: all

Lo que de hecho convierte al paquete en eom-common:amd64 para apt.

La solución a lo anterior es como se vió más arriba que al paquete se le agregue Multi-Arch: foreign. Pero no sería solo a ese y también se encuentra que paquetes como el libgtk-3-0 no permiten instalar en otra arquitectura, como se puede ver en https://sources.debian.org/src/gtk+3.0/3.24.17-1/debian/control/:

Package: libgtk-3-0
Architecture: any
Multi-Arch: same

Por todo lo anterior es que el espiritu de querer utilizar paquetes de arquitectura riscv64 no se estaría consiguiendo.

¿Vuelta a testing?

Ya que estaba realmente interesado en instalar programas utilizando la arquitectura riscv64 asumí el “riesgo” de pasar a la distribución unstable. Ahora, a raíz de que no funcionó lo anterior me pesa estar utilizando la distribución unstable ya que actualiza muy seguido y no hay actualizaciones de seguridad. Por ello y porque no deseo estar reinstalando el sistema es que voy a probar de pasar a testing.

Para ello simplemente voy a cambiar el archivo /etc/apt/sources.list, pasando de sid a testing y actualizando la lista de paquetes:

$ sudo sed -i 's# sid # testing #' /etc/apt/sources.list
$ sudo apt-get clean
$ sudo apt-get update

¿Porqué solo realizo el cambio anterior?: Según se indica en las faqs de debian, los paquetes luego de 5 días son migrados de unstable a testing, por lo cual solo tengo que esperar unos cuantos días para que se actualicen todos los paquetes del sistema con la versión de testing.

En todo caso, cuando hice esta prueba sabía que como peor caso iba a tener que reinstalar el sistema y me pareció aceptable. Ahora simplemente estoy retrasando un tiempo esa decisión/tarea si es que estar en testing no me conforma.