Erstellen von ausführbaren Dateien für mehrere Plattformen unter Ubuntu 16.04

Einführung

DasGo programming language wird mit einer umfangreichen Toolchain geliefert, die das Abrufen von Paketen und das Erstellen ausführbarer Dateien unglaublich einfach macht. Eine der leistungsstärksten Funktionen von Go ist die Möglichkeit, ausführbare Dateien für jede von Go unterstützte fremde Plattform zu erstellen. Dies erleichtert das Testen und Verteilen von Paketen erheblich, da Sie keinen Zugriff auf eine bestimmte Plattform benötigen, um Ihr Paket für diese zu verteilen.

In diesem Lernprogramm verwenden Sie die Tools von Go, um ein Paket aus der Versionskontrolle abzurufen und die ausführbare Datei automatisch zu installieren. Anschließend erstellen und installieren Sie die ausführbare Datei manuell, damit Sie mit dem Prozess vertraut sind. Anschließend erstellen Sie eine ausführbare Datei für eine andere Architektur und automatisieren den Erstellungsprozess, um ausführbare Dateien für mehrere Plattformen zu erstellen. Wenn Sie fertig sind, wissen Sie, wie Sie ausführbare Dateien für Windows und macOS sowie für andere Plattformen erstellen, die Sie unterstützen möchten.

Voraussetzungen

Um diesem Tutorial zu folgen, benötigen Sie:

[[Schritt-1 - Installieren von Go-Programmen von der Versionskontrolle]] == Schritt 1 - Installieren von Go-Programmen von der Versionskontrolle

Bevor wir ausführbare Dateien aus einem Go-Paket erstellen können, müssen wir den Quellcode abrufen. Das Toolgo getkann Pakete von Versionskontrollsystemen wie GitHub abrufen. Unter der Haube klontgo get Pakete in Unterverzeichnisse des Verzeichnisses$GOPATH/src/. Gegebenenfalls wird das Paket installiert, indem die ausführbare Datei erstellt und im Verzeichnis$GOPATH/binabgelegt wird. Wenn Sie Go wie in den erforderlichen Lernprogrammen beschrieben konfiguriert haben, ist das Verzeichnis$GOPATH/binin der Umgebungsvariablen$PATHenthalten, wodurch sichergestellt wird, dass Sie installierte Pakete von überall auf Ihrem System verwenden können.

Die Syntax für den Befehlgo get lautetgo get package-import-path. package-import-path ist eine Zeichenfolge, die ein Paket eindeutig identifiziert. Dies ist häufig der Speicherort des Pakets in einem Remote-Repository wie Github oder ein Verzeichnis im Verzeichnis$GOPATH/src/auf Ihrem Computer.

Es ist üblich,go get mit dem Flag-u zu verwenden, dasgo get anweist, das Paket und seine Abhängigkeiten abzurufen, oder diese Abhängigkeiten zu aktualisieren, wenn sie bereits auf dem Computer vorhanden sind.

In diesem Tutorial installieren wirCaddy, einen in Go geschriebenen Webserver. ProCaddy’s instructionsx verwenden wirgithub.com/mholt/caddy/caddy für den Paketimportpfad. Verwenden Siego get, um Caddy abzurufen und zu installieren:

go get -u github.com/mholt/caddy/caddy

Der Befehl wird einige Zeit in Anspruch nehmen, aber Sie werden keinen Fortschritt sehen, während er das Paket abruft und installiert. Keine Ausgabe zeigt tatsächlich an, dass der Befehl erfolgreich ausgeführt wurde.

Wenn der Befehl ausgeführt wurde, finden Sie den Quellcode von Caddy unter$GOPATH/src/github.com/mholt/caddy. Da Caddy über eine ausführbare Datei verfügt, wurde diese automatisch erstellt und im Verzeichnis$GOPATH/bingespeichert. Überprüfen Sie dies, indem Siewhich verwenden, um den Speicherort der ausführbaren Datei zu drucken:

which caddy

Sie sehen die folgende Ausgabe:

Output/home/sammy/work/bin/caddy

[.Hinweis]##

Note: Der Befehlgo get installiert Pakete aus dem Standardzweig eines Git-Repositorys, in vielen Fällen aus demmaster-Zweig oder dem in Entwicklung befindlichen Zweig. Lesen Sie unbedingt die Anweisungen, die sich normalerweise in derREADME-Datei des Repositorys befinden, bevor Siego get verwenden.

