
Compilation pour différentes plateformes
Maîtrisez la compilation cross-platform en Go : compilation croisée, GOOS, GOARCH, CGO, architectures supportées, build tags et bonnes pratiques pour déployer vos applications Go partout.
Introduction à la compilation cross-platform en Go : Le slogan "Write Once, Run Anywhere"
L'un des atouts majeurs de Go est sa capacité à la compilation cross-platform (ou compilation croisée). La compilation cross-platform permet de compiler votre code Go une seule fois sur votre machine de développement, et de générer des binaires exécutables qui peuvent être exécutés sur différentes plateformes (systèmes d'exploitation et architectures processeur) sans nécessiter de recompilation sur chaque plateforme cible. Ce principe, souvent résumé par le slogan "Write Once, Run Anywhere" (écrire une fois, exécuter partout), simplifie considérablement le processus de build, de packaging, et de déploiement des applications Go sur diverses plateformes.
Grâce à la compilation cross-platform de Go, vous pouvez développer votre application Go sur votre machine de développement (par exemple, macOS ou Windows), et compiler des binaires exécutables pour Linux, Windows, macOS, FreeBSD, NetBSD, OpenBSD, Plan 9, Solaris, Android, iOS, et d'autres systèmes d'exploitation, et pour différentes architectures processeur (amd64, arm64, 386, arm, ppc64le, mips64le, wasm, etc.). Cette capacité de compilation cross-platform est particulièrement précieuse pour le développement d'applications web, de microservices, d'outils en ligne de commande, et de tout type d'application Go qui doit être déployée sur des environnements variés et hétérogènes.
Ce chapitre vous propose un guide complet sur la compilation cross-platform en Go. Nous allons explorer en détail les mécanismes de la compilation croisée de Go, comment utiliser les variables d'environnement GOOS et GOARCH pour cibler différentes plateformes, comment gérer les dépendances C/C++ (CGO) dans la compilation cross-platform, comment lister les architectures supportées par Go, comment utiliser les build tags pour compiler conditionnellement du code en fonction de la plateforme, et les bonnes pratiques pour le build et le déploiement cross-platform de vos applications Go. Que vous soyez débutant ou développeur expérimenté, ce guide vous fournira les clés pour maîtriser la compilation cross-platform en Go et déployer vos applications Go sur toutes les plateformes cibles de manière simple, rapide, et efficace.
Variables d'environnement GOOS et GOARCH : Cibler les plateformes
Le mécanisme central de la compilation cross-platform en Go repose sur l'utilisation des variables d'environnement GOOS et GOARCH. Ces variables d'environnement permettent de spécifier la plateforme cible (système d'exploitation et architecture processeur) pour laquelle vous souhaitez compiler votre code Go.
Variables d'environnement GOOS et GOARCH : Définition de la plateforme cible
GOOS(Go Operating System) : Spécifie le système d'exploitation cible (Operating System) pour la compilation. Valeurs courantes deGOOS:linux: Linuxwindows: Windowsdarwin: macOS (Darwin)freebsd: FreeBSDnetbsd: NetBSDopenbsd: OpenBSDplan9: Plan 9solaris: Solarisandroid: Androidios: iOS
GOOSsupportées :go tool dist list).GOARCH(Go Architecture) : Spécifie l'architecture processeur cible (Architecture) pour la compilation. Valeurs courantes deGOARCH:amd64: x86-64 (AMD64, Intel 64) - Architectures 64-bit x86 courantes (ordinateurs de bureau, serveurs, laptops).386: x86 (32-bit x86) - Architectures 32-bit x86 plus anciennes.arm64(ouarm64) : ARM 64-bit (AArch64) - Architectures ARM 64-bit (smartphones, tablettes, systèmes embarqués, serveurs ARM récents comme AWS Graviton, etc.).arm(ouarm) : ARM 32-bit (ARMv5, ARMv6, ARMv7) - Architectures ARM 32-bit plus anciennes (systèmes embarqués, appareils mobiles anciens).wasm: WebAssembly - Architecture WebAssembly (pour exécuter du code Go dans les navigateurs web ou les environnements WebAssembly).ppc64le: PowerPC 64-bit Little Endian - Architectures PowerPC 64-bit (serveurs PowerPC).mips64le: MIPS 64-bit Little Endian - Architectures MIPS 64-bit (systèmes embarqués MIPS).
GOARCHsupportées :go tool dist list).
Compilation pour la plateforme courante (par défaut) :
Par défaut, si vous exécutez la commande go build (ou go run, go test, etc.) sans spécifier les variables d'environnement GOOS et GOARCH, Go compile votre code pour la plateforme (système d'exploitation et architecture processeur) sur laquelle vous exécutez la commande go build (votre machine de développement). Par exemple, si vous exécutez go build main.go sur macOS sur un Mac Intel, Go compilera un binaire exécutable pour macOS/amd64.
Compilation cross-platform : Spécification de GOOS et GOARCH lors du build
Pour effectuer une compilation cross-platform et générer un binaire exécutable pour une plateforme cible différente de votre plateforme de développement, vous devez spécifier les variables d'environnement GOOS et GOARCH avant d'exécuter la commande go build.
Syntaxe pour spécifier GOOS et GOARCH lors du build :
- Linux/amd64 :
GOOS=linux GOARCH=amd64 go build main.go - Windows/amd64 :
GOOS=windows GOARCH=amd64 go build main.go - macOS/arm64 (Apple Silicon) :
GOOS=darwin GOARCH=arm64 go build main.go - Exemple générique (remplacez
linuxetamd64par la plateforme cible souhaitée) :GOOS=linux GOARCH=amd64 go build -o mon_executable_linux_amd64 main.go # Spécifier un nom de fichier de sortie avec -o
Liste des plateformes supportées par Go : go tool dist list
Pour obtenir la liste complète des plateformes (combinaisons GOOS/GOARCH) supportées par votre version de Go, exécutez la commande go tool dist list dans votre terminal.
go tool dist list
Cette commande affichera une liste de chaînes de caractères au format "os/arch", représentant toutes les combinaisons GOOS/GOARCH pour lesquelles Go peut compiler des binaires exécutables (par exemple, android/386, darwin/amd64, linux/arm64, windows/386, etc.). Utilisez cette liste pour vérifier si la plateforme cible pour laquelle vous souhaitez compiler est bien supportée par votre version de Go.
Compilation croisée (Cross-compilation) : Compiler depuis n'importe quelle plateforme vers n'importe quelle plateforme
La puissance de la compilation cross-platform de Go réside dans sa capacité à effectuer de la compilation croisée (cross-compilation) : compiler votre code Go sur n'importe quelle plateforme de développement (système d'exploitation et architecture processeur) pour générer des binaires exécutables pour n'importe quelle autre plateforme cible supportée par Go.
Développer sur macOS et compiler pour Linux, Windows, etc. : Cas d'usage typique
Un cas d'usage typique et très courant de la compilation croisée en Go est de développer votre application web ou votre microservice Go sur votre machine de développement locale (qui est souvent un Mac pour de nombreux développeurs), et de compiler des binaires exécutables pour Linux/amd64, la plateforme de déploiement cible la plus fréquente pour les serveurs web et les applications backend (serveurs Linux dans le cloud, conteneurs Docker basés sur Linux, etc.).
Exemple de compilation croisée : Compiler sur macOS pour Linux/amd64 et Windows/amd64
Supposons que vous développiez votre application web Go sur macOS (sur un Mac Intel ou Apple Silicon). Pour compiler des binaires exécutables pour Linux/amd64 et Windows/amd64, exécutez les commandes suivantes dans le répertoire racine de votre projet Go :
- Compilation pour Linux/amd64 (depuis macOS) :
Cette commande va générer un binaire exécutable nomméGOOS=linux GOARCH=amd64 go build -o mon_app_linux_amd64mon_app_linux_amd64, qui est compatible avec Linux et l'architecture processeur amd64 (x86-64). - Compilation pour Windows/amd64 (depuis macOS) :
Cette commande va générer un binaire exécutable nomméGOOS=windows GOARCH=amd64 go build -o mon_app_windows_amd64.exemon_app_windows_amd64.exe(avec l'extension.exetypique de Windows), qui est compatible avec Windows et l'architecture processeur amd64 (x86-64).
Vous pouvez ensuite déployer les binaires mon_app_linux_amd64 sur des serveurs Linux et mon_app_windows_amd64.exe sur des serveurs Windows, sans avoir à recompiler le code source sur ces plateformes cibles. La compilation croisée de Go simplifie considérablement le processus de build et de déploiement multiplateforme.
Compilation cross-platform avec CGO (dépendances C/C++) : Limitations et considérations
La compilation cross-platform de Go fonctionne parfaitement par défaut pour le code Go pur Go (code Go qui ne dépend pas de code C/C++ externe). Cependant, si votre projet Go utilise des dépendances C/C++ via CGO (chapitre 28), la compilation cross-platform peut devenir plus complexe et nécessiter des étapes de configuration supplémentaires.
Limitations de CGO pour la compilation cross-platform :
- Dépendances C/C++ spécifiques à la plateforme : Les dépendances C/C++ sont généralement compilées pour une plateforme cible spécifique (système d'exploitation et architecture processeur). Pour compiler cross-platform un projet Go qui utilise CGO, vous devez vous assurer que les bibliothèques C/C++ (et leurs headers) nécessaires sont disponibles pour la plateforme cible, et que le compilateur C/C++ (utilisé par CGO) est configuré pour compiler le code C/C++ pour la plateforme cible.
- Configuration de l'environnement de compilation croisée pour CGO : La compilation cross-platform avec CGO nécessite de configurer un environnement de compilation croisée (cross-compilation environment) qui permet de compiler du code C/C++ pour une plateforme cible différente de votre plateforme de développement. La configuration d'un environnement de compilation croisée pour CGO peut être plus complexe et plus dépendante du système d'exploitation et des outils de build utilisés.
- Complexité accrue du build et du déploiement : La compilation cross-platform avec CGO ajoute de la complexité au processus de build et de déploiement, en particulier pour les projets qui ciblent un grand nombre de plateformes différentes. Vous devez gérer la compilation croisée du code C/C++ pour chaque plateforme cible, la gestion des dépendances C/C++ spécifiques à chaque plateforme, et la création d'artefacts de déploiement multiplateformes (binaires exécutables, packages, conteneurs Docker multi-architectures, etc.).
Bonnes pratiques pour la compilation cross-platform avec CGO :
- Eviter CGO si possible (pour la compilation cross-platform simple) : Si la compilation cross-platform est une priorité pour votre projet Go, évitez d'utiliser CGO et de dépendre de code C/C++ externe autant que possible. Le code Go pur Go se compile cross-platform très facilement et sans configuration supplémentaire, tandis que CGO ajoute de la complexité et des limitations à la compilation cross-platform. Si vous avez le choix, privilégiez des solutions Go natives (bibliothèques Go, code Go pur) plutôt que de dépendre de bibliothèques C/C++ externes, pour simplifier la compilation cross-platform et la portabilité de votre code Go.
- Utiliser Docker pour la compilation croisée CGO (environnements de build isolés et reproductibles) : Pour les projets Go qui utilisent CGO et qui nécessitent la compilation cross-platform, l'utilisation de Docker pour créer des environnements de build isolés et reproductibles peut simplifier considérablement la configuration de la compilation croisée. Créez des images Docker multi-architectures (multi-architecture Docker images) qui contiennent les outils de compilation croisée et les bibliothèques C/C++ nécessaires pour chaque plateforme cible. Utilisez un pipeline CI/CD basé sur Docker pour automatiser le build cross-platform et la création d'images Docker multi-architectures pour chaque plateforme cible.
- Consulter la documentation CGO et les guides de compilation croisée Go : Consultez attentivement la documentation CGO de Go et les guides de compilation croisée Go (disponibles sur le site web de Go et dans la documentation du Go toolchain) pour comprendre les spécificités et les limitations de la compilation cross-platform avec CGO, et pour obtenir des instructions détaillées sur la configuration des environnements de compilation croisée et la résolution des problèmes potentiels.
La compilation cross-platform de Go est une fonctionnalité puissante et précieuse, qui simplifie considérablement le build et le déploiement multiplateforme des applications Go, en particulier pour le code Go pur Go. La compilation cross-platform avec CGO est possible, mais plus complexe et nécessite une configuration et une gestion des dépendances C/C++ spécifiques à chaque plateforme cible.
Conteneurisation avec Docker : Packaging et déploiement multiplateforme simplifié
La conteneurisation avec Docker est une technique de déploiement moderne et largement adoptée, qui se marie particulièrement bien avec la compilation cross-platform de Go pour simplifier et optimiser le packaging et le déploiement multiplateforme des applications Go. Docker permet de packager votre application Go (binaire exécutable et dépendances) dans un conteneur Docker léger et autonome, qui peut être exécuté de manière consistante et reproductible sur n'importe quelle plateforme (Linux, Windows, macOS, cloud, etc.) qui supporte Docker.
Avantages de la conteneurisation Docker pour le déploiement cross-platform Go :
- Packaging multiplateforme simplifié : Docker simplifie considérablement le packaging multiplateforme des applications Go. Au lieu de compiler des binaires exécutables différents pour chaque plateforme cible, vous construisez une seule image Docker multi-architecture (multi-architecture Docker image) qui contient le binaire exécutable Go et toutes les dépendances nécessaires pour plusieurs plateformes (Linux/amd64, Linux/arm64, Windows/amd64, macOS/amd64, etc.). Docker gère automatiquement la sélection de la bonne architecture de l'image Docker lors du déploiement sur une plateforme cible spécifique. La création d'images Docker multi-architectures est facilitée par les fonctionnalités de Docker Buildx et les manifests d'images Docker.
- Environnement d'exécution isolé et reproductible : Docker fournit un environnement d'exécution isolé et reproductible pour votre application Go. Le conteneur Docker encapsule votre application et toutes ses dépendances (runtime Go, bibliothèques système, fichiers de configuration, assets, etc.) dans une image Docker autonome, garantissant que l'application s'exécute de manière consistante et prévisible sur n'importe quel environnement Docker, indépendamment des différences entre les systèmes d'exploitation sous-jacents. La conteneurisation Docker élimine les problèmes de "ça marche sur ma machine, mais pas en production" liés aux différences d'environnement et de configuration.
- Facilité de déploiement et d'orchestration : Les conteneurs Docker sont le format de déploiement standard pour les applications cloud et les architectures de microservices. Les images Docker peuvent être facilement déployées et orchestrées sur différentes plateformes cloud (AWS, GCP, Azure, etc.) et plateformes d'orchestration de conteneurs (Kubernetes, Docker Swarm, etc.). Docker simplifie le processus de déploiement et d'orchestration des applications Go, en particulier dans les environnements cloud et distribués.
- Scalabilité et portabilité : Les applications Go conteneurisées avec Docker sont facilement scalables horizontalement et portables entre différents environnements cloud et infrastructures. Vous pouvez scaler horizontalement votre application en déployant plusieurs instances (répliques) de l'image Docker, et déployer la même image Docker sur différentes plateformes cloud ou infrastructures hybrides, sans nécessiter de modifications du code source ou de la configuration de l'application.
Workflow de conteneurisation Docker pour une application Go cross-platform :
- Créer un Dockerfile multi-stage : Créez un Dockerfile multi-stage à la racine de votre projet Go. Un Dockerfile multi-stage permet de définir un build en plusieurs étapes, en utilisant une image de build pour la compilation du code Go (et la gestion des dépendances CGO si nécessaire), et une image runtime minimale pour l'exécution du binaire exécutable Go. Les Dockerfiles multi-stage permettent de réduire la taille des images Docker finales et d'améliorer la sécurité en séparant l'environnement de build de l'environnement runtime.
- Compiler cross-platform dans l'image de build (étape builder) : Dans l'étape builder du Dockerfile, utilisez la commande
go buildavec les variables d'environnementGOOSetGOARCHpour compiler votre code Go pour les plateformes cibles souhaitées (Linux/amd64, Linux/arm64, Windows/amd64, etc.). Créez un binaire exécutable pour chaque plateforme cible et placez-les dans des répertoires séparés (par exemple,bin/linux_amd64,bin/windows_amd64.exe). Si votre projet utilise CGO, configurez l'environnement de compilation croisée CGO dans l'image de build pour compiler correctement le code C/C++ pour chaque plateforme cible. - Créer une image Docker multi-architecture (manifest) :
docker buildx build --platform ... --push: Utilisez la commandedocker buildx build(avec le plugin Docker Buildx activé) pour construire une image Docker multi-architecture (multi-platform Docker image) à partir de votre Dockerfile. Spécifiez les plateformes cibles souhaitées avec l'option--platform linux/amd64,linux/arm64,windows/amd64(ou les plateformes cibles que vous souhaitez supporter). Utilisez l'option--pushpour pousser l'image Docker multi-architecture vers un registre d'images Docker (Docker Hub, Google Container Registry, AWS ECR, Azure Container Registry, etc.). Docker Buildx se charge de compiler cross-platform le code Go pour chaque plateforme cible (en utilisant les variablesGOOSetGOARCH), d'assembler les binaires exécutables et les ressources dans une image Docker multi-architecture, et de créer un manifest d'image Docker qui décrit les différentes architectures supportées par l'image. - Déployer l'image Docker multi-architecture : Déployez l'image Docker multi-architecture vers votre plateforme de déploiement cible (Kubernetes, Docker Swarm, AWS ECS, GCP Cloud Run, Azure Container Instances, etc.). La plateforme de déploiement Docker détectera automatiquement l'architecture de la plateforme cible et téléchargera et exécutera automatiquement la partie appropriée de l'image Docker multi-architecture (le binaire exécutable compilé pour la plateforme cible). Le déploiement d'une image Docker multi-architecture simplifie considérablement le déploiement cross-platform : vous déployez une seule image Docker, et Docker se charge de choisir et d'exécuter la bonne architecture pour chaque plateforme cible.
Exemple de Dockerfile multi-stage pour une application Go cross-platform (compilation pour Linux/amd64 et Linux/arm64) :
# Stage 1: Builder (Compilation multiplateforme)
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
ARG TARGETOS
ARG TARGETARCH
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o bin/app_${TARGETOS}_${TARGETARCH} main.go
# Stage 2: Runner (Image runtime minimale)
FROM alpine:latest AS runner
WORKDIR /app
COPY --from=builder /app/bin/app_${TARGETOS}_${TARGETARCH} ./app
EXPOSE 8080
CMD ["./app"]
Ce Dockerfile multi-stage utilise une image builder (golang:1.21-alpine) pour compiler cross-platform le code Go pour les plateformes Linux/amd64 et Linux/arm64 (via les arguments de build TARGETOS et TARGETARCH), et une image runner (alpine:latest) minimale pour l'exécution du binaire exécutable. La commande docker buildx build --platform linux/amd64,linux/arm64 --push -t mon_repo/mon_image:latest . (exécutée avec Docker Buildx activé) permet de construire une image Docker multi-architecture qui supporte les deux plateformes Linux/amd64 et Linux/arm64 et de la pousser vers un registre Docker.