Comment créer des exécutables pour plusieurs plates-formes sur Ubuntu 16.04

introduction

LeGo programming language est livré avec une riche chaîne d'outils qui facilite incroyablement l'obtention de packages et la création d'exécutables. L’une des fonctionnalités les plus puissantes de Go est la possibilité de créer des exécutables croisés pour toutes les plateformes étrangères prises en charge par Go. Cela facilite grandement les tests et la distribution des packages, car il n’est pas nécessaire d’avoir accès à une plate-forme spécifique pour pouvoir distribuer votre package.

Dans ce didacticiel, vous utiliserez les outils de Go pour obtenir un package à partir du contrôle de version et installer automatiquement son exécutable. Ensuite, vous construirez et installerez manuellement le fichier exécutable afin de vous familiariser avec le processus. Vous construirez ensuite un fichier exécutable pour une architecture différente et automatiserez le processus de construction afin de créer des fichiers exécutables pour plusieurs plates-formes. Lorsque vous aurez terminé, vous saurez comment créer des exécutables pour Windows et macOS, ainsi que pour les autres plates-formes que vous souhaitez prendre en charge.

Conditions préalables

Pour suivre ce tutoriel, vous aurez besoin de:

[[step-1 -—- Installing-go-programs-from-version-control]] == Étape 1 - Installation des programmes Go à partir du contrôle de version

Avant de pouvoir créer des exécutables à partir d’un package Go, nous devons obtenir son code source. L'outilgo get peut récupérer des packages à partir de systèmes de contrôle de version comme GitHub. Sous le capot,go get clone les packages dans les sous-répertoires du répertoire$GOPATH/src/. Puis, le cas échéant, il installe le paquet en construisant son exécutable et en le plaçant dans le répertoire$GOPATH/bin. Si vous avez configuré Go comme décrit dans les didacticiels prérequis, le répertoire$GOPATH/bin est inclus dans votre variable d'environnement$PATH, ce qui garantit que vous pouvez utiliser les packages installés à partir de n'importe où sur votre système.

La syntaxe de la commandego get estgo get package-import-path. Lepackage-import-path est une chaîne qui identifie un package de manière unique. Il s'agit souvent de l'emplacement du package dans un référentiel distant comme Github, ou dans un répertoire dans le répertoire$GOPATH/src/ de votre machine.

Il est courant d’utilisergo get avec l’indicateur-u, qui demande àgo get d’obtenir le package et ses dépendances, ou de mettre à jour ces dépendances si elles sont déjà présentes sur la machine.

Dans ce tutoriel, nous allons installerCaddy, un serveur Web écrit en Go. PourCaddy’s instructionsx, nous utiliseronsgithub.com/mholt/caddy/caddy pour le chemin d’importation du package. Utilisezgo get pour récupérer et installer Caddy:

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

La commande prendra un certain temps, mais vous ne constaterez aucune progression pendant la récupération et l’installation du package. Aucune sortie n'indique réellement que la commande a été exécutée avec succès.

Une fois la commande terminée, vous trouverez le code source de Caddy disponible à$GOPATH/src/github.com/mholt/caddy. De plus, comme Caddy a un exécutable, il a été automatiquement créé et stocké dans le répertoire$GOPATH/bin. Vérifiez cela en utilisantwhich pour imprimer l'emplacement de l'exécutable:

which caddy

Vous verrez le résultat suivant:

Output/home/sammy/work/bin/caddy

[.Remarque]##

Note: La commandego get installe les packages à partir de la branche par défaut d'un référentiel Git, qui dans de nombreux cas est la branchemaster ou en développement. Assurez-vous de lire les instructions, généralement situées dans le fichierREADME du référentiel, avant d’utilisergo get.

Vous pouvez utiliser des commandes Git commegit checkout pour sélectionner une branche différente sur les sources obtenues à l'aide de la commandego get. Consultez le didacticielHow to Use Git Branches pour en savoir plus sur la façon de changer de branche.