Sie können Git-Befehle wiegit checkout verwenden, um einen anderen Zweig für Quellen auszuwählen, die mit dem Befehlgo get erhalten wurden. Lesen Sie das TutorialHow to Use Git Branches, um mehr über das Wechseln von Zweigen zu erfahren.

Schauen wir uns den Installationsprozess von Go-Paketen genauer an und beginnen mit der Erstellung von ausführbaren Dateien aus Paketen, die wir bereits erhalten haben.

[[Schritt 2 - Erstellen einer ausführbaren Datei]] == Schritt 2 - Erstellen einer ausführbaren Datei

Der Befehlgo gethat die Quelle heruntergeladen und die ausführbare Datei von Caddy für uns in einem einzigen Befehl installiert. Möglicherweise möchten Sie die ausführbare Datei jedoch selbst neu erstellen oder eine ausführbare Datei aus Ihrem eigenen Code erstellen. Der Befehlgo build erstellt ausführbare Dateien.

Obwohl wir Caddy bereits installiert haben, sollten wir es manuell neu erstellen, damit wir uns mit dem Vorgang vertraut machen können. Führen Siego build aus und geben Sie den Paketimportpfad an:

go build github.com/mholt/caddy/caddy

Wie zuvor zeigt keine Ausgabe eine erfolgreiche Operation an. Die ausführbare Datei wird in Ihrem aktuellen Verzeichnis mit demselben Namen wie das Verzeichnis erstellt, in dem sich das Paket befindet. In diesem Fall heißt die ausführbare Dateicaddy.

Wenn Sie sich im Paketverzeichnis befinden, können Sie den Pfad zum Paket weglassen und einfachgo build ausführen.

Verwenden Sie das Flag-o, um einen anderen Namen oder Speicherort für die ausführbare Datei anzugeben. Erstellen wir eine ausführbare Datei mit dem Namencaddy-server und platzieren Sie sie in einembuild-Verzeichnis im aktuellen Arbeitsverzeichnis:

go build -o build/caddy-server github.com/mholt/caddy/caddy

Dieser Befehl erstellt die ausführbare Datei und das Verzeichnis./build, falls es nicht vorhanden ist.

Schauen wir uns nun die Installation der ausführbaren Dateien an.

[[Schritt 3 - Installieren einer ausführbaren Datei]] == Schritt 3 - Installieren einer ausführbaren Datei

Durch das Erstellen einer ausführbaren Datei wird die ausführbare Datei im aktuellen Verzeichnis oder im Verzeichnis Ihrer Wahl erstellt. Beim Installieren einer ausführbaren Datei wird eine ausführbare Datei erstellt und in$GOPATH/bin gespeichert. Der Befehlgo install funktioniert genauso wiego build, abergo install sorgt dafür, dass die Ausgabedatei an der richtigen Stelle für Sie platziert wird.

Verwenden Sie zum Installieren einer ausführbaren Dateigo install, gefolgt vom Paketimportpfad. Probieren Sie das noch einmal mit Caddy aus:

go install github.com/mholt/caddy/caddy

Genau wie beigo build wird keine Ausgabe angezeigt, wenn der Befehl erfolgreich war. Und wie zuvor wird die ausführbare Datei mit demselben Namen wie das Verzeichnis erstellt, in dem sich das Paket befindet. Diesmal wird die ausführbare Datei jedoch in$GOPATH/bin gespeichert. Wenn$GOPATH/bin Teil der Umgebungsvariablen$PATH ist, ist die ausführbare Datei von überall auf Ihrem Betriebssystem verfügbar. Sie können den Speicherort mit dem Befehlwhichüberprüfen:

which caddy

Sie sehen die folgende Ausgabe:

Output of which/home/sammy/work/bin/caddy

Nachdem Sie nun verstanden haben, wiego get,go build undgo install funktionieren und wie sie zusammenhängen, wollen wir eine der beliebtesten Go-Funktionen untersuchen: Erstellen von ausführbaren Dateien für andere Zielplattformen.

[[Schritt 4 - Erstellen von ausführbaren Dateien für verschiedene Architekturen]] == Schritt 4 - Erstellen von ausführbaren Dateien für verschiedene Architekturen

Mit dem Befehlgo build können Sie eine ausführbare Datei für jede von Go unterstützte Zielplattformon your platform erstellen. Dies bedeutet, dass Sie Ihre Anwendung testen, freigeben und verteilen können, ohne die ausführbaren Dateien auf den Zielplattformen zu erstellen, die Sie verwenden möchten.

