Distcc/Cross-Compiling

From Gentoo Wiki
< Distcc
Jump to:navigation Jump to:search
This page is a translated version of the page Distcc/Cross-Compiling and the translation is 100% complete.


Dieser Artikel zeigt dem Leser, wie man distcc für die Cross-Kompilierung über verschiedene Prozessorarchitekturen hinweg einrichtet.

Cross-Compiling mit distcc

Einleitung

distcc ist ein Tool mit dem die Aufgaben eines Compilierprozesses auf mehrere im Netzwerk verteilte Rechner, aufgeteilt werden können. Wenn alle beteiligten Rechner die gleiche GCC-Version und Prozessorarchitektur verwenden, ist für distcc keine spezielle Konfiguration notwendig.

Diese Anleitung enthält die Instruktionen wie distcc zu konfigurieren ist um Übersetzungen für andere Rechnerarchitekturen durchführen zu können.

Installieren der benötigten Werkzeuge

Zuerst muss crossdev auf allen beteiligten Rechnern installiert werden. crossdev ist ein Tool mit dem die Werkzeuge die für andere Rechnerarchitekturen benötigt werden, einfach erstellt werden können. Es wird folgendermaßen aufgerufen: crossdev -t sparc erstellt alle Werkzeuge für die Sparc-Architektur. Die beinhaltet binutils, gcc, glibc und linux-Headers.

Es ist notwendig die passenden Werkzeuge auf allen teilnehmenden Rechner zu installieren. Weitere Hilfe wird durch crossdev --help angezeigt.

Hier ist ein Skript das die genauen Versionen für binutils, gcc, kernel, glibc und verwendete Architektur anzeigt (dieses sollte auf der Ziel-Platform aufgerufen werden).

CODE Anzeige der Versionen der Build-Werkzeuge
#!/bin/bash
BINUTILS_VER=$(qatom -F '%{PV}' $(qfile -v $(realpath /usr/bin/ld) | cut -d' ' -f1))
GCC_VER=$(qatom -F '%{PV}' $(qfile -v $(realpath /usr/bin/gcc) | cut -d' ' -f1))
KERNEL_VER=$(qatom -F '%{PV}' $(qlist -Ive sys-kernel/linux-headers))
LIBC_VER=$(qatom -F '%{PV}' $(qlist -Ive sys-libs/glibc))
echo "crossdev --b '~${BINUTILS_VER}' --g '~${GCC_VER}' --k '~${KERNEL_VER}' --l '~${LIBC_VER}' -t $(portageq envvar CHOST)"

Als nächstes muss distcc auf allen Rechnern installiert werden, die am Übersetzungsprozess beteiligt werden sollen. Dies schließt die Zielplattform und die Rechnern die für das Crosscompiling vorgesehen sind ein. Die Gentoo Distcc Dokumentation enthält weitere Informationen für die Konfiguration und Benutzung von distcc.

Hinweis
Aktuelle Versionen von crossdev haben ein S (--stable) Flag. Wenn dieses Flag gesetzt ist, werden nur als stabil gekennzeichnete Versionen der Compiler Werkzeuge benutzt. (z.B. crossdev -t i686-pc-linux-gnu --stable --ex-gcc --ex-gdb --portage --pretend). Ohne diese Option, installiert crossdev die letzte experimentelle Version der Compiler! Das Skript oben wird nicht benötigt, es sei den es wurden spezifische Versionen für Portage unmaskiert.

Hinweise für spezifische Architekturen

Hinweis
Den Namen der verwendeten Prozessorarchitektur enthält die CHOST Variable in /etc/make.conf. Crossdev wird für jede Architektur unterhalb /usr die erforderlichen Tools installieren (z.B. /usr/i686-pc-linux-gnu/, /usr/i686-linux-gnu/, ...). Es wird empfohlen jede nicht mehr benötigte Architektur mit dem Befehl crossdev --clean vom System zu entfernen, bzw. die betreffenden Verzeichnisse manuell zu löschen.

Intel x86 Architekturen