Examinons plus en détail le processus d’installation des packages Go, en commençant par la création d’exécutables à partir de packages déjà obtenus.

[[step-2 -—- building-an-executable]] == Étape 2 - Construire un exécutable

La commandego get a téléchargé la source et installé l'exécutable de Caddy pour nous en une seule commande. Mais vous voudrez peut-être reconstruire l'exécutable vous-même ou construire un exécutable à partir de votre propre code. La commandego build crée des exécutables.

Bien que nous ayons déjà installé Caddy, reconstruisons-le manuellement pour que nous puissions nous familiariser avec le processus. Exécutezgo build et spécifiez le chemin d’importation du package:

go build github.com/mholt/caddy/caddy

Comme auparavant, aucune sortie n'indique une opération réussie. L'exécutable sera généré dans votre répertoire actuel, avec le même nom que le répertoire contenant le package. Dans ce cas, l'exécutable sera nommécaddy.

Si vous vous trouvez dans le répertoire du package, vous pouvez omettre le chemin d’accès au package et simplement exécutergo build.

Pour spécifier un nom ou un emplacement différent pour l'exécutable, utilisez l'indicateur-o. Construisons un exécutable appelécaddy-server et placez-le dans un répertoirebuild dans le répertoire de travail actuel:

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

Cette commande crée l'exécutable et crée également le répertoire./build s'il n'existe pas.

Voyons maintenant comment installer des exécutables.

