KODI für Arch Linux ARM selbst kompilieren

Wenn man Anwendungen für den Raspberry Pi selbst kompilieren möchte, hat man verschiedene Optionen. Natürlich kann man die Anwendung direkt auf dem Raspberry kompilieren. Abhängig vom Umfang der Anwendung kann das jedoch ziemlich lange dauern, ggf. gehen auch die Ressourcen dabei zur Neige. In meinem Fall sollte Kodi neu übersetzt werden um einen Patch auszuprobieren. Das kann auf dem Raspberry Pi mal eben 10 Stunden dauern. Daher war direkt auf dem Raspberry zu kompilieren für mich keine Option.

Nach einer Recherche ergaben sich folgende Alternativen:

  • Verwenden von distcc um den Kompiliervorgang auf einen leistungsstarken Rechner auszulagern. Dies wird vom Arch Linux ARM Projekt empfohlen. Der Kompiliervorgang wird dann zwar weiterhin auf dem Raspberry angestossen und gesteuert, das rechenintensive Kompilieren jedoch auf einen oder mehrere andere Rechner ausgelagert. Auf diesen muss zudem ein geeigneter Cross-Compiler installiert sein. Das Linken der Software verbleibt jedoch auf dem Raspberry, deshalb müssen auch alle Build-Abhängigkeiten auf diesem installiert werden. Ich habe diesen Ansatz daher verworfen, da ich die Installation auf dem Raspberry, der ausschliesslich als Mediacenter dient, übersichtlich halten wollte.
  • Verwenden von QEMU um das ganze System zu emulieren. Hierfür ist kein eigenes Linux-System notwendig, da QEMU auch für Windows verfügbar ist.
  • Verwenden von QEMU und einem chroot um eine Raspberry Pi Umgebung unter dem eigenen Linux-System zu emulieren.

Die letzten beiden Ansätze möchte ich im folgenden für Arch Linux ARM beschreiben.

System emulieren

Benötigte Werkzeuge

Vorbereitungen vor dem Start von QEMU

Das Arch Linux Image ist mit 2GB relativ klein, der Platz wird schnell zu wenig, daher sollte zuerst das Image mit folgendem Befehl vergrössert werden:

qemu-img resize *.img +2G

Erster Start von QEMU

Die notwendigen Parameter habe ich diesem Blogeintrag entnommen und folgendes Batch-File erstellt:

cd Qemu-windows-2.2.0
start qemu-system-armw.exe  -kernel ../kernel-qemu -cpu arm1176  -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda5 panic=1 rootfstype=ext4 rw" -redir tcp:2222::22 -hda ../ArchLinuxARM-2014.06-rpi.img

Das System startet darauf, es kommt jedoch noch zu einigen Fehlern, die man z.B. wie folgt beheben kann:

# Die Boot-Partition wird beim Start nicht richtig eingehängt, deshalb entferne ich den Eintrag aus der fstab
echo "/dev/sda5 / auto defaults 0 0" > /etc/fstab
# Es werden Kernel-Module für den Raspberry geladen, die ohne die richtige Hardware Fehler erzeugen
rm /etc/modules-load.d/raspberrypi.conf

Außerdem muss noch mit fdisk /dev/sda die Partionstabelle an das vergrösserte Image angepasst werden (Auszug gekürzt):

Command (m for help): p
Disk /dev/sda: 3.8 GiB, 4108320768 bytes, 8024064 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x417ee54b

Device     Boot  Start     End Sectors  Size Id Type
/dev/sda1         2048  186367  184320   90M  c W95 FAT32 (LBA)
/dev/sda2       186368 3667967 3481600  1.7G  5 Extended
/dev/sda5       188416 3667967 3479552  1.7G 83 Linux

Command (m for help): d
Partition number (1,2,5, default 5): 2

Partition 2 has been deleted.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): e
Partition number (2-4, default 2): 2
First sector (186368-8024063, default 186368):
Last sector, +sectors or +size{K,M,G,T,P} (186368-8024063, default 8024063):

Created a new partition 2 of type 'Extended' and of size 3.8 GiB.

Command (m for help): d
Partition number (1,2,5, default 5): 5

Partition 5 has been deleted.

Command (m for help): n
Partition type
   p   primary (1 primary, 1 extended, 2 free)
   l   logical (numbered from 5)
Select (default p): l

Adding logical partition 5
First sector (188416-8024063, default 188416):
Last sector, +sectors or +size{K,M,G,T,P} (188416-8024063, default 8024063):

