Lista de correo: bazel-go-discute
Slack: #go en Bazel Slack, #bazel en Go Slack
Las reglas se encuentran en la etapa beta de desarrollo. Ellos apoyan:
Actualmente no admiten o tienen soporte limitado para:
Las reglas de Go se prueban y admiten en las siguientes plataformas de host:
Los usuarios han informado de éxito en varias otras plataformas, pero las reglas sólo se prueban en las mencionadas anteriormente.
Nota: Desde la versión v0.38.0, reglas_go requiere Bazel ≥ 5.4.0 para funcionar.
Se garantiza que la rama master
solo funcionará con la última versión de Bazel.
Para crear código Go con Bazel, necesitará:
patch
, cat
y un puñado de otras herramientas Unix en PATH
.Normalmente no necesitarás tener instalada una cadena de herramientas Go. Bazel descargará uno.
Consulte Uso de reglas_go en Windows para obtener instrucciones de configuración específicas de Windows. Es necesario instalar y configurar varias herramientas adicionales.
Si está utilizando el nuevo sistema de gestión de dependencias externas de Bazel, Bzlmod, consulte la guía dedicada Go with Bzlmod.
Cree un archivo en la parte superior de su repositorio llamado WORKSPACE
y agregue el fragmento a continuación (o agréguelo a su WORKSPACE
existente). Esto le dice a Bazel que busque reglas_go y sus dependencias. Bazel descargará una cadena de herramientas Go compatible reciente y la registrará para su uso.
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" )
Puedes usar reglas_go en master
usando git_repository en lugar de http_archive y apuntando a una confirmación reciente.
Agregue un archivo llamado BUILD.bazel
en el directorio raíz de su proyecto. Necesitará un archivo de compilación en cada directorio con código Go, pero también necesitará uno en el directorio raíz, incluso si su proyecto no tiene código Go allí. Para un binario "Hola, mundo", el archivo debería verse así:
load ( "@io_bazel_rules_go//go:def.bzl" , "go_binary" )
go_binary (
name = "hello" ,
srcs = [ "hello.go" ],
)
Puedes construir este objetivo con bazel build //:hello
.
Si su proyecto se puede construir con go build
, puede generar y actualizar sus archivos de compilación automáticamente usando gazelle.
Agregue el repositorio bazel_gazelle
y sus dependencias a su WORKSPACE
. Debería verse así:
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 ()
Agregue el siguiente código al archivo BUILD.bazel
en el directorio raíz de su proyecto. Reemplace la cadena después prefix
con un prefijo de ruta de importación que coincida con su proyecto. Debería ser la misma que la ruta de su módulo, si tiene un archivo go.mod
.
load ( "@bazel_gazelle//:def.bzl" , "gazelle" )
# gazelle:prefix github.com/example/project
gazelle ( name = "gazelle" )
Esto declara una regla binaria gazelle
, que puedes ejecutar usando el siguiente comando:
bazel run //:gazelle
Esto generará un archivo BUILD.bazel
con objetivos go_library, go_binary y go_test para cada paquete de su proyecto. Puede ejecutar el mismo comando en el futuro para actualizar los archivos de compilación existentes con nuevos archivos fuente, dependencias y opciones.
Si su proyecto no sigue las convenciones go build
o prefiere no utilizar gazelle, puede escribir archivos de compilación a mano.
En cada directorio que contenga código Go, cree un archivo llamado BUILD.bazel
Agregue una declaración load
en la parte superior del archivo para las reglas que utiliza.
load ( "@io_bazel_rules_go//go:def.bzl" , "go_binary" , "go_library" , "go_test" )
Para cada biblioteca, agregue una regla go_library como la siguiente. Los archivos fuente se enumeran en el atributo srcs
. Los paquetes importados fuera de la biblioteca estándar se enumeran en el atributo deps
utilizando etiquetas de Bazel que hacen referencia a las reglas go_library correspondientes. La ruta de importación de la biblioteca debe especificarse con el atributo 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" ],
)
Para las pruebas, agregue una regla go_test como la siguiente. La biblioteca que se está probando debe aparecer en un atributo embed
.
go_test (
name = "foo_test" ,
srcs = [
"a_test.go" ,
"b_test.go" ,
],
embed = [ ":foo_lib" ],
deps = [
"//testtools" ,
"@org_golang_x_utils//morestuff" ,
],
)
Para archivos binarios, agregue una regla go_binary como la siguiente.
go_binary (
name = "foo" ,
srcs = [ "main.go" ],
)
Para cada repositorio de Go, agregue una regla go_repository a WORKSPACE
como la que se muestra a continuación. Esta regla proviene del repositorio de Gazelle, por lo que deberás cargarla. gazelle update-repos puede generar o actualizar estas reglas automáticamente desde un archivo go.mod o 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 ()
Para generar código a partir de buffers de protocolo, deberá agregar una dependencia en com_google_protobuf
a su 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 ()
Necesitará una cadena de herramientas C/C++ registrada para la plataforma de ejecución (la plataforma donde Bazel ejecuta acciones) para crear el protocolo.
La regla proto_library la proporciona el repositorio rules_proto
. protoc-gen-go
, el complemento del compilador de proto Go, lo proporciona el repositorio com_github_golang_protobuf
. Ambos están declarados por go_rules_dependencies. No necesitarás declarar una dependencia explícita a menos que quieras usar específicamente una versión diferente. Consulte Anulación de dependencias para obtener instrucciones sobre cómo utilizar una versión diferente.
Las dependencias de gRPC no se declaran de forma predeterminada (hay demasiadas). Puedes declararlos en WORKSPACE usando go_repository. Es posible que desee utilizar gazelle update-repos para importarlos desde go.mod
.
Consulte Dependencias de Proto y dependencias de gRPC para obtener más información. Consulte también Evitar conflictos.
Una vez que se hayan registrado todas las dependencias, puede declarar las reglas proto_library y go_proto_library para generar y compilar código Go a partir de archivos .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" ],
)
Se puede importar un objetivo go_proto_library
y depender de él como un go_library
normal.
Tenga en cuenta que las versiones recientes de reglas_go admiten tanto APIv1 ( github.com/golang/protobuf
) como APIv2 ( google.golang.org/protobuf
). De forma predeterminada, el código se genera con github.com/golang/protobuf/cmd/protoc-gen-gen
para compatibilidad con ambas interfaces. El código del cliente puede importarse utilizando cualquiera de las bibliotecas de tiempo de ejecución o ambas.
Ir
Búfers de protocolo
Dependencias y pruebas
Sí, pero no directamente.
reglas_go invoca al compilador y enlazador de Go directamente, según los objetivos descritos con go_binary y otras reglas. Bazel y reglas_go juntos cumplen la misma función que el comando go
, por lo que no es necesario utilizar el comando go
en un espacio de trabajo de Bazel.
Dicho esto, generalmente sigue siendo una buena idea seguir las convenciones requeridas por el comando go
(por ejemplo, un paquete por directorio, las rutas de los paquetes coinciden con las rutas de los directorios). Las herramientas que no son compatibles con Bazel seguirán funcionando y los proyectos que no sean de Bazel pueden depender de su proyecto.
Si necesita usar el comando go
para realizar tareas que Bazel no cubre (como agregar una nueva dependencia a go.mod
), puede usar la siguiente invocación de Bazel para ejecutar el binario go
del SDK Go configurado por Bazel:
bazel run @io_bazel_rules_go//go -- < args >
Prefiera esto a ejecutar go
directamente ya que garantiza que la versión de Go sea idéntica a la utilizada por reglas_go.
Sí, pero no directamente. Bazel ignora los archivos go.mod
y todas las dependencias de los paquetes deben expresarse mediante atributos deps
en los objetivos descritos con go_library y otras reglas.
Puede descargar un módulo Go en una versión específica como repositorio externo usando go_repository, una regla de espacio de trabajo proporcionada por gazelle. Esto también generará archivos de compilación usando gazelle.
Puede importar reglas de go_repository desde un archivo go.mod
usando gazelle update-repos.
Esto se usó para mantener las rutas de importación consistentes en las bibliotecas que se pueden crear con go build
antes de que el atributo importpath
estuviera disponible.
Para compilar y vincular correctamente, reglas_go debe conocer la ruta de importación de Go (la cadena mediante la cual se puede importar un paquete) para cada biblioteca. Esto ahora se establece explícitamente con el atributo importpath
. Antes de que existiera ese atributo, la ruta de importación se infería concatenando una cadena de una regla go_prefix
especial y el nombre del paquete y la etiqueta de la biblioteca. Por ejemplo, si go_prefix
fuera github.com/example/project
, para una biblioteca //foo/bar:bar
, reglas_go inferiría la ruta de importación como github.com/example/project/foo/bar/bar
. El tartamudeo al final es incompatible con go build
, por lo que si el nombre de la etiqueta fuera go_default_library
, la ruta de importación no lo incluiría. Entonces, para la biblioteca //foo/bar:go_default_library
, la ruta de importación sería github.com/example/project/foo/bar
.
Desde que se eliminó go_prefix
y el atributo importpath
se volvió obligatorio (ver n.° 721), el nombre go_default_library
ya no sirve para ningún propósito. Es posible que decidamos dejar de usarlo en el futuro (ver n.° 265).
Puede realizar una compilación cruzada configurando el indicador --platforms
en la línea de comando. Por ejemplo:
$ compilación de bazel --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64 //cmd
De forma predeterminada, cgo está deshabilitado durante la compilación cruzada. Para realizar una compilación cruzada con cgo, agregue un sufijo _cgo
a la plataforma de destino. Debe registrar una cadena de herramientas C/C++ de compilación cruzada con Bazel para que esto funcione.
$ compilación de bazel --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64_cgo //cmd
Las fuentes específicas de la plataforma con etiquetas de compilación o sufijos de nombres de archivos se filtran automáticamente en el momento de la compilación. Puede incluir selectivamente dependencias específicas de la plataforma con expresiones select
(Gazelle lo hace automáticamente).
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" : [],
}),
)
Para crear un objetivo go_binary específico para una plataforma de destino o utilizar una versión específica del SDK de golang, utilice la regla go_cross_binary. Esto es útil para producir múltiples archivos binarios para diferentes plataformas en una sola compilación.
Para crear un objetivo go_test específico para una plataforma de destino, establezca los atributos goos
y goarch
en esa regla.
De manera equivalente, puede depender de una regla go_binary o go_test a través de una transición de configuración de Bazel en //command_line_option:platforms
(existían problemas con este enfoque antes de reglas_go 0.23.0).
Bazel ejecuta pruebas en un entorno limitado, lo que significa que las pruebas no tienen acceso automático a los archivos. Debe incluir archivos de prueba utilizando el atributo data
. Por ejemplo, si desea incluir todo en el directorio testdata
:
go_test (
name = "foo_test" ,
srcs = [ "foo_test.go" ],
data = glob ([ "testdata/**" ]),
importpath = "github.com/example/project/foo" ,
)
De forma predeterminada, las pruebas se ejecutan en el directorio del archivo de compilación que las definió. Tenga en cuenta que esto sigue la convención de prueba de Go, no la convención de Bazel seguida por otros lenguajes, que se ejecutan en la raíz del repositorio. Esto significa que puede acceder a los archivos de prueba utilizando rutas relativas. Puede cambiar el directorio de prueba utilizando el atributo rundir
. Ver go_test.
Gazelle agregará automáticamente un atributo data
como el anterior si tiene un directorio testdata
, a menos que contenga archivos .go o archivos de compilación compilables, en cuyo caso, testdata
se trata como un paquete normal.
Tenga en cuenta que en Windows, los archivos de datos no están directamente disponibles para las pruebas, ya que los archivos de datos de prueba dependen de enlaces simbólicos y, de forma predeterminada, Windows no permite que los usuarios sin privilegios creen enlaces simbólicos. Puede utilizar la biblioteca github.com/bazelbuild/rules_go/go/tools/bazel para acceder a archivos de datos.
La ubicación donde go_binary
escribe su archivo ejecutable no es estable en todas las versiones de reglas_go y no se debe depender de ella. El directorio principal incluye algunos datos de configuración en su nombre. Esto evita que la caché de Bazel sea envenenada cuando el mismo binario se construye en diferentes configuraciones. El nombre base binario también puede depender de la plataforma: en Windows, agregamos una extensión .exe.
Para depender de un ejecutable en una regla go_test
, haga referencia al ejecutable en el atributo data
(para hacerlo visible) y luego expanda la ubicación en args
. La ubicación real se pasará a la prueba en la línea de comando. Por ejemplo:
go_binary (
name = "cmd" ,
srcs = [ "cmd.go" ],
)
go_test (
name = "cmd_test" ,
srcs = [ "cmd_test.go" ],
args = [ "$(location :cmd)" ],
data = [ ":cmd" ],
)
Consulte //tests/core/cross para ver un ejemplo completo de una prueba que accede a un binario.
Alternativamente, puede establecer el atributo out
de go_binary en un nombre de archivo específico. Tenga en cuenta que cuando se establece out
, el binario no se almacenará en caché al cambiar las configuraciones.
go_binary (
name = "cmd" ,
srcs = [ "cmd.go" ],
out = "cmd" ,
)
go_test (
name = "cmd_test" ,
srcs = [ "cmd_test.go" ],
data = [ ":cmd" ],
)
Consulte Evitar conflictos en la documentación del proto.
Esto no es compatible. Cuando se usa go_proto_library con el compilador @io_bazel_rules_go//proto:go_grpc
, se agrega una dependencia implícita en @org_golang_google_grpc//:go_default_library
. Si vincula otra copia del mismo paquete desde //vendor/google.golang.org/grpc:go_default_library
o en cualquier otro lugar, puede experimentar conflictos durante la compilación o el tiempo de ejecución.
Si está utilizando Gazelle con la generación de reglas proto habilitada, las importaciones de google.golang.org/grpc
se resolverán automáticamente en @org_golang_google_grpc//:go_default_library
para evitar conflictos. En este caso, se debe ignorar el gRPC suministrado.
Si necesita utilizar específicamente un paquete gRPC proporcionado, es mejor evitar el uso de go_proto_library
por completo. Puede registrar archivos .pb.go pregenerados y compilarlos con reglas go_library
. Gazelle generará estas reglas cuando la generación de reglas proto esté deshabilitada (agregue # gazelle:proto disable_global
a su archivo de compilación raíz).
Consulte Anulación de dependencias para obtener instrucciones sobre cómo anular repositorios declarados en go_rules_dependencies.
Referencias:
Para ejecutar pruebas de Bazel en Travis CI, deberá instalar Bazel en el script before_install
. Vea nuestro archivo de configuración vinculado arriba.
Querrá ejecutar Bazel con varias opciones para evitar que consuma una gran cantidad de memoria en el entorno de prueba.
--host_jvm_args=-Xmx500m --host_jvm_args=-Xms500m
: establece el tamaño máximo e inicial del montón de JVM. Mantener lo mismo significa que la JVM no perderá tiempo haciendo crecer el montón. La elección del tamaño del montón es algo arbitraria; Otros archivos de configuración recomiendan límites de hasta 2500 m. Los valores más altos significan una construcción más rápida, pero un mayor riesgo de muerte de OOM.--bazelrc=.test-bazelrc
: utilice un archivo de configuración de Bazel específico para Travis CI. Puede colocar la mayoría de las opciones restantes aquí.build --spawn_strategy=standalone --genrule_strategy=standalone
: deshabilita el espacio aislado para la compilación. El sandboxing puede fallar dentro de los contenedores de Travis porque la llamada al sistema mount
no está permitida.test --test_strategy=standalone
: deshabilite también el sandboxing para las pruebas.--local_resources=1536,1.5,0.5
: establece los límites de Bazel en RAM disponible en MB, núcleos disponibles para computación y núcleos disponibles para E/S. Los valores más altos significan una construcción más rápida, pero una mayor contención y riesgo de muerte de OOM.--noshow_progress
: suprime los mensajes de progreso en la salida para obtener registros más limpios.--verbose_failures
: obtiene mensajes de error más detallados.--test_output=errors
: muestra stderr de prueba en el registro de Travis. Normalmente, el resultado de la prueba son archivos de registro escritos que Travis no guarda ni informa. Las descargas en Travis son relativamente lentas (la red está muy competida), por lo que querrás minimizar la cantidad de E/S de red en tu compilación. Descargar Bazel y Go SDK es una gran parte de eso. Para evitar descargar un SDK de Go, puede solicitar un contenedor con una versión preinstalada de Go en su archivo .travis.yml
y luego llamar go_register_toolchains(go_version = "host")
en un archivo WORKSPACE
específico de Travis.
Es posible que tengas la tentación de poner el caché de Bazel en tu caché de Travis. Aunque esto puede acelerar significativamente la compilación, Travis almacena su caché en Amazon y la transferencia lleva mucho tiempo. Las construcciones limpias parecen más rápidas en la práctica.
reglas_go solo admite versiones oficiales del Go SDK. Sin embargo, aún puedes probar las versiones beta y RC pasando una version
como "1.16beta1"
a go_register_toolchains. Véase también 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" )