tl;dr: - Linux debugging works - macOS running works, debugging doesn't.
114 lines
5.6 KiB
Markdown
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
|