Wird das Crosscompiling für verschiedene Intel-x86-Prozessoren (z.B. i586 und i686) durchgeführt, müssen die Tools für jeden gewünschten CHOST installiert werden, ansonsten schlägt die Übersetzung fehl. Die Prozessoren i586 und i686 sind aktuell verschiedene CHOST, obwohl es sich bei beiden um x86-Prozessoren handelt. Diese Unterscheidung darf nicht vergessen werden, wenn die Cross-Compiling Werkzeuge installiert werden. Wenn zum Beispiel für einen i586 Rechner Programme übersetzt werden sollen und über distcc i686 Rechner beteiligt werden, müssen auf diese die Werkzeuge für i586 installiert sein.

SPARC

Der Aufruf von crossdev -t sparc kann mit einer der folgenden Fehlermeldungen fehlschlagen.

CODE Angezeigte Fehler beim Aufruf von crossdev -t sparc
linker with -z relro support required
support for the tls_model attribute is required
this configuration requires -mlong-double-128 support

Wenn dies zutrifft, kann der folgende Befehl verwendet werden:

user $crossdev --lenv "CC=sparc-unknown-linux-gnu-gcc" -t sparc-unknown-linux-gnu

Fehlerfreies Crosscompiling mit distcc

Hinweis
Der in diesem Abschnitt beschriebene Workaround wird seit distcc-3.2 nicht mehr benötigt, da die Funktionalität zum Ersetzen der Compileraufrufe durch den vollständigen Compilernamen seither [1] in distcc selbst implementiert wurde.

Mit dem voreingestellten distcc-Setup wird das Crosscompiling nicht funktionieren. Ursache des Problems ist, dass viele Pakete als Compiler nur gcc auf rufen, anstelle des vollen Pfades (z.B. sparc-unknown-linux-gnu-gcc). Wird dieses Paket nur zum Übersetzen auf einen Remotehost übertragen, wird auf diesem der system-eigene Compiler verwendet, anstelle des Cross-Compiler.

Für dieses kleine Problem gibt es zum Glück einen Workaround. Alles was es benötigt, ist ein Wrapper-Skript und ein paar Symlinks auf dem Rechner, auf dem emerge laufen soll. In folgenden Beispiel wird ein Sparc-Rechner benutzt, also muss immer dort wo sparc-unknown-linux-gnu an die eigene CHOST, z.B. x86_64-pc-linux-gnu für eine AMD64 CPU. Nach dem Installieren von distcc, sieht ein Listing /usr/lib/distcc/bin in etwa folgendermaßen aus:

Hinweis
Die folgenden Anweisungen sind nur auf dem Rechner durchzuführen, von dem die Übersetzung ausgeht, nicht auf den helfenden Rechnern.
root #cd /usr/lib/distcc/bin
root #ls -l
total 0
lrwxrwxrwx  1 root root 15 Dec 23 20:13 c++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 cc -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 g++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 gcc -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 sparc-unknown-linux-gnu-c++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 sparc-unknown-linux-gnu-g++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Dec 23 20:13 sparc-unknown-linux-gnu-gcc -> /usr/bin/distcc

Was ist zu tun?

root #rm c++ g++ gcc cc

Nun muss auf dem Ausgangsrechner ein Skript erstellt werden, mit dem Text aus der folgenden Box. Es muss Dieses ist unter sparc-unknown-linux-gnu-wrapper zu speichern. Es muss sparc-unknown-linux-gnu an die CHOST Variable angepasst werden auf der das emerge-Skript aufgerufen wird.

CODE Das neue Skript
#!/bin/bash
exec /usr/lib/distcc/bin/sparc-unknown-linux-gnu-g${0:$[-2]} "$@"

Der nächste Schritt besteht darin, das Skript ausführbar zu machen und die benötigen Verlinkungen auf dieses Skript anzulegen.

root #chmod a+x sparc-unknown-linux-gnu-wrapper
root #ln -s sparc-unknown-linux-gnu-wrapper cc
root #ln -s sparc-unknown-linux-gnu-wrapper gcc
root #ln -s sparc-unknown-linux-gnu-wrapper g++
root #ln -s sparc-unknown-linux-gnu-wrapper c++

Nun sollte das Listing von /usr/lib/distcc/bin folgendes Bild ergeben:

