Ergänzungen zum Sbuild-Artikel in IT-Administrator 05/2017

Hier einige Ergänzungen zu meinem Artikel über Sbuild in IT-Administrator 05/2017. In dem Zeitschriftenartikel geht es um die Einrichtung von Chroots für diesen Paketbuilder, um die Einbindung von Eatmydata, den Einsatz von Overlayfs und dem APT-Proxy APT-Cacher-NG, sowie um das Crossbuilding in Verbindung mit dem QEMU-Emulator. Wie dort bereits geschrieben gibt es noch weitere Möglichkeiten für die Verbesserung der Bauperformance, und dazu hier noch ein paar Tricks für die tägliche Arbeit mit Sbuild.

Ccache einbinden

Für den in einem Paket kompilierten Maschinencode in einen experimentellen Workflow mit mehreren Baudurchgängen hintereinander bietet sich der Einsatz von Ccache an. Der Compilercache legt die einmal erzeugten Objektdateien ab und greift bei einem weiteren Bauvorgang dann darauf zu, anstatt sie jedesmal neu zu generieren – hierbei gibt es erhebliche Reserven den Zeitaufwand beim wiederholten Bauen signifikant abzukürzen. Dabei müssen die Objektdateien natürlich außerhalb des Chroots abgelegt werden um danach immer wieder zur Verfügung zu stehen, und das macht die Einrichtung von Ccache für Sbuild ein klein wenig kniffliger. Zunächst muss das Ccache-Paket auf dem Arbeitsrechner installiert werden, dieser Objektdatei-Cacher steht genau wie beim APT-Cacher-NG dann bereits für den Wirt zur Verfügung – für tiefer gehende Infos zu Ccache konsultiere man bitte die dem Paket mitgelieferte Dokumentation. Zunächst muss der eigentliche Cache eingerichtet werden:

$ dir=/var/cache/ccache-sbuild
$ sudo install --group=sbuild --mode=2775 -d $dir
$ env CCACHE_DIR=$dir ccache --max-size 4G

Danach muss dieser Cache dann an die Sbuild-Chroots durchgeschaltet bzw. durchgereicht werden, und zwar geht das mittels der eigenen fstab-Datei von Sbuild:

$ echo "$dir $dir none rw,bind 0 0" | sudo tee -a /etc/schroot/sbuild/fstab

Dann benötigt man ein Shellskript, welches Ccache beim Aufruf der Compilern im Chroot vorschaltet. Der Dateiname und Ablageort auf dem Wirt ist dabei beliebig, es eignet sich zum Beispiel /var/cache/ccache-sbuild/sbuild-setup:

#!/bin/sh
export CCACHE_DIR=/var/cache/ccache-sbuild
export CCACHE_UMASK=002
export CCACHE_COMPRESS=1
unset CCACHE_HARDLINK
export PATH="/usr/lib/ccache:$PATH"
exec "$@"

Nun muss dasselbe Ccache-Paket auch in den Chroot installiert werden, für welchen diese Funktionalität benötigt wird. Wie schon im Artikel geschrieben muss bei derartigen Operationen der Chroot immer mit vorgesetztem source: aufgerufen werden, um nicht an der “Wegwerf”-Fassung (der “Session”) zu operieren, weil die Änderungen (das neu installierte Paket) sonst verloren gehen:

# schroot -d / -c source:unstable-amd64-sbuild apt-get install ccache

Der Pfad zu dem Shellskript muss dann noch dem command-prefix-Feld in der Konfigurationsdatei dieses Chroot (etwa /etc/schroot/chroot.d/unstable-amd64-sbuild-vAYhbv) hinzugefügt bzw. mit Komma getrennt einfach angehängt werden:

[unstable-amd64-sbuild]
type=directory
description=Debian unstable/amd64 autobuilder
directory=/var/lib/sbuild/unstable-amd64
groups=root,sbuild
root-groups=root,sbuild
profile=sbuild
command-prefix=eatmydata,/var/cache/ccache-sbuild/sbuild-setup
union-type=overlay

