1
0
Fork 0
go_plugin_demo/README.md
Frédéric G. MARAND be1f9236e0 Code and findings updated for go 1.27.3.
tl;dr:
- Linux debugging works
- macOS running works, debugging doesn't.
2026-11-02 17:17:20 +01:00

114 lines
5.6 KiB
Markdown

# Démonstration des greffons Go
Un programme hôte, `cmd/demo`, charge deux greffons, `plugins/foo` et `plugins/bar`, par le paquet `plugin`,
et leur confie du travail par une fonction de type `Worker`.
- Écrit en 2020 pour Go 1.14.
- Revérifié le 2026-11-02 avec Go 1.27.3 et Delve 1.27.0 :
méthode et résultats dans [VERIFICATION.md].
## Utilisation
Depuis la racine du dépôt, car les greffons sont chargés par un chemin relatif :
```
make all # hôte et greffons, en mode déboguage
./cmd/demo
make FLAGS= clean all # les mêmes, optimisés
go tool dlv exec ./cmd/demo
```
Delve est épinglé dans `go.mod` par la directive `tool`.
## Déboguage des greffons
Sous Linux, Delve entre dans les greffons :
- points d'arrêt, variables et pas à pas y fonctionnent ;
- les valeurs renvoyées par `plugin.Lookup` s'inspectent sans conversion.
Sous macOS, Delve ne charge pas les informations de déboguage des greffons,
bien qu'elles soient présentes ([go-delve/delve#1628]).
- Il ne peut ni s'arrêter dans un greffon, ni y avancer pas à pas, ni afficher une fonction qui en provient.
- Il passe en revanche par-dessus un appel au greffon (`next`),
et affiche les données renvoyées par `plugin.Lookup`.
## Compilation pour le déboguage avec GoLand
Dans la configuration par défaut, dans un projet compilé avec GoLand,
l'ouverture des greffons par `plugin.Open` échoue avec une valeur d'erreur de la forme :
```
plugin was built with a different version of package <un_paquet>
```
Avec Go 1.27, le paquet désigné est `internal/abi`.
La cause tient en deux points :
- le chargement des greffons s'assure de la compatibilité entre l'appelant et le greffon,
bien au-delà du simple chargement par [`dlopen(3)`],
en vérifiant les versions internes et les drapeaux de compilation des fichiers en jeu[^1] ;
- GoLand ne passe pas de drapeaux spécifiques aux compilations destinées à l'exécution,
mais ajoute `-gcflags="all=-N -l"` à celles destinées au déboguage :
les greffons, compilés à l'avance, le sont sans ces drapeaux,
tandis que le client débogué est compilé avec.
[^1]: Détails dans la fonction `runtime.plugin_lastmoduleinit()` du fichier `src/runtime/plugin.go`.
La solution en découle, à deux niveaux :
- compiler les greffons en mode déboguage avec ce même drapeau :
- dans le champ `Go tool arguments` des configurations d'exécution qui les construisent,
ou dans tout autre mécanisme de construction, comme le `Makefile` de ce dépôt ;
- plus généralement, hôte et greffons doivent partager tous leurs réglages de compilation (`-gcflags`, `-trimpath`, `-race`, étiquettes de construction)
et les mêmes versions de dépendances ;
- prévoir deux constructions séparées, l'une pour le déboguage, l'autre pour la production,
puisque ces drapeaux désactivent les optimisations (`-N`) et l'inlining (`-l`),
ce qui réduit la performance du code.
## Plateformes
Le paquet fonctionne sous Linux, macOS (`darwin`) et FreeBSD, avec cgo.
En Go 1.27, les plateformes acceptées par `-buildmode=plugin` sont :
- Linux : 386, amd64, arm, arm64, loong64, ppc64, ppc64le, riscv64, s390x ;
- Android : 386, amd64 ;
- macOS : amd64, arm64 ;
- FreeBSD : amd64.
La liste fait foi dans la fonction `BuildModeSupported` de `src/internal/platform/supported.go`
(`src/cmd/internal/sys/supported.go` jusqu'à Go 1.19).
Cette prise en charge a évolué depuis l'introduction du paquet en Go 1.8 :
| Version Go | Situation | Linux | macOS | FreeBSD | Commit |
|:----------:|:---------------------------------------------:|:-----:|:-----:|:-------:|:-------:|
| 1.8beta1 | Ajout du paquet `plugin` | X | | | 0cbb12f |
| | Support macOS | X | X | | b444d43 |
| 1.8beta2 | Retrait du support macOS | X | | | c1ada22 |
| 1.8 | Annonce: paquet "early support" | X | | | |
| 1.9beta1 | Paquet documenté comme incomplet | X | | | 3717b42 |
| 1.9rc2 | Paquet documenté comme bogué | X | | | ac29f30 |
| 1.10beta2 | Support macOS | X | X | | 3f5c1ad |
| 1.12beta1 | Import possible sous Windows | X | X | | 4af4dc8 |
| 1.14beta1 | Support FreeBSD/amd64 | X | X | X | 88ca80b |
| 1.16beta1 | Support macOS/arm64 | X | X | X | 7d6b304 |
| 1.20rc1 | Section "Warnings" de la documentation | X | X | X | ee56b3c |
| 1.21rc1 | Retrait d'android/arm et android/arm64 | X | X | X | 56a14ad |
| 1.22rc1 | Support Linux/loong64 | X | X | X | d7fcb5c |
| 1.24rc1 | Avertissement sur le détecteur de compétition | X | X | X | 1443a3e |
| 1.25rc1 | Support Linux/riscv64 | X | X | X | cdc9560 |
| 1.27rc1 | Support Linux/ppc64 (gros-boutiste) | X | X | X | 364de84 |
Importer le paquet `plugin` sous Windows, possible depuis Go 1.12,
ne rend pas le mécanisme de greffons utilisable :
le paquet y fournit des moignons (_stubs_),
pour éviter une erreur de compilation sans étiquette de construction spécifique à Windows.
<!-- link definitions -->
[VERIFICATION.md]: VERIFICATION.md
[go-delve/delve#1628]: https://github.com/go-delve/delve/issues/1628
[`dlopen(3)`]: https://man7.org/linux/man-pages/man3/dlopen.3.html