root #ls -l
total 4
lrwxrwxrwx  1 root root 25 Jan 18 14:20 c++ -> sparc-unknown-linux-gnu-wrapper
lrwxrwxrwx  1 root root 25 Jan 18 14:20 cc -> sparc-unknown-linux-gnu-wrapper
lrwxrwxrwx  1 root root 25 Jan 18 14:20 g++ -> sparc-unknown-linux-gnu-wrapper
lrwxrwxrwx  1 root root 25 Jan 18 14:20 gcc -> sparc-unknown-linux-gnu-wrapper
lrwxrwxrwx  1 root root 15 Nov 21 10:42 sparc-unknown-linux-gnu-c++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Nov 21 10:42 sparc-unknown-linux-gnu-g++ -> /usr/bin/distcc
lrwxrwxrwx  1 root root 15 Jul 27 10:52 sparc-unknown-linux-gnu-gcc -> /usr/bin/distcc
-rwxr-xr-x  1 root root 70 Jan 18 14:20 sparc-unknown-linux-gnu-wrapper
Hinweis
Bei neueren distcc-Versionen sind die folgenden Schritte unnötig - distcc kann einfach mit dem crossdev USE-Flag installiert werden, um dasselbe Ergebnis zu erreichen.

Bei einem Upgrade des Distcc-Paketes werden nun diese Verknüpfungen überschrieben. Damit diese nach einem Upgrade wieder hergestellt werden, wird folgende Verfahrensweise benutzt. Wird das Distcc-Paket oder der GNU-C-Compiler neu übersetzt, wird nach dem Übersetzen und Installieren ein Skript ausgeführt. Die Anweisung bekommt Portage dazu durch folgendes Skript in /etc/portage/bashrc:

DATEI /etc/portage/bashrc
case ${CATEGORY}/${PN} in
                sys-devel/distcc | sys-devel/gcc | sys-devel/clang)
			if [ "${EBUILD_PHASE}" == "postinst" ]; then
				/usr/local/sbin/distcc-fix &
			fi
		;;
esac

Erstellen Sie dann eine der folgenden Dateien, falls zutreffend. Wenn Sie nicht clang verwenden:

DATEI /usr/local/sbin/distcc-fix
#!/bin/bash                     
 
sleep 20
# Wir extrahieren $TUPLE aus make.conf, um zu vermeiden, dass das Skript für jede Architektur bearbeitet werden muss.
TUPLE=$(portageq envvar CHOST)
GCC_VER=$(gcc-config -c|cut -d "-" -f5)
cd /usr/lib/distcc/bin
rm cc c++ gcc g++ gcc-${GCC_VER} g++-${GCC_VER} ${TUPLE}-wrapper
echo '#!/bin/bash' > ${TUPLE}-wrapper
echo "exec ${TUPLE}-g\${0:\$[-2]}" "\"\$@\"" >> ${TUPLE}-wrapper
chmod 755 ${TUPLE}-wrapper
ln -s ${TUPLE}-wrapper cc
ln -s ${TUPLE}-wrapper c++
ln -s ${TUPLE}-wrapper gcc
ln -s ${TUPLE}-wrapper g++
ln -s ${TUPLE}-wrapper gcc-${GCC_VER}
ln -s ${TUPLE}-wrapper g++-${GCC_VER}

Wenn Sie clang verwenden:

DATEI /usr/local/sbin/distcc-fix
#!/bin/bash	                
#clang aware, jetzt werden Ihre >chromium-65-Ebuilds distcc genau wie vorher benutzen ;) 
sleep 20
# Wir extrahieren $TUPLE aus make.conf, um zu vermeiden, dass das Skript für jede Architektur bearbeitet werden muss.
TUPLE=$(portageq envvar CHOST)
GCC_VER=$(gcc-config -c|cut -d "-" -f5)
CLANG_VER=$(clang --version|grep version|cut -d " " -f3|cut -d'.' -f1,2)
cd /usr/lib/distcc/bin
rm cc c++ gcc g++ gcc-${GCC_VER} g++-${GCC_VER} clang clang++ clang-${CLANG_VER} clang++-${CLANG_VER} ${TUPLE}-wrapper ${TUPLE}-clang-wrapper 
echo '#!/bin/bash' > ${TUPLE}-wrapper
echo "exec ${TUPLE}-g\${0:\$[-2]}" "\"\$@\"" >> ${TUPLE}-wrapper
echo '#!/bin/bash' > ${TUPLE}-clang-wrapper
echo "exec ${TUPLE}-\$(basename \${0}) \"\$@\"" >> ${TUPLE}-clang-wrapper
chmod 755 ${TUPLE}-wrapper
chmod 755 ${TUPLE}-clang-wrapper
ln -s ${TUPLE}-wrapper cc
ln -s ${TUPLE}-wrapper c++
ln -s ${TUPLE}-wrapper gcc
ln -s ${TUPLE}-wrapper g++
ln -s ${TUPLE}-wrapper gcc-${GCC_VER}
ln -s ${TUPLE}-wrapper g++-${GCC_VER}
ln -s ${TUPLE}-clang-wrapper clang
ln -s ${TUPLE}-clang-wrapper clang++
ln -s ${TUPLE}-clang-wrapper clang-${CLANG_VER}
ln -s ${TUPLE}-clang-wrapper clang++-${CLANG_VER}

