sobota, 14 maja 2011

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.