ODR-0001 — Zéro cgo, un binaire, trois cibles¶
Statut : accepté Date : 2026-07-31
Décision antérieure, reprise ici
Cette décision a été rendue pendant la conception et vit sous le numéro ADR-001
au § 20 de
docs/02-architecture.md.
Elle ouvre ce registre parce que c'est la première chose qu'un nouvel arrivant doit
comprendre : elle explique la moitié des contraintes qu'il va rencontrer. La version
longue reste là-bas.
Contexte¶
Le parc des coopératives tourne sous Windows. Un basculement vers de petits PC Linux ou ARM était envisagé sans être décidé. Surtout : il n'y a pas de développeur permanent sur ce projet. Le poste sera repris dans trois ans par quelqu'un qui n'était pas là, et qui n'installera pas une chaîne de compilation C pour produire un binaire.
Or Go, dès qu'un module exige cgo, perd la compilation croisée triviale : il faut alors
un compilateur C par cible, ou Docker, ou une machine de construction par plateforme.
Le module SQLite le plus répandu de l'écosystème, mattn/go-sqlite3, exige cgo.
Décision¶
Le binaire se construit avec CGO_ENABLED=0 sur les trois cibles — Windows amd64, Linux
amd64, Linux arm64. SQLite passe par modernc.org/sqlite, une transcription en Go pur.
Toute dépendance exigeant cgo est refusée, quelle que soit sa qualité.
Alternatives écartées¶
| Alternative | Pourquoi non |
|---|---|
mattn/go-sqlite3 |
Plus rapide et plus éprouvé, mais exige cgo : c'est la dépendance qui, à elle seule, aurait imposé une chaîne C sur chaque machine de construction |
| Docker pour la construction croisée | Déplace le problème sans le résoudre, et ajoute un outil à installer et à maintenir pour la personne qui reprendra le dépôt |
| Une machine de construction par plateforme | Trois machines à tenir à jour pour une équipe qui n'a pas de développeur permanent |
gousb pour parler à l'imprimante en USB direct |
Exige cgo, et refusé nommément. L'impression passe par les transports du système |
Conséquences¶
Ce que ça achète. Les trois binaires se construisent depuis n'importe quelle machine, sans Docker et sans compilateur C. Déployer un poste, c'est copier un fichier. Une migration vers un mini-PC ARM ne demande pas de préparer un environnement : c'est une variable d'environnement de plus sur la même commande.
Ce que ça coûte. SQLite en Go pur est en retrait d'environ 30 % sur la version C d'après le dossier d'architecture — sans effet ici, où un poste écrit une trentaine de lignes par minute. Et l'écosystème se referme : chaque nouvelle dépendance doit être vérifiée pur Go avant d'être ajoutée.
Le détecteur de course fait exception, et c'est structurant. -race exige cgo. La
CI joue donc go test deux fois : une passe CGO_ENABLED=1 avec -race, pour
attraper les courses du Hub, et une passe CGO_ENABLED=0 qui prouve que la configuration
réellement livrée compile et passe. Un CGO_ENABLED=0 posé globalement casserait la
première, et le premier contributeur qui rencontrerait l'erreur retirerait -race — on
perdrait la seule vérification automatique des invariants de concurrence.
C'est aussi pourquoi gcc reste un prérequis facultatif d'une machine de
développement : sans lui, la passe -race est sautée avec un avertissement, et la CI
la couvre.
Ce qui le vérifie. Le job build de
.github/workflows/ci.yml
compile les trois cibles en CGO_ENABLED=0 à chaque commit. Une dépendance cgo introduite
par mégarde ne survit pas à la première PR.