Anpassen der Zugriffsrechte:

root #chmod 755 /usr/local/sbin/distcc-fix

Glückwunsch zum (hoffentlich) fehlerfrei funktionierendem Distcc Cross-Comiling Setup.

Funktionsweise

Immer wenn nun distcc aufgerufen wird, prüft es über welche Verknüpfung es aufgerufen wurde, (z.B. i686-pc-linux-gnu-gcc, sparc-unknown-linux-gnu-g++, etc.). Wenn nun Distcc einen Quelltext auf einen anderen Rechner zur Übersetzung sendet, wird der vollständige Name des Compilers, der auf dem unterstützenden Rechners zu verwenden ist, genannt. Würde nur der Defaultname gcc mitgegeben, würde auf dem Unterstützungsrechner der dortige gcc augeführt, der mit dem lokal verwendeten nicht übereinstimmen muss.

Fehlerbehebung

Dieser Abschnitt hilft bei einigen häufigen Problemen die bei der Benutzung von distcc und Crosscompiling auftreten können.

Übersetzungsfehler auf dem Remote Rechner

Erscheint die Meldung COMPILE ERRORS in der Datei /var/log/distccd.log auf dem Remoterechner, ist die korrekte Rechnerarchitektur wie im obigen Abschnitt anzugeben (z.B. crossdev -t $TARGET).

Eine andere Lösungsmöglichkeit besteht darin, die crossdev Compiler-Tools zu deinstallieren und neu zu installieren, unter Benutzung der crossdev --clean Option. Wenn /usr/$TARGET leer ist, kann man auch den CrossCompiler komplett neu installieren.

Ratsam ist es auch die Datei /usr/$TARGET/etc/portage/make.conf auf dem Remote Host so anzupassen, dass die CFLAGS Variablen auf allen teilnehmenden Rechner angeglichen sind. Stellen Sie auch sicher, dass die USE-Flags für den Cross-Compiler ausreichend sind: Wenn Sie GCC mit USE=graphite auf dem Client gebaut haben, brauchen Sie auch eine Zeile wie cross-i686-pc-linux-gnu/gcc graphite in /etc/portage/package.use.

Failed to exec $TARGET-unknown-linux-gnu-gcc: No such file or directory

Auch bei richtig gesetzten Zugriffsrechten, können die Wrapper-Skripte mit einem Fehler abbrechen:

CODE Fehlermeldung des Wrapper
distcc[6195] (dcc_execvp) ERROR: failed to exec i686-unknown-linux-gnu-gcc: No such file or directory

Um diesen Fehler zu beheben, ist zu kontrollieren, dass das Wrapper-Skript mit dem kompletten Name der Architektur erstellt wurde.

user $ls -alh /usr/lib/distcc/bin/c++
/usr/lib/distcc/bin/c++ ->./i686-pc-linux-gnu-wrapper

Siehe auch

  • Crossdev — a set of bash scripts that utilize emerge to provide a system integrated cross-compilation capability.

This page is based on a document formerly found on our main website gentoo.org.
The following people contributed to the original document: Andrew Gaffney, Joshua Saddler
They are listed here because wiki history does not allow for any external attribution. If you edit the wiki article, please do not add yourself here; your contributions are recorded on each article's associated history page.