Cross-Compiling funktioniert, indem erforderliche Umgebungsvariablen festgelegt werden, die das Zielbetriebssystem und die Architektur angeben. Wir verwenden die VariableGOOS für das Zielbetriebssystem undGOARCH für die Zielarchitektur. Um eine ausführbare Datei zu erstellen, würde der Befehl die folgende Form annehmen:

env GOOS=target-OS GOARCH=target-architecture go build package-import-path

Der Befehlenv führt ein Programm in einer geänderten Umgebung aus. Auf diese Weise können Sie Umgebungsvariablen nur für die aktuelle Befehlsausführung verwenden. Die Variablen werden nach Ausführung des Befehls zurückgesetzt oder zurückgesetzt.

Die folgende Tabelle zeigt die möglichen Kombinationen vonGOOS undGOARCH, die Sie verwenden können:

GOOS - Zielbetriebssystem GOARCH - Zielplattform

android

arm

darwin

386

darwin

amd64

darwin

arm

darwin

arm64

dragonfly

amd64

freebsd

386

freebsd

amd64

freebsd

arm

linux

386

linux

amd64

linux

arm

linux

arm64

linux

ppc64

linux

ppc64le

linux

mips

linux

mipsle

linux

mips64

linux

mips64le

netbsd

386

netbsd

amd64

netbsd

arm

openbsd

386

openbsd

amd64

openbsd

arm

plan9

386

plan9

amd64

solaris

amd64

windows

386

windows

amd64

[.Warnung]##

Warning: Für das Cross-Compilieren von ausführbaren Dateien für Android sindAndroid NDK und einige zusätzliche Einstellungen erforderlich, die den Rahmen dieses Lernprogramms sprengen.

Mit den Werten in der Tabelle können wir Caddy für Windows 64-Bit wie folgt erstellen:

env GOOS=windows GOARCH=amd64 go build github.com/mholt/caddy/caddy

Wieder zeigt keine Ausgabe an, dass der Vorgang erfolgreich war. Die ausführbare Datei wird im aktuellen Verzeichnis erstellt, wobei der Paketname als Name verwendet wird. Da wir diese ausführbare Datei jedoch für Windows erstellt haben, endet der Name mit dem Suffix.exe.

Sie solltencaddy.exe Datei in Ihrem aktuellen Verzeichnis haben, die Sie mit dem Befehlls überprüfen können.

ls caddy.exe

In der Ausgabe wird die Dateicaddy.exeangezeigt:

Outputcaddy.exe

[.note] #Note: Mit dem Flag-o können Sie die ausführbare Datei umbenennen oder an einem anderen Speicherort ablegen. Wenn Sie jedoch eine ausführbare Datei für Windows erstellen und einen anderen Namen angeben, müssen Sie beim Festlegen des Namens der ausführbaren Datei explizit das Suffix ".exe" angeben.
#

Schauen wir uns die Skripterstellung für diesen Prozess an, um die Freigabe von Software für mehrere Zielumgebungen zu vereinfachen.

[[Schritt 5 - Erstellen eines Skripts zum Automatisieren der Cross-Kompilierung]] == Schritt 5 - Erstellen eines Skripts zum Automatisieren der Cross-Kompilierung

Das Erstellen von ausführbaren Dateien für viele Plattformen kann etwas langwierig sein, wir können jedoch ein Skript erstellen, um die Arbeit zu vereinfachen.

Das Skript verwendet den Paketimportpfad als Argument, durchläuft eine vordefinierte Liste von Betriebssystem- und Plattformpaaren und generiert für jedes Paar eine ausführbare Datei, wobei die Ausgabe im aktuellen Verzeichnis abgelegt wird. Jede ausführbare Datei wird mit dem Paketnamen gefolgt von der Zielplattform und -architektur in der Formpackage-OS-architecture benannt. Dies ist ein universelles Skript, das Sie für jedes Projekt verwenden können.

Wechseln Sie in Ihr Ausgangsverzeichnis und erstellen Sie in Ihrem Texteditor eine neue Datei mit dem Namengo-executable-build.bash:

cd ~
nano go-executable-build.bash

