Angetestet: Android Apps mit Go

Ein ausführliches How-To

Die nötigen Schritte, um Example Apps aus dem mobile Projekt auf GitHub zu bauen:
  1. Vorwort
  2. Go 1.4.x besorgen, oder haben
  3. Android NDK besorgen
  4. Standalone Toolchain aus dem NDK bauen
  5. Go 1.5 bauen (keine Binaries verfügbar)
  6. das mobile Projekt initialisieren
  7. eine Example Anwendung kompilieren
  8. die Anwendung auf ein kompatibles Gerät deployen
  9. vielleicht selbst etwas entwickeln?

1. Vorwort

Dieser Artikel ist für Windows Nutzer höchstens von informativem Gehalt. Die nötigen Tools des mobile Projekts funktionieren derzeit nicht auf Windows. Ob eine Portierung geplant ist, ist ungewiss.
Meines Wissens nach müsste das Setup in ähnlicher Form auf Apple Geräten durchzuführen sein, ich habe aber keine Solchen und kann daher auch keine Aussagen über eventuell auftretende Abweichungen treffen.
Ganz allgemein richtet sich dieses How-To an Fortgeschrittene User. Es sollte zwar auch möglich sein, nur die Kommandos zu kopieren, dabei wird aber vermutlich der gewünschte Wissenszuwachs ausbleiben.

Die Entwicklung für linux/arm Plattformen ist zwar auch schon mit Go 1.4.x möglich, das erzeugt aber “nur” Binaries, wie man sie z.B für den Raspberry PI und andere ARM basierte Plattformen verwenden kann. Android hat eine Linux Kernel, aber der Überbau weicht stark von den üblichen Linux Geschmacksrichtungen ab. Um eine kompilierte Binary auf einem (nicht gerooteten) Android verwenden zu können, muss diese in eine .apk Datei verpackt werden und sich über die gewöhnliche Installation aus Drittquellen, also nicht über den Play Store, aufs Gerät gebracht werden.
Die Zielplattform android/arm ist aber erst ab dem noch in der Entwicklung befindlichen (Stand Juni 2015) Android 1.5 verfügbar. Bis jetzt gibt es für Go 1.5 keine offiziellen Binaries, oder Pakete, daher muss man sich eine passende Umgebung erst selbst bauen.
Eine überraschende Neuerung an dieser Go Version ist es, dass man jetzt ein Go der Version 1.4.x benötigt, um Go 1.5 und vermutlich auch die folgenden Versionen selbst zu bauen.

2. Go 1.4.x besorgen

Wer Go 1.4.x hat braucht hier nichts zu tun. Wichtig ist nur, dass die Go Kommandos auch wirklich im Suchpfad sind.
Ubuntu 14.4 bringt z.B. nur Go in der Version 1.2 mit sich, falls man also ein aktuelles braucht, bekommt man das am besten direkt von der Downloadseite.

Ich habe die Version go1.4.2.linux-amd64.tar.gz genommen. Diese ist schnell als root zu installieren:

sudo tar -C /usr/local -xzf go1.4.2.linux-amd64.tar.gz

Danach befinden sich die Kommandos unter /usr/local/go/bin. Dieses Verzeichnis liegt höchstwahrscheinlich nicht im Suchpfad daher empfiehlt es sich, das Verzeichnis mit auf zu nehmen.

export PATH=$PATH:/usr/local/go/bin

Das gilt allerdings nur für die betroffene Shell. Zu beachten ist auch, dass diese Zeile, die schändlich aus der Dokumentation übernommen wurde, das Verzeichnis am Ende des Suchpfades anfügt. Wer also schon über seine Distribution Go installiert hatte, wird weiterhin die alte Version aufrufen. Dies ist ein gern gemachter Fehler.
Es ist eine Überlegung wert, ob man sich das Verzeichnis immer in den Suchpfad schreiben will. Benutzt man sehr viele von Extern installierte Tools, sollte man darüber nachdenken, ob man die wirklich alle ständig im Suchpfad mit sich rumschleppen will. Lautet die Antwort für Go trotzdem “Ja”, ist auch das schnell erledigt.

echo 'PATH=$PATH:/usr/local/go/bin' >> $HOME/.profile

Damit diese Zuweisung aus der .profile übernommen wird, muss man sich einmal abmelden und wieder anmelden.

3. Android NDK besorgen

