Compilation croisée et création de releases
Une autre force de Go c’est la simplicité avec laquelle le compilateur peut produire du code pour différentes architectures. Illustrons avec un simple programme Hello World
La structure des fichiers est la suivante :
.
├── cmd
│ └── hello
│ └── main.go
└── go.mod
Le fichier go.mod contient le code suivant :
module demo
go 1.19
et le code Go du programme
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello World!")
}
On génère un exécutable pour ce programme avec la commande go build :
go build ./cmd/hello
Le nom de l’exécutable correspond au nom du dossier dans lequel se trouve le
package main. Dans notre cas, le nom de l’exécutable est hello
(sur une machine de type Unix) ou hello.exe (sur une machine Windows).
On peut changer le nom de l’exécutable avec l’option -o :
go build -o my-great-program ./cmd/hello
ou
go build -o my-great-program.exe ./cmd/hello
Si nous voulons utiliser notre programme sur un Raspberry Pi, nous pouvons
produire un nouveau binaire en modifiant les variables d’environnement
GOOS (GO Operating System) et GOARCH (GO ARCHitecture) :
GOOS=linux GOARCH=arm go build -o hello-for-rpi ./cmd/hello
La commande go tool dist list affiche la liste de toutes les combinaisons possibles de
GOOS/GOARCH :
go tool dist list
Résultat avec go version go1.23.1 darwin/arm64
aix/ppc64 freebsd/arm linux/arm64 netbsd/386 plan9/386
android/386 freebsd/arm64 linux/loong64 netbsd/amd64 plan9/amd64
android/amd64 freebsd/riscv64 linux/mips netbsd/arm plan9/arm
android/arm illumos/amd64 linux/mips64 netbsd/arm64 solaris/amd64
android/arm64 ios/amd64 linux/mips64le openbsd/386 wasip1/wasm
darwin/amd64 ios/arm64 linux/mipsle openbsd/amd64 windows/386
darwin/arm64 js/wasm linux/ppc64 openbsd/arm windows/amd64
dragonfly/amd64 linux/386 linux/ppc64le openbsd/arm64 windows/arm
freebsd/386 linux/amd64 linux/riscv64 openbsd/ppc64 windows/arm64
freebsd/amd64 linux/arm linux/s390x openbsd/riscv64
Utilisation de gox
gox est un outil pour simplifier la génération d’exécutables pour
différentes architectures. Installez le gox avec la commande
suivante :
go install github.com/mitchellh/gox@latest
Vous pouvez maintenant produire les exécutables avec la commande suivante :
gox ./cmd/hello
Vous pouvez aussi spécifier les architectures pour lesquelles vous voulez produire les exécutables :
gox -arch="amd64 arm64" -os="darwin linux windows" ./cmd/hello
Note
gox n’est plus maintenu et le projet est archivé. Vous pouvez
cependant toujours l’utiliser.
Utilisation de GoReleaser
Une autre manière de produire des exécutables est offert par GoReleaser. Pour faire vos premiers pas avec GoReleaser, commencez par installer l’application :
go install github.com/goreleaser/goreleaser@latest
et initialisez le projet :
goreleaser init
vous devriez avoir deux nouveaux fichiers : .gitignore et goreleaser.yaml :
.
├── .gitignore
├── .goreleaser.yaml
├── README.md
├── cmd
│ └── hello
│ └── main.go
└── go.mod
Editez le fichier .goreleaser.yaml pour ajouter les informations sur votre projet :
## .goreleaser.yaml
``` yaml
project_name: hello-world
...
builds:
- main: ./cmd/hello
env:
- CGO_ENABLED=0
...
universal_binaries:
- replace: true
tapez ensuite la commande suivante pour générer les exécutables :
goreleaser build --snapshot --clean
Dans le dossier dist, vous trouverez les exécutables pour différentes
architectures, y-compris un exécutable universel (AMD64/ARM64) pour les Macs (darwin).
• starting build...
• loading path=.goreleaser.yaml
• skipping validate...
• loading environment variables
• getting and validating git state
• accepting to run without a git repository because this is a snapshot
• git state commit=none branch=none current_tag=v0.0.0
previous_tag=<unknown> dirty=false
• pipe skipped reason=disabled during snapshot mode
• parsing tag
• setting defaults
• snapshotting
• building snapshot... version=0.0.0-SNAPSHOT-none
• running before hooks
• running hook=go mod tidy
• running hook=go generate ./...
• checking distribution directory
• cleaning dist
• setting up metadata
• storing release metadata
• writing file=dist/metadata.json
• loading go mod information
• build prerequisites
• writing effective config file
• writing config=dist/config.yaml
• building binaries
• building binary=dist/hello-world_windows_386/hello-world.exe
• building binary=dist/hello-world_windows_arm64/hello-world.exe
• building binary=dist/hello-world_darwin_amd64_v1/hello-world
• building binary=dist/hello-world_linux_386/hello-world
• building binary=dist/hello-world_windows_amd64_v1/hello-world.exe
• building binary=dist/hello-world_darwin_arm64/hello-world
• building binary=dist/hello-world_linux_arm64/hello-world
• building binary=dist/hello-world_linux_amd64_v1/hello-world
• took: 3s
• universal binaries
• creating from 2 binaries id=hello-world
binary=dist/hello-world_darwin_all/hello-world
• storing artifacts metadata
• writing file=dist/artifacts.json
• build succeeded after 2s
• thanks for using goreleaser!
En plus de produire des exécutables, GoReleaser peut aussi créer des releases sur GitHub ou sur GitLab. Lisez la documentation pour plus d’informations.