This page looks best with JavaScript enabled

Distcc different architecture

 ยท  ๐ŸŽƒ kr0m

As we already know from this previous article, it is possible to configure Gentoo to distribute the compilation of ebuilds among different compilation nodes, but this method had a limitation: all machines had to share the same architecture. In this guide, we will solve this problem and make distcc compile for a different architecture than the one it is running on.

In my case, I will configure a compilation server with an amd64 architecture and a RaspBerryPi with an ARM architecture.

The first step will be to install distcc on both the compilation servers and the Rasp:

emerge -av distcc

To make the magic possible, we will have to install crossdev on the server, as it is the necessary tool to compile the toolchains for another architecture:

emerge -av sys-devel/crossdev

Now we will need to maintain two profiles, one for the server architecture and another for the Rasp architecture, for which it is necessary to have the ebuilds from /etc/portage in directory format:

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!"

We compile the toolchains:

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

If the compilation fails, we can try the following:

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

We add the IP of the RaspberryPi to the distcc configuration:

vi /etc/conf.d/distccd

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

We finished setting up distcc:

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


On the Rasp:

vi /etc/portage/make.conf

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

NOTE: N = Number of computers that will compile code (local and remote) + 1, M = Number of local cores, M is used when the compilation is local.

  • distcc โ€“> Uses distcc to distribute the compilation load ;)
  • buildpkg โ€“> Generates binary packages for all packages that are ordered to compile, so we can use this rasp as a package server.
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"

NOTE: Actually, the Rasp will not compile code for anyone, but in recent versions of distcc, we are forced to configure at least one IP, so we put 1.1.1.1

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

We will have to indicate the architecture to use to distcc, what we will do is an intermediate script:

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

We can see which compilation server the tasks are being distributed to from the rasp with:

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

And we can see from the build server which part of the software is being compiled with:

tail -f /var/log/distccd.log

NOTE: It should be noted that this does NOT work perfectly, as occasionally we may see errors of the following type on the build server:

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

However, the load distribution continues during the compilation, soโ€ฆ