Para simplificar el proceso, a menudo complejo, de migrar de WORKSPACE
a Bzlmod, se recomienda usar la secuencia de comandos de migración. Esta herramienta de ayuda automatiza muchos de los pasos involucrados en la migración de tu sistema externo de administración de dependencias.
Nota: Si quieres probar la migración a Bzlmod impulsada por IA, consulta Configuración del agente de migración a Bzlmod.
Funcionalidad principal
Las funciones principales de la secuencia de comandos son las siguientes:
- Recopilación de información de dependencias: Se analiza el archivo
WORKSPACE
de tu proyecto para identificar los repositorios externos que usan los destinos de compilación especificados, con la marca experimental_repository_resolved_file de Bazel para generar un archivo de dependencias resueltas que contenga esta información. - Identificación de dependencias directas: Uso de
bazel query
para determinar qué repositorios son dependencias directas para los destinos especificados. - Migración a Bzlmod: Traducción de las dependencias de
WORKSPACE
pertinentes a sus equivalentes de Bzlmod Este es un proceso de dos pasos:- Introduce todas las dependencias directas identificadas en el archivo
MODULE.bazel
. - Compila los destinos especificados con Bzlmod habilitado y, luego, identifica y corrige de forma iterativa los errores reconocibles. Este paso es necesario, ya que es posible que falten algunas dependencias en el primer paso.
- Introduce todas las dependencias directas identificadas en el archivo
- Generación de un informe de migración: Creación de un archivo
migration_info.md
que documenta el proceso de migración. Este informe incluye una lista de las dependencias directas, las declaraciones de Bzlmod generadas y los pasos manuales que pueden ser necesarios para completar la migración.
La herramienta de migración admite lo siguiente:
- Dependencias disponibles en el registro central de Bazel
- Reglas de repositorio personalizadas definidas por el usuario
- Dependencias del administrador de paquetes
- Maven
- Go
- Python
Notas importantes:
- La herramienta de migración es una utilidad que se ofrece de la mejor manera posible. Siempre verifica que sus recomendaciones sean correctas.
- Usa la herramienta de migración con Bazel 7 (no es compatible con Bazel 8).
Cómo usar la herramienta de migración
Antes de comenzar:
- Actualiza a la versión más reciente de Bazel 7, que proporciona compatibilidad sólida con WORKSPACE y Bzlmod.
Verifica que el siguiente comando se ejecute correctamente para los principales destinos de compilación de tu proyecto:
bazel build --nobuild --enable_workspace --noenable_bzlmod <targets>
Comando para ejecutar el script
Una vez que se cumplan los requisitos previos, ejecuta los siguientes comandos para usar la herramienta de migración:
# Clone the Bazel Central Registry repository git clone https://github.com/bazelbuild/bazel-central-registry.git cd bazel-central-registry # Build the migration tool bazel build //tools:migrate_to_bzlmod # Create a convenient alias for the tool alias migrate2bzlmod=$(realpath ./bazel-bin/tools/migrate_to_bzlmod) # Navigate to your project's root directory and run the tool cdmigrate2bzlmod -t
Archivos generados por este script
MODULE.bazel
: Es el archivo de manifiesto central de Bzlmod, que declara los metadatos del proyecto y sus dependencias directas de otros módulos de Bazel.migration_info.md
: Es un archivo que proporciona instrucciones paso a paso sobre cómo se ejecutó la herramienta de migración y que está diseñado para ayudar a completar manualmente el proceso de migración, si es necesario.resolved_deps.py
: Contiene una lista completa de las dependencias externas del proyecto, que se genera analizando el archivoWORKSPACE
del proyecto y sirve como referencia durante la transición.query_direct_deps
: Contiene información relevante para la migración sobre los destinos utilizados, que se obtiene invocando Bazel con--output=build
en el archivoWORKSPACE
del proyecto. El script de migración es el que consume principalmente este archivo.extension_for_XXX
: Es un archivo que contiene una definición de extensión del módulo. La herramienta de migración genera estos archivos para las dependencias que no son módulos estándar de Bazel, pero que se pueden administrar con las extensiones de módulos de Bzlmod.
Marcas
Las marcas disponibles en estas secuencias de comandos de migración son las siguientes:
--t
/--target
: Son los destinos a los que se migrarán los datos. Esta marca se puede repetir y los destinos se acumulan.--i
/--initial
: Borra los archivosMODULE.bazel
,resolved_deps.py
ymigration_info.md
, y comienza desde cero. Detecta las dependencias directas, las introduce en MODULE.bazel y vuelve a ejecutar la generación de las dependencias resueltas.
Limpieza posterior a la migración
- Se borraron
migration_info.md
,resolved_deps.py
yquery_direct_deps
. - Limpia los comentarios del archivo
MODULE.bazel
que se usaron para la migración, como# -- bazel_dep definitions -- #
.
Ejemplo de migración
Para ver el script de migración en acción, considera la siguiente situación en la que se declaran las dependencias de Python, Maven y Go en el archivo WORKSPACE
.
Haz clic aquí para ver el archivo WORKSPACE
workspace(name="example")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load(":my_custom_macro.bzl", "my_custom_macro")
http_archive(
name = "rules_cc",
sha256 = "b8b918a85f9144c01f6cfe0f45e4f2838c7413961a8ff23bc0c6cdf8bb07a3b6",
strip_prefix = "rules_cc-0.1.5",
urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.1.5/rules_cc-0.1.5.tar.gz"],
)
# Module dependency
# -------------------
http_archive(
name = "rules_shell",
sha256 = "3e114424a5c7e4fd43e0133cc6ecdfe54e45ae8affa14fadd839f29901424043",
strip_prefix = "rules_shell-0.4.0",
url = "https://github.com/bazelbuild/rules_shell/releases/download/v0.4.0/rules_shell-v0.4.0.tar.gz",
)
# Repo rule
# -------------------
http_archive(
name = "com_github_cockroachdb_cockroach",
sha256 = "6c3568ef244ce6b874694eeeecb83ed4f5d5dff6cf037c952ecde76828a6c502",
strip_prefix = "cockroach-22.1.6",
url = "https://github.com/cockroachdb/cockroach/archive/v22.1.6.tar.gz",
)
# Module extension
# -------------------
# Macro which invokes repository_rule
my_custom_macro(
name = "my_custom_repo",
)
# Go dependencies
# -------------------
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_repository")
go_rules_dependencies()
go_register_toolchains(version = "1.23.1")
gazelle_dependencies()
go_repository(
name = "org_golang_x_net",
importpath = "golang.org/x/net",
sum = "h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=",
version = "v0.0.0-20190311183353-d8887717615a",
build_file_proto_mode = "disable",
build_naming_convention = "import",
)
# Python dependencies
# -------------------
http_archive(
name = "rules_python",
integrity = "sha256-qDdnnxOC8mlowe5vg5x9r5B5qlMSgGmh8oFd7KpjcwQ=",
strip_prefix = "rules_python-1.4.0",
url = "https://github.com/bazelbuild/rules_python/releases/download/1.4.0/rules_python-1.4.0.tar.gz",
)
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()
load("@rules_python//python:pip.bzl", "pip_parse")
pip_parse(
name = "my_python_deps",
requirements_lock = "@example//:requirements_lock.txt",
)
load("@my_python_deps//:requirements.bzl", "install_deps")
install_deps()
load("@rules_python//python:repositories.bzl", "python_register_toolchains")
python_register_toolchains(
name = "python_3_11",
python_version = "3.11",
)
# Maven dependencies
# __________________
RULES_JVM_EXTERNAL_TAG = "4.5"
RULES_JVM_EXTERNAL_SHA = "b17d7388feb9bfa7f2fa09031b32707df529f26c91ab9e5d909eb1676badd9a6"
http_archive(
name = "rules_jvm_external",
strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
sha256 = RULES_JVM_EXTERNAL_SHA,
url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)
load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps")
rules_jvm_external_deps()
load("@rules_jvm_external//:setup.bzl", "rules_jvm_external_setup")
rules_jvm_external_setup()
load("@rules_jvm_external//:defs.bzl", "maven_install")
maven_install(
name = "px_deps",
artifacts = [
"org.antlr:antlr4:4.11.1",
],
repositories = [
"https://repo1.maven.org/maven2",
],
)
Además, para demostrar el uso de la extensión del módulo, se invoca la macro personalizada desde WORKSPACE
y se define en my_custom_macro.bzl
.
Haz clic aquí para ver el archivo my_custom_macro.bzl
"""Repo rule and macro used for testing"""
def _test_repo_rule_impl(repository_ctx):
repository_ctx.file(
"BUILD",
content = """
genrule(
name = "foo",
outs = ["rule_name.out"],
cmd = "touch $@",
visibility = ["//visibility:public"],
)
"""
)
_test_repo_rule = repository_rule(
implementation = _test_repo_rule_impl,
)
def my_custom_macro(name):
_test_repo_rule(name = name)
El objetivo final es tener el archivo MODULE.bazel
y borrar el archivo WORKSPACE
, sin afectar la experiencia del usuario.
El primer paso es seguir las instrucciones de Cómo usar la herramienta de migración, que consiste principalmente en verificar la versión de Bazel (debe ser Bazel 7) y agregar un alias a la secuencia de comandos de migración.
Luego, al ejecutar migrate2bzlmod -t=//...
, se obtienen los siguientes resultados:
bazel 7.6.1 Generating ./resolved_deps.py file - It might take a while... RESOLVED:rules_java
has been introduced as a Bazel module. RESOLVED:bazel_gazelle
has been introduced as a Bazel module. RESOLVED:io_bazel_rules_go
has been introduced as a Bazel module. RESOLVED:rules_python
has been introduced as a Bazel module. IMPORTANT: 3.11 is used as a default python version. If you need a different version, please change it manually and then rerun the migration tool. RESOLVED:my_python_deps
has been introduced as python extension. RESOLVED:org_golang_x_net
has been introduced as go extension. RESOLVED:rules_jvm_external
has been introduced as a Bazel module. RESOLVED:org.antlr
has been introduced as maven extension. RESOLVED:rules_shell
has been introduced as a Bazel module. Congratulations! All external repositories needed for building //... are available with Bzlmod! IMPORTANT: Fix potential build time issues by running the following command: bazel build --enable_bzlmod --noenable_workspace //... IMPORTANT:For details about the migration process, check `migration_info.md` file.
que proporciona la siguiente información importante:
- Genera el archivo
./resolved_deps.py
, que contiene información sobre todos los repositorios externos declarados y cargados con tu archivoWORKSPACE
. - La palabra clave
RESOLVED
describe todas las dependencias que resuelve la herramienta y que se agregan al archivoMODULE.bazel
. - La palabra clave
IMPORTANT
describe información importante en la que vale la pena invertir tiempo. - En este ejemplo, se resolvieron todas las dependencias, al menos con la marca
--nobuild
. - Es importante ejecutar la compilación completa (comando especificado) y corregir manualmente los posibles errores (p.ej., la cadena de herramientas no se registró correctamente).
- El archivo
migration_info.md
contiene detalles sobre la migración. Consulta los detalles en esta sección.
Transformaciones
En esta sección, se ilustra la migración del código del archivo WORKSPACE
a MODULE.bazel
.
WORKSPACE - Bazel Module
http_archive( name = "rules_shell", sha256 = "3e114424a5c7e4fd43e0133cc6ecdfe54e45ae8affa14fadd839f29901424043", strip_prefix = "rules_shell-0.4.0", url = "https://github.com/bazelbuild/rules_shell/releases/download/v0.4.0/rules_shell-v0.4.0.tar.gz", )
MODULE.bazel: Módulo de Bazel
bazel_dep(name = "rules_shell", version = "0.6.1")
WORKSPACE - Extensión de Go
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_repository") go_rules_dependencies() go_register_toolchains(version = "1.23.1") gazelle_dependencies() go_repository( name = "org_golang_x_net", importpath = "golang.org/x/net", sum = "h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=", version = "v0.0.0-20190311183353-d8887717615a", build_file_proto_mode = "disable", build_naming_convention = "import", )
MODULE.bazel - Go Extension
go_deps = use_extension("@bazel_gazelle//:extensions.bzl", "go_deps") go_sdk = use_extension("@io_bazel_rules_go//go:extensions.bzl", "go_sdk") go_deps.from_file(go_mod = "//:go.mod") use_repo(go_deps, "org_golang_x_net") go_sdk.from_file(go_mod = "//:go.mod") go_deps.gazelle_override( path = "golang.org/x/net", directives = [ "gazelle:proto disable", "gazelle:go_naming_convention import", ], )
WORKSPACE - Extensión de Python
http_archive( name = "rules_python", integrity = "sha256-qDdnnxOC8mlowe5vg5x9r5B5qlMSgGmh8oFd7KpjcwQ=", strip_prefix = "rules_python-1.4.0", url = "https://github.com/bazelbuild/rules_python/releases/download/1.4.0/rules_python-1.4.0.tar.gz", ) load("@rules_python//python:repositories.bzl", "py_repositories") py_repositories() load("@rules_python//python:pip.bzl", "pip_parse") pip_parse( name = "my_python_deps", requirements_lock = "@example//:requirements_lock.txt", ) load("@my_python_deps//:requirements.bzl", "install_deps") install_deps() load("@rules_python//python:repositories.bzl", "python_register_toolchains") python_register_toolchains( name = "python_3_11", python_version = "3.11", )
MODULE.bazel: extensión de Python
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip") pip.parse( hub_name = "my_python_deps", python_version = "3.11", requirements_lock = "//:requirements_lock.txt", ) use_repo(pip, "my_python_deps") python = use_extension("@rules_python//python/extensions:python.bzl", "python") python.defaults(python_version = "3.11") python.toolchain(python_version = "3.11")
WORKSPACE - Extensión de Maven
RULES_JVM_EXTERNAL_TAG = "4.5" RULES_JVM_EXTERNAL_SHA = "b17d7388feb9bfa7f2fa09031b32707df529f26c91ab9e5d909eb1676badd9a6" http_archive( name = "rules_jvm_external", strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG, sha256 = RULES_JVM_EXTERNAL_SHA, url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG, ) load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps") rules_jvm_external_deps() load("@rules_jvm_external//:setup.bzl", "rules_jvm_external_setup") rules_jvm_external_setup() load("@rules_jvm_external//:defs.bzl", "maven_install") maven_install( name = "px_deps", artifacts = [ "org.antlr:antlr4:4.11.1", ], repositories = [ "https://repo1.maven.org/maven2", ], )
MODULE.bazel: extensión de Maven
bazel_dep(name = "rules_jvm_external", version = "6.8") maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") use_repo(maven, "px_deps") maven.artifact( name = "px_deps", group = "org.antlr", artifact = "antlr4", version = "4.11.1" )
WORKSPACE - Repo rule
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "com_github_cockroachdb_cockroach", sha256 = "6c3568ef244ce6b874694eeeecb83ed4f5d5dff6cf037c952ecde76828a6c502", strip_prefix = "cockroach-22.1.6", url = "https://github.com/cockroachdb/cockroach/archive/v22.1.6.tar.gz", )
MODULE.bazel: regla de repo
http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "com_github_cockroachdb_cockroach", url = "https://github.com/cockroachdb/cockroach/archive/v22.1.6.tar.gz", sha256 = "6c3568ef244ce6b874694eeeecb83ed4f5d5dff6cf037c952ecde76828a6c502", strip_prefix = "cockroach-22.1.6", )
WORKSPACE - Module extension
load(":my_custom_macro.bzl", "my_custom_macro") my_custom_macro( name = "my_custom_repo", )
MODULE.bazel: Extensión del módulo
extension_for_my_custom_macro = use_extension("//:extension_for_my_custom_macro.bzl", "extension_for_my_custom_macro") use_repo(extension_for_my_custom_macro, "my_custom_repo")
extension_for_my_custom_macro.bzl
load("//:my_custom_macro.bzl", "my_custom_macro") def _extension_for_my_custom_macro_impl(ctx): my_custom_macro( name = "my_custom_repo", ) extension_for_my_custom_macro = module_extension(implementation = _extension_for_my_custom_macro_impl)
Sugerencias para la depuración
En esta sección, se proporcionan comandos e información útiles para depurar los problemas que pueden surgir durante la migración de Bzlmod.
Sugerencias útiles
Anular la versión: No es raro que la actualización de la versión de una dependencia cause problemas. Bzlmod podría cambiar la versión de la dependencia debido al algoritmo de MVS. Para usar la misma versión o una similar a la que se usaba en WORKSPACE, reemplázala con single_version_override. Ten en cuenta que esto es útil para depurar diferencias entre WORKSPACE y Bzlmod, pero no debes depender de esta función a largo plazo.
single_version_override(module_name = "{dep_name}", version = "{version}")
Usa el comando bazel mod.
Verifica la versión de un repo especificado con el comando
show_repo
. Por ejemplo:bazel mod show_repo @rules_python
Verifica la información sobre una extensión de módulo con el comando
show_extension
. Por ejemplo:bazel mod show_extension @rules_python//python/extensions:pip.bzl%pip
Usa el modo de proveedor para crear una copia local de un repo cuando quieras supervisar o controlar la fuente del repo. Por ejemplo:
bazel vendor --enable_bzlmod --vendor_dir=vendor_src --repo=@protobuf
Generación de informes de migración
Este archivo se actualiza con cada ejecución de la secuencia de comandos de migración o se genera desde cero si es la primera ejecución o si se usa la marca --i
. El informe contiene la siguiente información:
- Comando para pruebas locales.
- Lista de dependencias directas (al menos las que se usan directamente en el proyecto).
Para cada dependencia, un menú desplegable para verificar dónde se declaró el repositorio en el archivo
WORKSPACE
, lo que es particularmente útil para la depuración. Puedes verlo de la siguiente manera:> Click here to see where and how the repo was declared in the WORKSPACE file
Para cada dependencia, cómo se implementó en el archivo
MODULE.bazel
. En el ejemplo de migración anterior, se vería de la siguiente manera:Dependencia del módulo de Bazel:
Migration of rules_python
Found perfect name match in BCR: rules_python Found partially name matches in BCR: rules_python_gazelle_plugin It has been introduced as a Bazel module: `bazel_dep(name = "rules_python", version = "1.6.1")`
- La secuencia de comandos usará automáticamente el
perfect name match
si lo encuentra. En caso de error, puedes verificar si el nombre se agregó correctamente.
- La secuencia de comandos usará automáticamente el
Extensión de Python:
Migration of my_python_deps
pip.parse( hub_name = "my_python_deps", requirements_lock = "//:requirements_lock.txt", python_version = "3.11", ) use_repo(pip, "my_python_deps")
Extensión de Maven:
Migration of org.antlr (px_deps):
maven.artifact( name = "px_deps", group = "org.antlr", artifact = "antlr4", version = "4.11.1" )
Extensión Go:
Migration of org_golang_x_net
go_deps.from_file(go_mod = "//:go.mod") go_sdk.from_file(go_mod = "//:go.mod") go_deps.gazelle_override( path = "golang.org/x/net", directives = [ "gazelle:proto disable", "gazelle:go_naming_convention import", ], )
- Se introdujo como un módulo Go con la ayuda de
go.mod
. Sigo.mod
ygo.sum
no están disponibles, el módulo de Go se agrega directamente al archivoMODULE.bazel
. gazelle_override
se usa para agregar directivas específicas.
- Se introdujo como un módulo Go con la ayuda de
Vínculos útiles
- Páginas oficiales de las extensiones externas
- Publicaciones y videos de Comunidad
Comentarios
Si quieres contribuir, crea un problema o una PR en bazel-central-registry.