Created a new partition 5 of type 'Linux' and of size 3.8 GiB.

Command (m for help): p
[...]
Device     Boot  Start     End Sectors  Size Id Type
/dev/sda1         2048  186367  184320   90M  c W95 FAT32 (LBA)
/dev/sda2       186368 8024063 7837696  3.8G  5 Extended
/dev/sda5       188416 8024063 7835648  3.8G 83 Linux

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.

Anschliessend das System neustarten und die Vergösserung mit resize2fs /dev/sda5 abschliessen.

QEMU regulär starten

QEMU sollte nun ohne Fehler laufen. Die nächsten Schritte sind:

# Deutsche Tastatur laden
loadkeys de
# Netzwerk aktivieren
dhcpcd eth0
# System auf den aktuellen Stand bringen
pacman -Syu
# Benötigte Pakete nachinstallieren
pacman -S sudo git binutils svn make autoconf automake pkg-config gcc
# Einen Nutzer zum Pakete bauen anlagen
useradd -m -G wheel build
# Dem Nutzer Zugriff per sudo erlauben
nano /etc/sudoers -> zeile entkommentieren
# Die Systemzeit stellen
ntpdate pool.ntp.org
# Zum Build Nutzer wechseln
su build
# Das PKGBUILD Repo von Arch Linux ARM auschecken
git clone https://github.com/archlinuxarm/PKGBUILDs.git archlinuxarm
cd archlinuxarm/alarm/kodi-rbp
# Kodi Sourcen holen und entpacken
makepkg -so
# Jetzt die gewünschten Patches durchführen
nano ...
# Die Release des Paketes hochzählen oder die Version ändern
edit PKGBUILD release
# Das Paket bauen
makepkg -e

Fertig :-)

Probleme

Bei diesem Vorgehen bin ich auf folgende Probleme gestossen:

  • Bei einem Systemupdate kommt es zu Fehlern weil /boot nicht gemountet ist. Negative Auswirkungen hatte ich dadurch jedoch noch nicht.
  • Die Console von QEMU bietet wenig Platz und Komfort. Eine grafische Oberfläche wollte ich jedoch auch nicht extra installieren. Ich habe daher ein Port-Forwarding definiert (s.o.) und logge mich per SSH auf dem System ein.
  • Netzwerk ist beim Start nicht verfügbar. Ein manuelles dhcpcd eth0 ist nach einem Neustart erforderlich. Zudem ist die Netzwerkperformance schlecht (ca. 30kB/s).
  • Die Systemzeit stimmt nicht. Ein manuelles ntpdate pool.ntp.org ist nach einem Neustart erforderlich.
  • Die Leistung ist gering, es kann nur ein Prozessorkern genutzt werden. Versuche, QEMU zur Bereitstellung mehrerer Kerne mit -smp 4 zu überzeugen, schlugen fehl.

QEMU Chroot

Aufgrund der doch nennenswerten Probleme des vorherigen Ansatzes habe ich im Anschluss ausprobiert, ob ein Chroot die bessere Option ist. Dafür habe ich die oben erstellte Image-Datei weiterverwendet, da diese schon entsprechend konfiguriert ist.

# Notwendige Pakete installieren [1]
yaourt -S multipath-tools binfmt-support qemu-user-static fakeroot
# Imagedatei mounten [2]
kpartx -a ArchLinuxARM-2014.06-rpi.img
mkdir /mnt/rbp
mount /dev/mapper/loop0p5 /mnt/rbp
# Arm Binaries für Emulation registrieren [3]
echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:' > /proc/sys/fs/binfmt_misc/register
# Chroot vorbereiten [4]
cd /mnt/rbp
cp /usr/bin/qemu-arm-static  usr/bin/
mount -t proc proc proc/
mount --rbind /sys sys/
mount --rbind /dev dev/
mount --rbind /run run/
cp /etc/resolv.conf  etc
# Chroot starten
chroot .
# Anschliessend wie beim vorherigen Ansatz verfahren

Verwendete Quellen: [1] [2] [3] [4]

Fazit

Mit dem Chroot-Ansatz sind die meisten der zuvor erkannten Probleme hinfällig. Netzwerk und Systemzeit werden vom Host übernommen, ebenso stehen alle CPU-Kerne zur Verfügung. Eine extra Konsole o.ä. gibt es nicht, man arbeitet ganz normal mit seiner gewohnten Shell. Der Ansatz erfordert allerdings ein vorhandenes Linux-System.