Wir beginnen unser Skript mit einershebang-Zeile. Diese Zeile definiert, welcher Interpreter dieses Skript analysiert, wenn es als ausführbare Datei ausgeführt wird. Fügen Sie die folgende Zeile hinzu, um anzugeben, dassbash dieses Skript ausführen soll:

go-executable-build.bash

#!/usr/bin/env bash

Wir möchten den Paketimportpfad als Befehlszeilenargument verwenden. Dazu verwenden wir die Variable$n, wobein eine nicht negative Zahl ist. Die Variable$0 enthält den Namen des Skripts, das Sie ausgeführt haben, während$1 und höher vom Benutzer bereitgestellte Argumente enthalten. Fügen Sie diese Zeile dem Skript hinzu, das das erste Argument aus der Befehlszeile übernimmt und in einer Variablen namenspackage speichert:

go-executable-build.bash

...
package=$1

Stellen Sie als Nächstes sicher, dass der Benutzer diesen Wert angegeben hat. Wenn der Wert nicht angegeben wird, beenden Sie das Skript mit einer Meldung, in der die Verwendung des Skripts erläutert wird:

go-executable-build.bash

...

if [[z "$package" ]]; then
  echo "usage: $0 "
  exit 1
fi

Diese Anweisungif überprüft den Wert der Variablen$package. Wenn es nicht festgelegt ist, verwenden wirecho, um die korrekte Verwendung zu drucken, und beenden das Skript dann mitexit. exit verwendet einen Rückgabewert als Argument, der für erfolgreiche Ausführungen0 und für nicht erfolgreiche Ausführungen ein Wert ungleich Null sein sollte. Wir verwenden hier1, da das Skript nicht erfolgreich war.

[.Hinweis]##

Note: Wenn Sie möchten, dass dieses Skript mit einem vordefinierten Paket funktioniert, ändern Sie die Variablepackageo, dass sie auf diesen Importpfad verweist:

go-executable-build.bash

...
package="github.com/user/hello"

Als Nächstes möchten wir den Paketnamen aus dem Pfad extrahieren. Der Paketimportpfad wird durch/ Zeichen begrenzt, wobei sich der Paketname am Ende des Pfads befindet. Zuerst teilen wir den Paketimportpfad in ein Array auf, wobei wir/ als Trennzeichen verwenden:

go-executable-build.bash

