Liste de diffusion : bazel-go-discuss
Slack : #allez sur Bazel Slack, #bazel sur Go Slack
Les règles sont en phase bêta de développement. Ils soutiennent :
Ils ne prennent actuellement pas en charge ou ont une prise en charge limitée pour :
Les règles Go sont testées et prises en charge sur les plateformes hôtes suivantes :
Les utilisateurs ont signalé du succès sur plusieurs autres plateformes, mais les règles ne sont testées que sur celles répertoriées ci-dessus.
Remarque : Depuis la version v0.38.0, Rules_go nécessite Bazel ≥ 5.4.0 pour fonctionner.
La branche master
est uniquement garantie de fonctionner avec la dernière version de Bazel.
Pour créer du code Go avec Bazel, vous aurez besoin de :
patch
, cat
et une poignée d'autres outils Unix dans PATH
.Vous n’aurez normalement pas besoin d’installer une chaîne d’outils Go. Bazel en téléchargera un.
Consultez Utilisation de Rules_go sous Windows pour obtenir des instructions de configuration spécifiques à Windows. Plusieurs outils supplémentaires doivent être installés et configurés.
Si vous utilisez le nouveau système de gestion des dépendances externes de Bazel, Bzlmod, reportez-vous plutôt au guide dédié Go with Bzlmod.
Créez un fichier en haut de votre référentiel nommé WORKSPACE
et ajoutez l'extrait ci-dessous (ou ajoutez-le à votre WORKSPACE
existant). Cela indique à Bazel de récupérer Rules_go et ses dépendances. Bazel téléchargera une chaîne d'outils Go récente prise en charge et l'enregistrera pour utilisation.
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
http_archive (
name = "io_bazel_rules_go" ,
integrity = "sha256-M6zErg9wUC20uJPJ/B3Xqb+ZjCPn/yxFF3QdQEmpdvg=" ,
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" ,
"https://github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" ,
],
)
load ( "@io_bazel_rules_go//go:deps.bzl" , "go_register_toolchains" , "go_rules_dependencies" )
go_rules_dependencies ()
go_register_toolchains ( version = "1.23.1" )
Vous pouvez utiliser Rules_go sur master
en utilisant git_repository au lieu de http_archive et en pointant vers une validation récente.
Ajoutez un fichier nommé BUILD.bazel
dans le répertoire racine de votre projet. Vous aurez besoin d'un fichier de build dans chaque répertoire avec du code Go, mais vous en aurez également besoin dans le répertoire racine, même si votre projet n'y contient pas de code Go. Pour un binaire « Hello, world », le fichier devrait ressembler à ceci :
load ( "@io_bazel_rules_go//go:def.bzl" , "go_binary" )
go_binary (
name = "hello" ,
srcs = [ "hello.go" ],
)
Vous pouvez créer cette cible avec bazel build //:hello
.
Si votre projet peut être construit avec go build
, vous pouvez générer et mettre à jour automatiquement vos fichiers de construction à l'aide de gazelle.
Ajoutez le référentiel bazel_gazelle
et ses dépendances à votre WORKSPACE
. Cela devrait ressembler à ceci :
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" ) http_archive ( name = "io_bazel_rules_go" , integrity = "sha256-M6zErg9wUC20uJPJ/B3Xqb+ZjCPn/yxFF3QdQEmpdvg=" , urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" , "https://github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" , ], ) http_archive ( name = "bazel_gazelle" , integrity = "sha256-12v3pg/YsFBEQJDfooN6Tq+YKeEWVhjuNdzspcvfWNU=" , urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.37.0/bazel-gazelle-v0.37.0.tar.gz" , "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.37.0/bazel-gazelle-v0.37.0.tar.gz" , ], ) load ( "@io_bazel_rules_go//go:deps.bzl" , "go_register_toolchains" , "go_rules_dependencies" ) load ( "@bazel_gazelle//:deps.bzl" , "gazelle_dependencies" ) go_rules_dependencies () go_register_toolchains ( version = "1.23.1" ) gazelle_dependencies ()
Ajoutez le code ci-dessous au fichier BUILD.bazel
dans le répertoire racine de votre projet. Remplacez la chaîne après prefix
par un préfixe de chemin d'importation qui correspond à votre projet. Il devrait être le même que le chemin de votre module, si vous avez un fichier go.mod
.
load ( "@bazel_gazelle//:def.bzl" , "gazelle" )
# gazelle:prefix github.com/example/project
gazelle ( name = "gazelle" )
Ceci déclare une règle binaire gazelle
, que vous pouvez exécuter à l'aide de la commande ci-dessous :
bazel run //:gazelle
Cela générera un fichier BUILD.bazel
avec les cibles go_library, go_binary et go_test pour chaque package de votre projet. Vous pourrez exécuter la même commande ultérieurement pour mettre à jour les fichiers de build existants avec de nouveaux fichiers source, dépendances et options.
Si votre projet ne suit pas les conventions go build
ou si vous préférez ne pas utiliser gazelle, vous pouvez écrire les fichiers de construction à la main.
Dans chaque répertoire contenant du code Go, créez un fichier nommé BUILD.bazel
Ajoutez une instruction load
en haut du fichier pour les règles que vous utilisez.
load ( "@io_bazel_rules_go//go:def.bzl" , "go_binary" , "go_library" , "go_test" )
Pour chaque bibliothèque, ajoutez une règle go_library comme celle ci-dessous. Les fichiers sources sont répertoriés dans l'attribut srcs
. Les packages importés en dehors de la bibliothèque standard sont répertoriés dans l'attribut deps
à l'aide d'étiquettes Bazel qui font référence aux règles go_library correspondantes. Le chemin d'importation de la bibliothèque doit être spécifié avec l'attribut importpath
.
go_library (
name = "foo_library" ,
srcs = [
"a.go" ,
"b.go" ,
],
importpath = "github.com/example/project/foo" ,
deps = [
"//tools" ,
"@org_golang_x_utils//stuff" ,
],
visibility = [ "//visibility:public" ],
)
Pour les tests, ajoutez une règle go_test comme celle ci-dessous. La bibliothèque testée doit être répertoriée dans un attribut embed
.
go_test (
name = "foo_test" ,
srcs = [
"a_test.go" ,
"b_test.go" ,
],
embed = [ ":foo_lib" ],
deps = [
"//testtools" ,
"@org_golang_x_utils//morestuff" ,
],
)
Pour les binaires, ajoutez une règle go_binary comme celle ci-dessous.
go_binary (
name = "foo" ,
srcs = [ "main.go" ],
)
Pour chaque référentiel Go, ajoutez une règle go_repository à WORKSPACE
comme celle ci-dessous. Cette règle provient du référentiel Gazelle, vous devrez donc la charger. gazelle update-repos peut générer ou mettre à jour ces règles automatiquement à partir d'un fichier go.mod ou Gopkg.lock.
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
# Download the Go rules.
http_archive (
name = "io_bazel_rules_go" ,
integrity = "sha256-M6zErg9wUC20uJPJ/B3Xqb+ZjCPn/yxFF3QdQEmpdvg=" ,
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" ,
"https://github.com/bazelbuild/rules_go/releases/download/v0.48.0/rules_go-v0.48.0.zip" ,
],
)
# Download Gazelle.
http_archive (
name = "bazel_gazelle" ,
integrity = "sha256-12v3pg/YsFBEQJDfooN6Tq+YKeEWVhjuNdzspcvfWNU=" ,
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.37.0/bazel-gazelle-v0.37.0.tar.gz" ,
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.37.0/bazel-gazelle-v0.37.0.tar.gz" ,
],
)
# Load macros and repository rules.
load ( "@io_bazel_rules_go//go:deps.bzl" , "go_register_toolchains" , "go_rules_dependencies" )
load ( "@bazel_gazelle//:deps.bzl" , "gazelle_dependencies" , "go_repository" )
# Declare Go direct dependencies.
go_repository (
name = "org_golang_x_net" ,
importpath = "golang.org/x/net" ,
sum = "h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=" ,
version = "v0.23.0" ,
)
# Declare indirect dependencies and register toolchains.
go_rules_dependencies ()
go_register_toolchains ( version = "1.23.1" )
gazelle_dependencies ()
Pour générer du code à partir des tampons de protocole, vous devrez ajouter une dépendance sur com_google_protobuf
à votre WORKSPACE
.
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
http_archive (
name = "com_google_protobuf" ,
sha256 = "535fbf566d372ccf3a097c374b26896fa044bf4232aef9cab37bd1cc1ba4e850" ,
strip_prefix = "protobuf-3.15.0" ,
urls = [
"https://mirror.bazel.build/github.com/protocolbuffers/protobuf/archive/v3.15.0.tar.gz" ,
"https://github.com/protocolbuffers/protobuf/archive/v3.15.0.tar.gz" ,
],
)
load ( "@com_google_protobuf//:protobuf_deps.bzl" , "protobuf_deps" )
protobuf_deps ()
Vous aurez besoin d'une chaîne d'outils C/C++ enregistrée pour la plate-forme d'exécution (la plate-forme sur laquelle Bazel exécute les actions) pour créer un protocole.
La règle proto_library est fournie par le référentiel rules_proto
. protoc-gen-go
, le plugin du compilateur Go proto, est fourni par le référentiel com_github_golang_protobuf
. Les deux sont déclarés par go_rules_dependencies. Vous n'aurez pas besoin de déclarer une dépendance explicite, sauf si vous souhaitez spécifiquement utiliser une version différente. Voir Remplacement des dépendances pour obtenir des instructions sur l'utilisation d'une version différente.
Les dépendances gRPC ne sont pas déclarées par défaut (il y en a trop). Vous pouvez les déclarer dans WORKSPACE en utilisant go_repository. Vous souhaiterez peut-être utiliser gazelle update-repos pour les importer depuis go.mod
.
Voir Dépendances Proto, Dépendances gRPC pour plus d'informations. Voir également Éviter les conflits.
Une fois toutes les dépendances enregistrées, vous pouvez déclarer les règles proto_library et go_proto_library pour générer et compiler du code Go à partir de fichiers .proto.
load ( "@rules_proto//proto:defs.bzl" , "proto_library" )
load ( "@io_bazel_rules_go//proto:def.bzl" , "go_proto_library" )
proto_library (
name = "foo_proto" ,
srcs = [ "foo.proto" ],
deps = [ "//bar:bar_proto" ],
visibility = [ "//visibility:public" ],
)
go_proto_library (
name = "foo_go_proto" ,
importpath = "github.com/example/protos/foo_proto" ,
protos = [ ":foo_proto" ],
visibility = [ "//visibility:public" ],
)
Une cible go_proto_library
peut être importée et dépendante comme une go_library
normale.
Notez que les versions récentes de Rules_go prennent en charge à la fois APIv1 ( github.com/golang/protobuf
) et APIv2 ( google.golang.org/protobuf
). Par défaut, le code est généré avec github.com/golang/protobuf/cmd/protoc-gen-gen
pour la compatibilité avec les deux interfaces. Le code client peut être importé à l'aide de la bibliothèque d'exécution ou des deux.
Aller
Tampons de protocole
Dépendances et tests
Oui, mais pas directement.
Rules_go appelle directement le compilateur et l'éditeur de liens Go, en fonction des cibles décrites avec go_binary et d'autres règles. Bazel et Rules_go remplissent ensemble le même rôle que la commande go
, il n'est donc pas nécessaire d'utiliser la commande go
dans un espace de travail Bazel.
Cela dit, c'est généralement une bonne idée de suivre les conventions requises par la commande go
(par exemple, un package par répertoire, les chemins des packages correspondent aux chemins des répertoires). Les outils qui ne sont pas compatibles avec Bazel fonctionneront toujours et votre projet pourra dépendre de projets non Bazel.
Si vous devez utiliser la commande go
pour effectuer des tâches que Bazel ne couvre pas (telles que l'ajout d'une nouvelle dépendance à go.mod
), vous pouvez utiliser l'invocation Bazel suivante pour exécuter le binaire go
du SDK Go configuré par Bazel :
bazel run @io_bazel_rules_go//go -- < args >
Préférez cela à l'exécution directe go
car cela garantit que la version de Go est identique à celle utilisée par Rules_go.
Oui, mais pas directement. Bazel ignore les fichiers go.mod
et toutes les dépendances des packages doivent être exprimées via les attributs deps
dans les cibles décrites avec go_library et d'autres règles.
Vous pouvez télécharger un module Go dans une version spécifique en tant que référentiel externe en utilisant go_repository, une règle d'espace de travail fournie par gazelle. Cela générera également des fichiers de construction en utilisant gazelle.
Vous pouvez importer des règles go_repository à partir d'un fichier go.mod
en utilisant gazelle update-repos.
Ceci a été utilisé pour maintenir la cohérence des chemins d'importation dans les bibliothèques qui peuvent être créées avec go build
avant que l'attribut importpath
ne soit disponible.
Afin de compiler et de créer des liens correctement, Rules_go doit connaître le chemin d'importation Go (la chaîne par laquelle un package peut être importé) pour chaque bibliothèque. Ceci est désormais défini explicitement avec l'attribut importpath
. Avant que cet attribut n'existe, le chemin d'importation était déduit en concaténant une chaîne à partir d'une règle spéciale go_prefix
et le nom du package et de l'étiquette de la bibliothèque. Par exemple, si go_prefix
était github.com/example/project
, pour une bibliothèque //foo/bar:bar
, Rules_go déduirait le chemin d'importation comme github.com/example/project/foo/bar/bar
. Le bégaiement à la fin est incompatible avec go build
, donc si le nom de l'étiquette était go_default_library
, le chemin d'importation ne l'inclurait pas. Donc pour la bibliothèque //foo/bar:go_default_library
, le chemin d'importation serait github.com/example/project/foo/bar
.
Depuis que go_prefix
a été supprimé et que l'attribut importpath
est devenu obligatoire (voir #721), le nom go_default_library
ne sert plus à rien. Nous pourrions décider de cesser de l'utiliser à l'avenir (voir #265).
Vous pouvez effectuer une compilation croisée en définissant l'indicateur --platforms
sur la ligne de commande. Par exemple:
$ bazel build --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 //cmd
Par défaut, cgo est désactivé lors de la compilation croisée. Pour effectuer une compilation croisée avec cgo, ajoutez un suffixe _cgo
à la plateforme cible. Vous devez enregistrer une chaîne d'outils C/C++ de compilation croisée avec Bazel pour que cela fonctionne.
$ bazel build --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64_cgo //cmd
Les sources spécifiques à la plate-forme avec des balises de construction ou des suffixes de nom de fichier sont automatiquement filtrées au moment de la compilation. Vous pouvez inclure de manière sélective des dépendances spécifiques à la plate-forme avec des expressions select
(Gazelle le fait automatiquement).
go_library (
name = "foo" ,
srcs = [
"foo_linux.go" ,
"foo_windows.go" ,
],
deps = select ({
"@io_bazel_rules_go//go/platform:linux_amd64" : [
"//bar_linux" ,
],
"@io_bazel_rules_go//go/platform:windows_amd64" : [
"//bar_windows" ,
],
"//conditions:default" : [],
}),
)
Pour créer une cible go_binary spécifique pour une plate-forme cible ou en utilisant une version spécifique du SDK golang, utilisez la règle go_cross_binary. Ceci est utile pour produire plusieurs binaires pour différentes plates-formes en une seule version.
Pour créer une cible go_test spécifique pour une plate-forme cible, définissez les attributs goos
et goarch
sur cette règle.
Vous pouvez de manière équivalente dépendre d'une règle go_binary ou go_test via une transition de configuration Bazel sur //command_line_option:platforms
(il y avait des problèmes avec cette approche avant Rules_go 0.23.0).
Bazel exécute les tests dans un bac à sable, ce qui signifie que les tests n'ont pas automatiquement accès aux fichiers. Vous devez inclure les fichiers de test à l'aide de l'attribut data
. Par exemple, si vous souhaitez tout inclure dans le répertoire testdata
:
go_test (
name = "foo_test" ,
srcs = [ "foo_test.go" ],
data = glob ([ "testdata/**" ]),
importpath = "github.com/example/project/foo" ,
)
Par défaut, les tests sont exécutés dans le répertoire du fichier de build qui les a définis. Notez que cela suit la convention de test Go, et non la convention Bazel suivie par d'autres langages, qui s'exécutent à la racine du référentiel. Cela signifie que vous pouvez accéder aux fichiers de test en utilisant des chemins relatifs. Vous pouvez modifier le répertoire de test à l'aide de l'attribut rundir
. Voir go_test.
Gazelle ajoutera automatiquement un attribut data
comme celui ci-dessus si vous disposez d'un répertoire testdata
à moins qu'il ne contienne des fichiers .go ou des fichiers de construction constructibles, auquel cas, testdata
est traité comme un package normal.
Notez que sous Windows, les fichiers de données ne sont pas directement disponibles pour les tests, car les fichiers de données de test reposent sur des liens symboliques et, par défaut, Windows ne permet pas aux utilisateurs non privilégiés de créer des liens symboliques. Vous pouvez utiliser la bibliothèque github.com/bazelbuild/rules_go/go/tools/bazel pour accéder aux fichiers de données.
L'emplacement où go_binary
écrit son fichier exécutable n'est pas stable entre les versions de Rules_go et ne doit pas être utilisé. Le répertoire parent inclut certaines données de configuration dans son nom. Cela empêche le cache de Bazel d'être empoisonné lorsque le même binaire est construit dans différentes configurations. Le nom de base binaire peut également dépendre de la plateforme : sous Windows, nous ajoutons une extension .exe.
Pour dépendre d'un exécutable dans une règle go_test
, référencez l'exécutable dans l'attribut data
(pour le rendre visible), puis développez l'emplacement dans args
. La localisation réelle sera transmise au test sur la ligne de commande. Par exemple:
go_binary (
name = "cmd" ,
srcs = [ "cmd.go" ],
)
go_test (
name = "cmd_test" ,
srcs = [ "cmd_test.go" ],
args = [ "$(location :cmd)" ],
data = [ ":cmd" ],
)
Voir //tests/core/cross pour un exemple complet de test qui accède à un binaire.
Alternativement, vous pouvez définir l'attribut out
de go_binary sur un nom de fichier spécifique. Notez que lorsque out
est défini, le binaire ne sera pas mis en cache lors de la modification des configurations.
go_binary (
name = "cmd" ,
srcs = [ "cmd.go" ],
out = "cmd" ,
)
go_test (
name = "cmd_test" ,
srcs = [ "cmd_test.go" ],
data = [ ":cmd" ],
)
Voir Éviter les conflits dans la documentation du proto.
Ceci n'est pas pris en charge. Lors de l'utilisation de go_proto_library avec le compilateur @io_bazel_rules_go//proto:go_grpc
, une dépendance implicite est ajoutée sur @org_golang_google_grpc//:go_default_library
. Si vous liez une autre copie du même package depuis //vendor/google.golang.org/grpc:go_default_library
ou ailleurs, vous risquez de rencontrer des conflits lors de la compilation ou de l'exécution.
Si vous utilisez Gazelle avec la génération de règles proto activées, les importations de google.golang.org/grpc
seront automatiquement résolues en @org_golang_google_grpc//:go_default_library
pour éviter les conflits. Le gRPC vendu doit être ignoré dans ce cas.
Si vous avez spécifiquement besoin d'utiliser un package gRPC fourni, il est préférable d'éviter complètement d'utiliser go_proto_library
. Vous pouvez archiver des fichiers .pb.go pré-générés et les créer avec les règles go_library
. Gazelle générera ces règles lorsque la génération de règles proto est désactivée (ajoutez # gazelle:proto disable_global
à votre fichier de construction racine).
Voir Remplacement des dépendances pour obtenir des instructions sur le remplacement des référentiels déclarés dans go_rules_dependencies.
Références :
Afin d'exécuter les tests Bazel sur Travis CI, vous devrez installer Bazel dans le script before_install
. Voir notre fichier de configuration lié ci-dessus.
Vous souhaiterez exécuter Bazel avec un certain nombre d'indicateurs pour l'empêcher de consommer une énorme quantité de mémoire dans l'environnement de test.
--host_jvm_args=-Xmx500m --host_jvm_args=-Xms500m
: Définit la taille maximale et initiale du tas JVM. Garder la même chose signifie que la JVM ne passera pas de temps à développer le tas. Le choix de la taille du tas est quelque peu arbitraire ; d'autres fichiers de configuration recommandent des limites allant jusqu'à 2 500 m. Des valeurs plus élevées signifient une construction plus rapide, mais un risque plus élevé de destruction du MOO.--bazelrc=.test-bazelrc
: Utilisez un fichier de configuration Bazel spécifique à Travis CI. Vous pouvez mettre la plupart des options restantes ici.build --spawn_strategy=standalone --genrule_strategy=standalone
: Désactivez le sandboxing pour la build. Le sandboxing peut échouer à l'intérieur des conteneurs de Travis car l'appel système mount
n'est pas autorisé.test --test_strategy=standalone
: Désactivez également le sandboxing pour les tests.--local_resources=1536,1.5,0.5
: définissez les limites de Bazel sur la RAM disponible en Mo, les cœurs disponibles pour le calcul et les cœurs disponibles pour les E/S. Des valeurs plus élevées signifient une construction plus rapide, mais un conflit et un risque plus élevés de destruction du MOO.--noshow_progress
: supprime les messages de progression dans la sortie pour des journaux plus propres.--verbose_failures
: Obtenez des messages d'échec plus détaillés.--test_output=errors
: Afficher le test stderr dans le journal Travis. Normalement, les résultats des tests sont des fichiers journaux écrits que Travis ne sauvegarde ni ne rapporte. Les téléchargements sur Travis sont relativement lents (le réseau est fortement sollicité), vous souhaiterez donc minimiser la quantité d'E/S réseau dans votre build. Le téléchargement de Bazel et d’un SDK Go en constitue une grande partie. Pour éviter de télécharger un SDK Go, vous pouvez demander un conteneur avec une version préinstallée de Go dans votre fichier .travis.yml
, puis appeler go_register_toolchains(go_version = "host")
dans un fichier WORKSPACE
spécifique à Travis.
Vous pourriez être tenté de mettre le cache de Bazel dans votre cache Travis. Bien que cela puisse accélérer considérablement votre build, Travis stocke son cache sur Amazon et le transfert prend très longtemps. Les builds propres semblent plus rapides dans la pratique.
Rules_go ne prend en charge que les versions officielles du SDK Go. Cependant, vous pouvez toujours tester les versions bêta et RC en transmettant une version
telle que "1.16beta1"
à go_register_toolchains. Voir aussi go_download_sdk.
load ( "@io_bazel_rules_go//go:deps.bzl" , "go_register_toolchains" , "go_rules_dependencies" )
go_rules_dependencies ()
go_register_toolchains ( version = "1.17beta1" )