Beim Bauen von Go 1.5 werden einige Bibliotheken und Tools für die Zielplattform gebaut. Wir brauchen also einen Compiler, der das auch kann. Ich rate an dieser stelle davon ab, einen anderen ARM Crosscompiler zu verwenden, als das Native Development Kit für Android bereitstellt. Diese sind möglicherweise mit ungünstigen Default Einstellungen kompiliert worden und könnten unnötige Probleme verursachen.
Nachdem Go für die Zielplattform gebaut wurde, kann man das NDK wieder entfernen, da das gomobile Kommando sich später selbst automatisch passende Compiler besorgt.
Das NDK bezieht man direkt von der Developer Seite von Android in meinem Fall war es die Version android-ndk-r10e-linux-x86_64.bin.

An der Endung erkennt man schon, dass es sich hier unnötigerweise nicht um ein reines Archiv handelt, sondern um ein selbst entpackendes Binary. Für die Basteleien mit dem NDK sollte ein eigenes Verzeichnis im $HOME Verzeichnis angelegt werden. Die .bin Datei muss für die weiteren Schritte dort abgelegt werden. Ich nenne das Verzeichnis der Einfachheit halber mal NDK. Das Anlegen des Verzeichnisses und ablegen des Downloads gebe ich jetzt nicht extra an.

cd $HOME/NDK
chmod a+x android-ndk-r10e-linux-x86_64.bin
./android-ndk-r10e-linux-x86_64.bin

Wer nicht die Version r10e genommen hat, muss natürlich Passendes ersetzen.

4. Standalone Toolchain aus dem NDK bauen

Damit ist es aber noch nicht getan. Das NDK kann für verschiedene Zwecke eingesetzt werden und der Native Compiler wird im Normalfall nicht direkt aufgerufen, sondern über diverse Skripte und Tools. Wer wie wir nur den gcc braucht, muss sich eine Standalone Toolchain bauen. Direkte Aufrufe des gcc schlagen sonst fehl, da er einige Bibliotheken nicht finden wird.

Praktischerweise kann man sich die nötige Toolchain mit einem Einzeiler vorbereiten lassen.

android-ndk-r10e/build/tools/make-standalone-toolchain.sh \
--platform=android-21 --arch=arm --install-dir=toolchain

Ja, das ist ein Einzeiler.

Jetzt sollte die Toolchain unter $HOME/NDK/toolchain einsatzbereit sein.

5. Go 1.5 bauen

Jetzt haben wir schon fast alle Vorraussetzungen zusammen um Go 1.5 zu bauen. Ich schreibe fast, weil ich der Vollständigkeit halber nicht unerwähnt lassen will, dass wir natürlich eine Buildumgebung für C(++) brauchen. Der Befehl go get wird später git benötigen, also hier noch eben die Abhängigkeiten exemplarisch für Debian.

sudo apt-get install build-essential
sudo apt-get install git

Kommen wir nun endlich zu Go. Um uns ein paar Umgebungsvariablen zu ersparen, wechseln wir zurück ins $HOME Verzeichnis und legen dort den symbolischen Link go1.4 an, der auf das bin Verzeichnis unserer Go 1.4.2 Installation zeigt. Wenn nichts Anderes definiert ist, erwartet der Buildprozess Go 1.4.x unter $HOME/go1.4.
Danach besorgen wir uns den Quellcode für Go 1.5 über git.

ln -s /usr/local/go/ $HOME/go1.4
git clone https://go.googlesource.com/go $HOME/gosrc

Wer möchte, darf sich den Quellcode natürlich in ein anderes Verzeichnis Klonen, hat dann aber im Folgenden kein so einfaches Copy & Paste mehr.

Es folgen die magischen Zeilen um ein Go für die Zielplattform android/arm zu bauenen

export CC_FOR_TARGET=$HOME/NDK/toolchain/arm-linux-androideabi\
/bin/gcc
cd $HOME/gosrc/src/
GOOS=android GOARCH=arm GOARM=7 ./make.bash

Vorsicht mit diesem Block! Wordpress bricht mir die erste Zeile ungünstig um, daher musste ich die erste Zeile verunstalten.

Es fliegen ein paar Fehler der Form

warning: unable to find runtime/cgo.a.

Das ist ein bekanntes Problem am aktuellen Stand und ist in unserem Fall nicht schlimm. Auf keinen Fall sollte dieses Verzeichnis aber verwendet werden, um Go1.5 für eine andere Plattform zu bauen, Go kann nicht fehlerfrei für verschiedene Ziele initialisiert werden.