package_split=(${package//\// })

Der Paketname sollte das letzte Element des neuen Arrays$package_splitein. In Bash können Sie einen negativen Array-Index verwenden, um auf ein Array vom Ende statt vom Anfang zuzugreifen. Fügen Sie diese Zeile hinzu, um den Paketnamen aus dem Array abzurufen und in einer Variablen namenspackage_name zu speichern:

go-executable-build.bash

...
package_name=${package_split[-1]}

Nun müssen Sie entscheiden, für welche Plattformen und Architekturen Sie ausführbare Dateien erstellen möchten. In diesem Tutorial erstellen wir ausführbare Dateien für Windows 64-Bit-, Windows 32-Bit- und 64-Bit-MacOS. Wir werden diese Ziele in ein Array mit dem FormatOS/Platform einfügen, damit wir jedes Paar mit der gleichen Methode, mit der wir den Paketnamen aus dem Pfad extrahiert haben, inGOOS undGOARCH Variablen aufteilen können . Fügen Sie die Plattformen zum Skript hinzu:

go-executable-build.bash

...
platforms=("windows/amd64" "windows/386" "darwin/amd64")

Als Nächstes durchlaufen wir das Plattformarray, teilen jeden Plattformeintrag in Werte für die UmgebungsvariablenGOOS undGOARCHauf und verwenden diese zum Erstellen der ausführbaren Datei. Wir können das mit der folgendenfor-Schleife tun:

go-executable-build.bash

...
for platform in "${platforms[@]}"
do
    ...
done

Die Variableplatform enthält in jeder Iteration einen Eintrag aus dem Arrayplatforms. Wir müssenplatform in zwei Variablen aufteilen -GOOS undGOARCH. Fügen Sie derfor-Schleife die folgenden Zeilen hinzu:

go-executable-build.bash

for platform in "${platforms[@]}"
do
    platform_split=(${platform//\// })
    GOOS=${platform_split[0]}
    GOARCH=${platform_split[1]}

done

Als Nächstes generieren wir den Namen der ausführbaren Datei, indem wir den Paketnamen mit dem Betriebssystem und der Architektur kombinieren. Wenn wir für Windows erstellen, müssen wir dem Dateinamen auch das Suffix.exehinzufügen. Fügen Sie diesen Code zurfor-Schleife hinzu:

go-executable-build.bash

for platform in "${platforms[@]}"
do
    platform_split=(${platform//\// })
    GOOS=${platform_split[0]}
    GOARCH=${platform_split[1]}

    output_name=$package_name'-'$GOOS'-'$GOARCH

    if [ $GOOS = "windows" ]; then
        output_name+='.exe'
    fi
done

Wenn die Variablen festgelegt sind, verwenden wirgo build, um die ausführbare Datei zu erstellen. Fügen Sie diese Zeile zum Textkörper derfor-Schleife direkt über dem Schlüsselwortdone hinzu:

go-executable-build.bash

...
    if [ $GOOS = "windows" ]; then
        output_name+='.exe'
    fi

    env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package

done

Schließlich sollten wir überprüfen, ob Fehler beim Erstellen der ausführbaren Datei aufgetreten sind. Beispielsweise kann ein Fehler auftreten, wenn wir versuchen, ein Paket zu erstellen, für das wir keine Quellen haben. Wir können den Rückkehrcode des Befehlsgo buildauf einen Wert ungleich Null überprüfen. Die Variable$? enthält den Rückkehrcode aus der Ausführung eines vorherigen Befehls. Wenngo build etwas anderes als0 zurückgibt, ist ein Problem aufgetreten, und wir möchten das Skript beenden. Fügen Sie diesen Code nach dem Befehlgo build und über dem Schlüsselwortdone zur Schleifefor hinzu.

go-executable-build.bash

...

    env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package

    if [ $? -ne 0 ]; then
        echo 'An error has occurred! Aborting the script execution...'
        exit 1
    fi

Damit haben wir jetzt ein Skript, das mehrere ausführbare Dateien aus unserem Go-Paket erstellt. Hier ist das fertige Skript:

go-executable-build.bash

#!/usr/bin/env bash

package=$1
if [[z "$package" ]]; then
  echo "usage: $0 "
  exit 1
fi
package_split=(${package//\// })
package_name=${package_split[-1]}

platforms=("windows/amd64" "windows/386" "darwin/amd64")

for platform in "${platforms[@]}"
do
    platform_split=(${platform//\// })
    GOOS=${platform_split[0]}
    GOARCH=${platform_split[1]}
    output_name=$package_name'-'$GOOS'-'$GOARCH
    if [ $GOOS = "windows" ]; then
        output_name+='.exe'
    fi

    env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
    if [ $? -ne 0 ]; then
        echo 'An error has occurred! Aborting the script execution...'
        exit 1
    fi
done

Stellen Sie sicher, dass Ihre Datei mit dem vorhergehenden Code übereinstimmt. Speichern Sie dann die Datei und beenden Sie den Editor.

Bevor wir das Skript verwenden können, müssen wir es mit dem Befehlchmod ausführbar machen:

chmod +x go-executable-build.bash

Testen Sie das Skript, indem Sie ausführbare Dateien für Caddy erstellen:

./go-executable-build.bash github.com/mholt/caddy/caddy

Wenn alles gut geht, sollten Sie ausführbare Dateien in Ihrem aktuellen Verzeichnis haben. Keine Ausgabe zeigt eine erfolgreiche Skriptausführung an. Sie können überprüfen, ob ausführbare Dateien mit dem Befehllserstellt wurden:

ls caddy*

Sie sollten alle drei Versionen sehen:

Example ls outputcaddy-darwin-amd64 caddy-windows-386.exe caddy-windows-amd64.exe

Um die Zielplattformen zu ändern, ändern Sie einfach die Variableplatformsin Ihrem Skript.

Fazit

In diesem Lernprogramm erfahren Sie, wie Sie mit den Tools von Go Pakete aus Versionskontrollsystemen abrufen und ausführbare Dateien für verschiedene Plattformen erstellen und kompilieren.

Sie haben auch ein Skript erstellt, mit dem Sie ein einzelnes Paket für viele Plattformen übergreifend kompilieren können.

Um sicherzustellen, dass Ihre Anwendung ordnungsgemäß funktioniert, können Sie sichtesting undcontinuous integration wieTravis-CI undAppVeyor zum Testen unter Windows ansehen.

Wenn Sie sich für Caddy interessieren und wissen, wie man es benutzt, schauen Sie sichHow to Host a Website with Caddy on Ubuntu 16.04 an.