Kompilacja systemu 32-bitowego przy wsparciu systemu 64-bitowego

Distcc jest genialnym narzędziem dla użytkowników Gentoo - umożliwia rozłożenie kompilacji programu na kilka maszyn i wybitne skrócenie czasu kompilacji. Problem z tym, że domyślnie nie działa w środowisku z różnymi architekturami.

W domu mam stacjonarne AMD64 i laptopa z P3 - to ostatnie to zdecydowanie nie demon kompilacji. W internecie jest dużo manuali jak zrobić kroskompilację (uwielbiam polski "poprawny" odpowiednik - kompilacja skrośna). Problem z tym, że nie działa mi "crossdev" - nie chce generować wszystkich potrzebnych narzędzi. Ale - po zastanowieniu się - po czorta osobne narzędzia do i686, skoro kompilator do amd64 potrafi generować kod i686 po dodaniu opcji -m32?

Przygotowanie wrappera

Na początek na komputerze z AMD64 potrzebujemy zrobić "udawaczkę" narzędzi do i686. Następujący plik umieść w katalogu /opt/cross32/bin i nazwij go i686-pc-linux-gnu-wrapper:

#!/bin/bash
exec /usr/bin/x86_64-pc-linux-gnu-g${0:$[-2]} -m32 "$@"

Nie zapomnij uczynić go wykonywalnym!

chmod a+x i686-pc-linux-gnu-wrapper

Następnie potrzebujesz zrobić parę linków:

ln -s i686-pc-linux-gnu-wrapper gcc
ln -s i686-pc-linux-gnu-wrapper g++
ln -s i686-pc-linux-gnu-wrapper c++
ln -s i686-pc-linux-gnu-wrapper cc
ln -s i686-pc-linux-gnu-wrapper i686-pc-linux-gnu-gcc
ln -s i686-pc-linux-gnu-wrapper i686-pc-linux-gnu-g++
ln -s i686-pc-linux-gnu-wrapper i686-pc-linux-gnu-c++
ln -s i686-pc-linux-gnu-wrapper i686-pc-linux-gnu-cc

wynikowo katalog /opt/cross32/bin powinien wyglądać tak:

lrwxrwxrwx 1 root root 25 kwi  8 22:35 c++ -> i686-pc-linux-gnu-wrapper
lrwxrwxrwx 1 root root 25 kwi  8 22:35 cc -> i686-pc-linux-gnu-wrapper
lrwxrwxrwx 1 root root 25 kwi  8 22:35 g++ -> i686-pc-linux-gnu-wrapper
lrwxrwxrwx 1 root root 25 kwi  8 22:35 gcc -> i686-pc-linux-gnu-wrapper
lrwxrwxrwx 1 root root 25 kwi  8 22:36 i686-pc-linux-gnu-c++ -> i686-pc-linux-gnu-wrapper
lrwxrwxrwx 1 root root 25 kwi  8 22:36 i686-pc-linux-gnu-cc -> i686-pc-linux-gnu-wrapper
lrwxrwxrwx 1 root root 25 kwi  8 22:36 i686-pc-linux-gnu-g++ -> i686-pc-linux-gnu-wrapper
lrwxrwxrwx 1 root root 25 kwi  8 22:36 i686-pc-linux-gnu-gcc -> i686-pc-linux-gnu-wrapper
-rwxr-xr-x 1 root root 68 kwi  8 23:03 i686-pc-linux-gnu-wrapper

Konfiguracja distcc

Idealna byłaby praca distcc bez żadnych zmian. Niestety, dużo programów jako kompilatora używa krótkich wersji (np "cc") zamiast pełnych (np. "i686-pc-linux-gnu-cc"). Po wysłaniu takiej "krótkiej" komendy na host AMD64, ten skompilowałby kod "po swojemu" (64-bitowo) i taki odesłałby na maszynę 32-bitową. Jak się domyślasz, taka kombinacja nie zadziała.

Rozwiązaniem jest modyfikacja konfiguracji distcc. Masz dwie drogi: albo rezygnujesz całkowicie z distcc 64-bitowego, albo nie :)

Obsługa tylko 32-bitów

W pliku /etc/init.d/distccd popraw zmienną PATH:

#!/sbin/runscript
# $Header: /var/cvsroot/gentoo-x86/sys-devel/distcc/files/2.18/init,v 1.1 2004/10/12 17:21:43 lisa Exp $

depend() {
       need net
       use ypbind
}

start() {
       [ -e "${DISTCCD_PIDFILE}" ] && rm -f ${DISTCCD_PIDFILE} &>/dev/null

       ebegin "Starting distccd"
       chown distcc `dirname ${DISTCCD_PIDFILE}` &>/dev/null
       TMPDIR="${TMPDIR}" \
       PATH="/opt/cross32/bin" \
       /sbin/start-stop-daemon –start –quiet –startas ${DISTCCD_EXEC} \
       –pidfile ${DISTCCD_PIDFILE} — \
       –pid-file ${DISTCCD_PIDFILE} -N ${DISTCCD_NICE} –user distcc \
       ${DISTCCD_OPTS}

       eend $?
}

stop() {
       ebegin "Stopping distccd"
       start-stop-daemon –stop –quiet –pidfile "${DISTCCD_PIDFILE}"
       rm -f "${DISTCCD_PIDFILE}"
       eend $?
}

Praca 64 + 32 bity

Jak pisałem, pojedyńczy demon nie obsłuży obu trybów... Trzeba więc dwóch demonów :) . Plik z poprzedniego przykładu zapisz pod nazwą /etc/init.d/distccd32 pozostawiając oryginał bez zmian. Następnie skopiuj plik /etc/conf.d/distccd do /etc/conf.d/distccd32. W oryginalnym pliku popraw linijkę z portem:

# set this option to run distccd with extra parameters
# Default port is 3632.  For most people the default is okay.
DISTCCD_OPTS="${DISTCCD_OPTS} --port 3664"

Od tej chwili masz dwa demony: distcc pracujący jako kompilacja 64-bitowa, ale na porcie 3664 oraz distcc32 pracujący jako kompilacja 32-bitowa na standardowym porcie 3632.