[[step-3 -—- installation-d'un-executable]] == Étape 3 - Installation d'un exécutable

La construction d'un exécutable crée l'exécutable dans le répertoire en cours ou dans le répertoire de votre choix. L'installation d'un exécutable consiste à créer un exécutable et à le stocker dans$GOPATH/bin. La commandego install fonctionne exactement commego build, maisgo install prend soin de placer le fichier de sortie au bon endroit pour vous.

Pour installer un exécutable, utilisezgo install, suivi du chemin d’importation du package. Encore une fois, utilisez Caddy pour essayer ceci:

go install github.com/mholt/caddy/caddy

Tout comme avecgo build, vous ne verrez aucune sortie si la commande a réussi. Et comme auparavant, l'exécutable est créé avec le même nom que le répertoire contenant le package. Mais cette fois, l'exécutable est stocké dans$GOPATH/bin. Si$GOPATH/bin fait partie de votre variable d'environnement$PATH, l'exécutable sera disponible de n'importe où sur votre système d'exploitation. Vous pouvez vérifier son emplacement à l'aide de la commandewhich:

which caddy

Vous verrez le résultat suivant:

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

Maintenant que vous comprenez le fonctionnement dego get,go build etgo install, et comment ils sont liés, explorons l'une des fonctionnalités Go les plus populaires: la création d'exécutables pour d'autres plates-formes cibles.

[[step-4 -—- building-executables-for-different-architectures]] == Étape 4 - Construire des exécutables pour différentes architectures

La commandego build vous permet de créer un fichier exécutable pour toute plate-forme cible prise en charge par Go,on your platform. Cela signifie que vous pouvez tester, publier et distribuer votre application sans créer ces exécutables sur les plates-formes cibles que vous souhaitez utiliser.

La compilation croisée fonctionne en définissant les variables d'environnement requises qui spécifient le système d'exploitation et l'architecture cibles. Nous utilisons la variableGOOS pour le système d'exploitation cible etGOARCH pour l'architecture cible. Pour construire un exécutable, la commande prendrait la forme suivante:

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

La commandeenv exécute un programme dans un environnement modifié. Cela vous permet d'utiliser des variables d'environnement uniquement pour l'exécution de la commande en cours. Les variables sont désactivées ou réinitialisées après l'exécution de la commande.

Le tableau suivant présente les combinaisons possibles deGOOS etGOARCH que vous pouvez utiliser:

GOOS - Système d'exploitation cible GOARCH - Plateforme cible

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

[.Attention]##

Warning: La compilation croisée d'exécutables pour Android nécessite lesAndroid NDK et une configuration supplémentaire qui dépasse le cadre de ce didacticiel.

En utilisant les valeurs du tableau, nous pouvons construire Caddy pour Windows 64 bits comme ceci:

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

Encore une fois, aucune sortie n'indique que l'opération a réussi. L'exécutable sera créé dans le répertoire en cours, en utilisant le nom du package comme nom. Cependant, puisque nous avons construit cet exécutable pour Windows, le nom se termine par le suffixe.exe.

Vous devriez avoir le fichiercaddy.exe dans votre répertoire actuel, que vous pouvez vérifier avec la commandels.

ls caddy.exe

Vous verrez le fichiercaddy.exe répertorié dans la sortie:

Outputcaddy.exe

[.note] #Note: Vous pouvez utiliser l'indicateur-o pour renommer l'exécutable ou le placer dans un emplacement différent. Cependant, lorsque vous créez un exécutable pour Windows et que vous fournissez un nom différent, veillez à spécifier explicitement le suffixe `.exe` lors de la définition du nom de l'exécutable.
#

Examinons ce processus par script pour faciliter la publication de logiciels pour plusieurs environnements cibles.

[[step-5 -—- creation-a-script-to-automate-cross-compilation]] == Étape 5 - Création d'un script pour automatiser la cross-compilation

Le processus de création d’exécutables pour de nombreuses plateformes peut être un peu fastidieux, mais nous pouvons créer un script pour faciliter les choses.

Le script prend en argument le chemin d'importation du package, parcourt une liste prédéfinie de paires système / plate-forme et génère un exécutable pour chaque paire, en plaçant la sortie dans le répertoire en cours. Chaque exécutable sera nommé avec le nom du package, suivi de la plate-forme et de l'architecture cible, sous la formepackage-OS-architecture. Ce sera un script universel que vous pouvez utiliser sur n'importe quel projet.

Basculez vers votre répertoire personnel et créez un nouveau fichier appelégo-executable-build.bash dans votre éditeur de texte:

cd ~
nano go-executable-build.bash

Nous allons commencer notre script avec une ligneshebang. Cette ligne définit l’interprète qui analysera ce script lorsqu’il sera exécuté en tant qu’exécutable. Ajoutez la ligne suivante pour spécifier quebash doit exécuter ce script:

go-executable-build.bash

#!/usr/bin/env bash

Nous voulons prendre le chemin d'importation du package comme argument de ligne de commande. Pour ce faire, nous utiliserons la variable$n, oùn est un nombre non négatif. La variable$0 contient le nom du script que vous avez exécuté, tandis que$1 et supérieur contiendra les arguments fournis par l'utilisateur. Ajoutez cette ligne au script, qui prendra le premier argument de la ligne de commande et le stockera dans une variable appeléepackage:

go-executable-build.bash

...
package=$1

Ensuite, assurez-vous que l'utilisateur a fourni cette valeur. Si la valeur n'est pas fournie, quittez le script avec un message expliquant comment utiliser le script:

go-executable-build.bash

...

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

Cette instructionif vérifie la valeur de la variable$package. S'il n'est pas défini, nous utilisonsecho pour imprimer l'utilisation correcte, puis terminons le script en utilisantexit. exit prend une valeur de retour comme argument, qui doit être0 pour les exécutions réussies et toute valeur différente de zéro pour les exécutions infructueuses. Nous utilisons1 ici car le script n'a pas réussi.

[.Remarque]##

Note: Si vous souhaitez que ce script fonctionne avec un package prédéfini, modifiez la variablepackage pour qu'elle pointe vers ce chemin d'importation:

go-executable-build.bash

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

Ensuite, nous voulons extraire le nom du paquet du chemin. Le chemin d’importation du package est délimité par les caractères/, le nom du package se trouvant à la fin du chemin. Tout d'abord, nous allons diviser le chemin d'importation du package en un tableau, en utilisant les/ comme délimiteur:

go-executable-build.bash

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

Le nom du package doit être le dernier élément de ce nouveau tableau$package_split. Dans Bash, vous pouvez utiliser un index de tableau négatif pour accéder à un tableau de la fin au lieu du début. Ajoutez cette ligne pour récupérer le nom du package dans le tableau et le stocker dans une variable appeléepackage_name:

go-executable-build.bash

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

À présent, vous devez choisir les plates-formes et les architectures pour lesquelles vous souhaitez créer des exécutables. Dans ce didacticiel, nous allons créer des exécutables pour Windows MacOS 64 bits, Windows 32 bits et 64 bits. Nous allons placer ces cibles dans un tableau au formatOS/Platform, afin que nous puissions diviser chaque paire en variablesGOOS etGOARCH en utilisant la même méthode que nous avons utilisée pour extraire le nom du package du chemin . Ajoutez les plateformes au script:

go-executable-build.bash

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

Ensuite, nous allons parcourir le tableau de plates-formes, diviser chaque entrée de plate-forme en valeurs pour les variables d'environnementGOOS etGOARCH, et les utiliser pour créer l'exécutable. Nous pouvons le faire avec la bouclefor suivante:

go-executable-build.bash

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

La variableplatform contiendra une entrée du tableauplatforms à chaque itération. Nous devons diviserplatform en deux variables -GOOS etGOARCH. Ajoutez les lignes suivantes à la bouclefor:

go-executable-build.bash

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

done

Ensuite, nous allons générer le nom de l’exécutable en combinant le nom du package avec le système d’exploitation et l’architecture. Lorsque nous construisons pour Windows, nous devons également ajouter le suffixe.exe au nom de fichier. Ajoutez ce code à la bouclefor:

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

Avec les variables définies, nous utilisonsgo build pour créer l'exécutable. Ajoutez cette ligne au corps de la bouclefor, juste au-dessus du mot clédone:

go-executable-build.bash

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

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

done

Enfin, nous devrions vérifier s'il y a eu des erreurs lors de la construction de l'exécutable. Par exemple, nous pourrions rencontrer une erreur si nous essayons de construire un paquet pour lequel nous n’avons pas de sources. Nous pouvons vérifier le code de retour de la commandego build pour une valeur non nulle. La variable$? contient le code retour de l’exécution d’une commande précédente. Sigo build renvoie autre chose que0, il y a eu un problème et nous voudrons quitter le script. Ajoutez ce code à la bouclefor, après la commandego build et au-dessus du mot clédone.

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

Avec cela, nous avons maintenant un script qui va générer plusieurs exécutables à partir de notre paquet Go. Voici le script terminé:

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

Vérifiez que votre fichier correspond au code précédent. Enregistrez ensuite le fichier et quittez l'éditeur.

Avant de pouvoir utiliser le script, nous devons le rendre exécutable avec la commandechmod:

chmod +x go-executable-build.bash

Enfin, testez le script en construisant des exécutables pour Caddy:

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

Si tout se passe bien, vous devriez avoir des exécutables dans votre répertoire actuel. Aucune sortie ne signifie que l'exécution du script a réussi Vous pouvez vérifier si des exécutables sont créés à l'aide de la commandels:

ls caddy*

Vous devriez voir les trois versions:

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

Pour changer les plates-formes cibles, changez simplement la variableplatforms dans votre script.

Conclusion

Dans ce tutoriel, vous avez appris à utiliser les outils de Go pour obtenir des packages à partir de systèmes de contrôle de version, ainsi que pour compiler et compiler des exécutables pour différentes plates-formes.

Vous avez également créé un script que vous pouvez utiliser pour compiler de manière croisée un seul package pour plusieurs plates-formes.

Pour vous assurer que votre application fonctionne correctement, vous pouvez jeter un œil àtesting etcontinuous integration commeTravis-CI etAppVeyor pour les tester sous Windows.

Si vous êtes intéressé par Caddy et comment l'utiliser, jetez un œil àHow to Host a Website with Caddy on Ubuntu 16.04.