Ccache reduziert die für das Kompilieren von Maschinencode benötigte Rechenzeit spürbar, wenn die benötigten Objektdateien aus dem Cache bezogen werden. Da lassen sich C++-Bibliotheken nach 45 Minuten Bauzeit beim ersten Bau danach auf demselben Rechner durchaus in unter 10 Minuten fertig bekommen.

Bauen mit Experimental

Möchte man Bauabhängigkeiten aus dem “experimental”-Archivzweig von Debian beziehen, dann muss man ein bisschen tricksen. Eine zusätzliche Paketquelle wie deb http://httpredir.debian.org/debian experimental main lässt sich einfach beim Sbuild-Aufruf mit --extra-repository angeben, wenn das mal benötigt wird. Pakete mit höheren Versionsnummern in Experimental werden aber nicht automatisch den niedrigeren Versionen in Unstable vorgezogen, und auch ein temporäres Anpassen der Version in debian/control führt zu einem Bauabbruch mit dem Hinweis, dass die gewünschte Version überhaupt nicht verfügbar ist, obwohl die zusätzliche Paketquelle mit dem erweiterten Aufruf korrekt berücksichtigt wird. Es handelt sich dabei um ein älteres Problem mit dem Paketmanager APT (siehe Bugreport #786609). Eine Lösung dafür ist den alternativen Manager Aptitude als Resolver einzusetzen, und zwar geht das beim Sbuild-Aufruf einfach, indem man zusätzlich --build-dep-resolver=aptitude mitgibt. Allerdings bezieht Aptitude ohne Anlass auch keine höhere Paketversion aus Experimental und es gibt keine Automatik dafür, so dass debian/control auf jeden Fall entsprechend angepasst werden muss, um das gewünschte Paket von dort eingebunden zu bekommen – es bleibt also ein bisschen sperrig.

Bleeding edge

Genauso einfach lässt sich auch mit deb http://incoming.debian.org/debian-buildd buildd-unstable main als zusätzliche Paketquelle auf das Incoming-Verzeichnis des Baunetzwerkes von Debian zugreifen, um mit Abhängigkeiten bauen zu können, die gerade ganz frisch hochgeladen worden sind und sich noch nicht im Archiv befinden. Das ist ein sehr nützlicher Service, der von incoming.debian.org betrieben wird, und so nah am “Pulsschlag” von Debian als Paketsammlung wahrscheinlich hauptsächlich von Maintainern genutzt wird.

Um Pakete lokal einzubinden kann man entweder ein eigenes rudimentäres Paketarchiv aufsetzen und als Paketquelle für Sbuild angeben, allerdings akzeptiert APT per Voreinstellung keine Pakete aus unauthentifizierten Repositorien (siehe apt-secure(1)). Diese Policy kann man aber über die Konfigurationseinstellung APT::Get::AllowUnauthenticated "true" (siehe auf der Manpage unter --allow-unauthenticated) auflockern, und das kann per Konfigurationsskript in /etc/schroot/setupt.d/ in die Chroots abgesetzt werden (man vergleiche die Einrichtung vom APT-Cacher-NG für Sbuild):

#!/bin/sh -e

. "$SETUP_DATA_DIR/common-data"
. "$SETUP_DATA_DIR/common-functions"
. "$SETUP_DATA_DIR/common-config"

if [ $STAGE = "setup-start" ] || [ $STAGE = "setup-recover" ]; then
echo "APT::Get::AllowUnauthenticated \"true\";" | \
tee "${CHROOT_PATH}/etc/apt/apt.conf.d/03allow-unauthenticated"
fi

Ein wesentlich einfacherer Weg ist es allerdings, --extra-package beim Sbuild-Aufruf zu verwenden (siehe sbuild(1)).