Ebenso kann diese Installation von go1.5 derzeit nicht genutzt werden um einzelne lauffähige Programme zu erzeugen, die man auf einem Android Gerät mit root Access in der Shell verwenden könnte. Seit Android 5.0.1 haben die Programme dazu nicht mehr das nötige Format, weil der linker zwingend Position Independend Executables erfordert.

error: only position independent executables (PIE) are supported.

Man kann sich aber damit Shared Libraries bauen, gegen die man dann mit dem gcc aus einer PIE Binary linken kann. Dazu später mehr.

6. Das mobile Projekt initialisieren

Ab jetzt machen wir mit dem frisch gebauten Go weiter, also nehmen wir das neue Go in den Suchpfad auf, legen uns ein Unterverzeichnis für unsere Tests an und initialisieren gomobile. Das müssen wir dann auch noch in den Suchpfad aufnehmen. Für go get muss vorher noch die Variable GOPATH auf das aktuelle Verzeichnis gesetzt werden.

export PATH=$HOME/gosrc/bin:$PATH
mkdir $HOME/mobile
cd $HOME/mobile
export GOPATH=$PWD
go get golang.org/x/mobile/cmd/gomobile
export PATH=$PWD/bin:$PATH
gomobile init

7. Eine Example Anwendung kompilieren

(äh, naja zwei)

Die Beispielanwendungen können jetzt sehr einfach gebaut werden. Ich habe die Basic und die Sprite App gebaut

go get -d golang.org/x/mobile/example/basic
gomobile build golang.org/x/mobile/example/basic

go get -d golang.org/x/mobile/example/sprite
gomobile build golang.org/x/mobile/example/sprite

Das war’s schon. Für beide Beispiele liegt jetzt unter $HOME/mobile ein APK bereit.

8. Die Anwendung auf ein kompatibles Gerät deployen

Hier führen wirklich viele Wege nach Rom. Wer den ADB benutzt, kann das natürlich damit machen und braucht vermutlich keine genauere Anleitung.
Auch sehr bequem ist es, die Dateien einfach vom Computer per Bluetooth an das Gerät zu schicken. Wem gar nichts anderes einfällt, wie er die APKs so im Heimnetz, oder auch im Internet hinterlegen kann, dass er sie mit seinem Mobilgerät beziehen kann, dem empfehle ich einfach mal Google Drive zu benutzen. Das sollte ohne zusätzliche Software mit jedem Android Gerät trivial sein.
Sind die APKs einmal auf dem Gerät, können sie dort durch Antippen zur Installation gebracht werden. Hierfür muss, zumindest zeitweise, die Installation aus unbekannten Quellen im Menüpunkt Sicherheit in den Einstellungen des Gerätes aktiviert werden.
Für Diejenigen, die nur aus Interesse gelesen haben, aber sich die Arbeit nicht selbst machen wollen, habe ich die beiden APKs auch zum Download:

basic.apk 1ea3fbcca983a58dee0032a11f3d38d106a476c31efc1c99a0de511711ca8110

sprite.apk 99f2f86de61b64cee61bdc4882ee386276d7e9dc8f93a9b3bc90b5c9a85670a2

Es schadet sicher nicht, vorher die sha256 Summen zu überprüfen.

9. Vielleicht selbst etwas entwickeln?

Diese triviale Übung überlasse ich natürlich dem Leser für zu Hause. Wer allerdings wirklich neugierig geworden ist, kann (wenn er das How-To durchgearbeitet hat) unter $HOME/mobile/src/golang.org/x/mobile/example die Quellen durchsehen. Dabei merkt man schnell, dass zumindest einfache Anwendungen mit den kommenden Tools für Go schnell gemacht sind.
Besonders interessant dürfte der GLES Support sein. Wer ohnehin schon OpenGL kann, oder vielleicht auch mal WebGL gemacht hat, braucht hier nicht viel Beiwerk, um schnell einfache Demos, aber auch komplexere Grafik Apps zu bauen.
Ich persönlich kann mich mit Java einfach nicht so richtig anfreunden und mir war das SDK immer ein bisschen zu umständlich – Go als zu Binärcode kompilierende Hochsprache hat mir hingegen in letzter Zeit eine Menge Spaß gemacht. Ich bin gespannt, wie sich das Projekt in nächster Zeit weiter entwickeln wird.