Esta pagina se ve mejor con JavaScript habilitado

Distcc distinta arquitectura

 ·  🎃 kr0m

Como ya sabemos por este articulo anterior es posible configurar Gentoo para que la compilación de los ebuilds se distribuya entre diferentes nodos de compilación, pero este método tenía una limitación y es que todos los equipos debían compartir arquitectura. En este manual vamos a solventar el problema y conseguiremos que distcc compile para otra arquitectura distinta a la que está corriendo.

En mi caso voy a configurar un servidor de compilación con arquitectura amd64 y una RaspBerryPi con arquitectura ARM.

Lo primero será instalar distcc tanto en los servidores de compilación como en la Rasp:

emerge -av distcc

Para que la magia sea posible tendremos que instalar crossdev en el servidor ya que son las herramientas necesarias para compilar las toolchains para otra arquitectura:

emerge -av sys-devel/crossdev

Ahora necesitaremos mantener dos profiles, unos para la arquitectura del server y otro para la de la rasp, para ello es preciso tener los ebuilds de /etc/portage en formato directorio:

vi ~/convert-profile-to-files.sh

!/bin/bash
PROFILE_DIR="/etc/portage"
if [ ! -e ${PROFILE_DIR} ]; then
  mkdir ${PROFILE_DIR};
fi;

for PACK_DIR in package.accept_keywords package.keywords package.use package.unmask package.mask; do
  CUR_DIR="${PROFILE_DIR}/${PACK_DIR}"
  if [ ! -e ${CUR_DIR} ]; then
    mkdir ${CUR_DIR}
  fi
  if [ -e ${CUR_DIR} -a ! -d ${CUR_DIR} ]; then
    mv ${CUR_DIR} ${CUR_DIR}.moving
    mkdir ${CUR_DIR}
    mv ${CUR_DIR}.moving ${CUR_DIR}/monolithic
  fi
done
echo "Completed!"

Compilamos las toolchains:

crossdev -S -v -t armv6j-hardfloat-linux-gnueabi

Si la compialción falla podemos intentarlo del siguiente modo:

CFLAGS="-O2 -pipe" CXXFLAGS="${CFLAGS}" crossdev -S -v -t armv6j-hardfloat-linux-gnueabi

Añadimos la ip de la RaspberryPi a la configuración de distcc:

vi /etc/conf.d/distccd

DISTCCD_OPTS="${DISTCCD_OPTS} --allow IP_RASP/32"

Terminamos de configurar distcc:

touch /var/log/distccd.log
chown distcc /var/log/distccd.log
rc-update add distccd default
/etc/init.d/distccd start


En la Rasp:

vi /etc/portage/make.conf

MAKEOPTS="-jN -lM"
FEATURES="distcc buildpkg"

NOTA: N = Nº de equipos que compilarán código(local y remotos) + 1, M = Nº de cores locales, M se utiliza cuando la compilación sea local.

  • distcc –> Utiliza discc para repartir la carga de compilación ;)
  • buildpkg –> Generará paquetes binarios para todos los paquetes que ordene compilar, así podremos utilizar esta rasp como servidor de paquetes.
vi /etc/conf.d/distccd
DISTCCD_OPTS="--port 3632 --log-level notice --log-file /var/log/distccd.log -N 15 --allow 1.1.1.1"

NOTA: En realidad la Rasp no compilará código para nadie pero en versiones recientes de distcc nos obliga a configurar al menos una ip así que le metemos 1.1.1.1

/usr/bin/distcc-config --set-hosts IP_SERVER

A distcc tendremos que indicarle la arquitectura a emplear, lo que haremos será un script intermedio:

cd /usr/lib/distcc/bin
ls -la

lrwxrwxrwx 1 root root 15 abr 7 16:30 armv6j-hardfloat-linux-gnueabi-c++ -> /usr/bin/distcc
lrwxrwxrwx 1 root root 15 abr 7 16:30 armv6j-hardfloat-linux-gnueabi-g++ -> /usr/bin/distcc
lrwxrwxrwx 1 root root 15 abr 7 16:30 armv6j-hardfloat-linux-gnueabi-gcc -> /usr/bin/distcc
lrwxrwxrwx 1 root root 15 abr 7 16:30 c++ -> /usr/bin/distcc
lrwxrwxrwx 1 root root 15 abr 7 16:30 cc -> /usr/bin/distcc
lrwxrwxrwx 1 root root 15 abr 7 16:30 g++ -> /usr/bin/distcc
lrwxrwxrwx 1 root root 15 abr 7 16:30 gcc -> /usr/bin/distcc
vi /usr/lib/distcc/bin/armv6j-hardfloat-linux-gnueabi-wrapper
#!/bin/bash
exec /usr/lib/distcc/bin/armv6j-hardfloat-linux-gnueabi-g${0:$[-2]} "$@"
rm c++ g++ gcc cc
chmod a+x /usr/lib/distcc/bin/armv6j-hardfloat-linux-gnueabi-wrapper
ln -s armv6j-hardfloat-linux-gnueabi-wrapper cc
ln -s armv6j-hardfloat-linux-gnueabi-wrapper gcc
ln -s armv6j-hardfloat-linux-gnueabi-wrapper g++
ln -s armv6j-hardfloat-linux-gnueabi-wrapper c++
ls -la
lrwxrwxrwx 1 root root 15 abr 7 16:30 armv6j-hardfloat-linux-gnueabi-c++ -> /usr/bin/distcc
lrwxrwxrwx 1 root root 15 abr 7 16:30 armv6j-hardfloat-linux-gnueabi-g++ -> /usr/bin/distcc
lrwxrwxrwx 1 root root 15 abr 7 16:30 armv6j-hardfloat-linux-gnueabi-gcc -> /usr/bin/distcc
-rwx--x--x 1 root root 85 abr 7 16:34 armv6j-hardfloat-linux-gnueabi-wrapper
lrwxrwxrwx 1 root root 38 abr 7 16:35 c++ -> armv6j-hardfloat-linux-gnueabi-wrapper
lrwxrwxrwx 1 root root 38 abr 7 16:35 cc -> armv6j-hardfloat-linux-gnueabi-wrapper
lrwxrwxrwx 1 root root 38 abr 7 16:35 g++ -> armv6j-hardfloat-linux-gnueabi-wrapper
lrwxrwxrwx 1 root root 38 abr 7 16:35 gcc -> armv6j-hardfloat-linux-gnueabi-wrapper
touch /var/log/distccd.log
chown distcc /var/log/distccd.log
rc-update add distccd default
/etc/init.d/distccd start

Podemos ver a que servidor de compilación se están ditribuyendo las tareas desde la rasp con:

watch -n1 DISTCC_DIR="/var/tmp/portage/.distcc/" distccmon-text

Y podemos ver desde el server de compilación que parte del software se está compilando con:

tail -f /var/log/distccd.log

NOTA: Hay que decir que esto NO funciona como la seda, parece ser que de vez en cuando en el servidor de compilación veamos errores del tipo:

distccd[24197] (dcc_readx) ERROR: unexpected eof on fd5
distccd[24197] (dcc_r_token_int) ERROR: read failed while waiting for token "DOTI"
distccd[24197] (dcc_job_summary) client: 192.168.69.13:32797 OTHER exit:0 sig:0 core:0 ret:108 time:0ms

Pero la compilación sigue distribuyendo la carga, así que…

Si te ha gustado el artículo puedes invitarme a un RedBull aquí