Para simplificar o processo de migração de WORKSPACE para Bzlmod, recomendamos o uso do script de migração. Essa ferramenta auxiliar automatiza muitas das etapas envolvidas na migração do sistema de gerenciamento de dependências externas.
Observação: se você quiser testar a migração do Bzlmod orientada por IA, consulte Configuração do agente de migração do Bzlmod.
Funcionalidade principal
As principais funções do script são:
- Coleta de informações de dependência: analisa o arquivo
WORKSPACEdo projeto para identificar repositórios externos usados por destinos de build especificados, usando a flag experimental_repository_resolved_file do Bazel para gerar um arquivo de dependências resolvidas que contém essas informações. - Identificação de dependências diretas:usa
bazel querypara determinar quais repositórios são dependências diretas dos destinos especificados. - Migração para o Bzlmod:traduz as dependências relevantes do
WORKSPACEpara os equivalentes do Bzlmod. Esse processo é realizado em duas etapas:- Introduza todas as dependências diretas identificadas no arquivo
MODULE.bazel. - Crie destinos especificados com o Bzlmod ativado e identifique e corrija erros reconhecíveis de forma iterativa. Essa etapa é necessária porque algumas dependências podem estar ausentes na primeira etapa.
- Introduza todas as dependências diretas identificadas no arquivo
- Geração de um relatório de migração:cria um arquivo
migration_info.mdque documenta o processo de migração. Esse relatório inclui uma lista de dependências diretas, as declarações do Bzlmod geradas e todas as etapas manuais que podem ser necessárias para concluir a migração.
A ferramenta de migração oferece suporte a:
- Dependências disponíveis no Registro central do Bazel
- Regras de repositório personalizadas definidas pelo usuário
- Dependências do gerenciador de pacotes
- Maven
- Go
- Python
Observações importantes:
- A ferramenta de migração é um utilitário de melhor esforço. Sempre verifique se as recomendações estão corretas.
- Use a ferramenta de migração com o Bazel 7 (não é compatível com o Bazel 8).
Como usar a ferramenta de migração
Antes de começar:
- Faça upgrade para a versão mais recente do Bazel 7, que oferece suporte robusto ao WORKSPACE e ao Bzlmod.
Verifique se o comando a seguir é executado corretamente para os principais destinos de build do projeto:
bazel build --nobuild --enable_workspace --noenable_bzlmod <targets>
Comando para executar o script
Depois que os pré-requisitos forem atendidos, execute os comandos a seguir para usar a ferramenta de migração:
# 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 cd <your project root> migrate2bzlmod -t <targets>
Arquivos gerados por esse script
MODULE.bazel: o arquivo de manifesto central do Bzlmod, que declara os metadados do projeto e as dependências diretas em outros módulos do Bazel.migration_info.md: um arquivo que fornece instruções detalhadas sobre como a ferramenta de migração foi executada, projetada para ajudar na conclusão manual do processo de migração, se necessário.resolved_deps.py: contém uma lista abrangente das dependências externas do projeto, gerada pela análise do arquivoWORKSPACEdo projeto, servindo como referência durante a transição.query_direct_deps: contém informações relevantes para a migração sobre os destinos utilizados, obtidas invocando o Bazel com--output=buildno arquivoWORKSPACEdo projeto. Esse arquivo é consumido principalmente pelo script de migração.extension_for_XXX: um arquivo que contém uma definição de extensão de módulo. A ferramenta de migração gera esses arquivos para dependências que não são módulos padrão do Bazel, mas podem ser gerenciadas usando as extensões de módulo do Bzlmod.
Sinalizações
As flags disponíveis nesses scripts de migração são:
--t/--target: destinos a serem migrados. Essa flag é repetível, e os destinos são acumulados.--i/--initial: exclui os arquivosMODULE.bazel,resolved_deps.py,migration_info.mde começa do zero. Detecta dependências diretas, as introduz no MODULE.bazel e executa novamente a geração de dependências resolvidas.
Limpeza pós-migração
- Exclua
migration_info.md,resolved_deps.pyequery_direct_deps. - Limpe os comentários do arquivo
MODULE.bazelque foram usados para a migração, como# -- bazel_dep definitions -- #.
Exemplo de migração
Para ver o script de migração em ação, considere o cenário a seguir quando as dependências do Python, do Maven e do Go são declaradas no arquivo WORKSPACE.
Clique aqui para ver o arquivo 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",
],
)
Além disso, para demonstrar o uso da extensão do módulo, a macro personalizada é invocada do WORKSPACE e definida em my_custom_macro.bzl.
Clique aqui para ver o arquivo 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)
O objetivo final é ter o arquivo MODULE.bazel e excluir o arquivo WORKSPACE, sem afetar a experiência do usuário.
A primeira etapa é seguir Como usar a ferramenta de migração, que consiste principalmente em verificar a versão do Bazel (ela precisa ser a 7) e adicionar um alias ao script de migração.
Em seguida, a execução de migrate2bzlmod -t=//... gera:
bazel 7.6.1 Generating ./resolved_deps.py file - It might take a while... RESOLVED:rules_javahas been introduced as a Bazel module. RESOLVED:bazel_gazellehas been introduced as a Bazel module. RESOLVED:io_bazel_rules_gohas been introduced as a Bazel module. RESOLVED:rules_pythonhas 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_depshas been introduced as python extension. RESOLVED:org_golang_x_nethas been introduced as go extension. RESOLVED:rules_jvm_externalhas been introduced as a Bazel module. RESOLVED:org.antlrhas been introduced as maven extension. RESOLVED:rules_shellhas 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 fornece as seguintes informações importantes:
- Gera o arquivo
./resolved_deps.py, que contém informações sobre todos os repositórios externos declarados e carregados usando o arquivoWORKSPACE. - A palavra-chave
RESOLVEDdescreve todas as dependências resolvidas pela ferramenta e adicionadas ao arquivoMODULE.bazel. - A palavra-chave
IMPORTANTdescreve informações significativas que valem a pena investir tempo. - Todas as dependências foram resolvidas neste exemplo, pelo menos com a flag
--nobuild. - É importante executar o build completo (comando especificado) e corrigir manualmente possíveis erros (por exemplo, o conjunto de ferramentas não registrado corretamente).
- O arquivo
migration_info.mdcontém detalhes sobre a migração. Confira os detalhes nesta seção.
Transformações
Esta seção ilustra a migração de código do arquivo WORKSPACE para MODULE.bazel.
WORKSPACE - Módulo do Bazel
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 do Bazel
bazel_dep(name = "rules_shell", version = "0.6.1")
WORKSPACE - Extensão do 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 - Extensão do Go
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 - Extensão do 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 - Extensão do 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 - Extensão do 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 - Extensão do 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 - Regra de repositório
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 - Regra de repositório
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 - Extensão do módulo
load(":my_custom_macro.bzl", "my_custom_macro") my_custom_macro( name = "my_custom_repo", )
MODULE.bazel - Extensão do 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)
Dicas de depuração
Esta seção fornece comandos e informações úteis para ajudar a depurar problemas que podem surgir durante a migração do Bzlmod.
Dicas úteis
Substituir versão: não é raro que o upgrade da versão de uma dependência cause problemas. O Bzlmod pode mudar a versão da dependência devido ao algoritmo MVS. Para usar a mesma versão ou uma versão semelhante à do WORKSPACE, substitua-a por single_version_override. Isso é útil para depurar diferenças entre o WORKSPACE e o Bzlmod, mas não confie nesse recurso a longo prazo.
single_version_override(module_name = "{dep_name}", version = "{version}")Use o comando bazel mod.
Verifique a versão de um repositório especificado com o comando
show_repo. Por exemplo:bazel mod show_repo @rules_pythonVerifique as informações sobre uma extensão de módulo com o comando
show_extension. Por exemplo:bazel mod show_extension @rules_python//python/extensions:pip.bzl%pip
Use o modo de fornecedor para criar uma cópia local de um repositório quando quiser monitorar ou controlar a origem dele. Por exemplo:
bazel vendor --enable_bzlmod --vendor_dir=vendor_src --repo=@protobuf
Geração de relatórios de migração
Esse arquivo é atualizado a cada execução do script de migração ou gerado
do zero se for a primeira execução ou se a --i
flag for usada. O relatório contém:
- Comando para testes locais.
- Lista de dependências diretas (pelo menos as que são usadas diretamente no projeto).
Para cada dependência, um menu suspenso para verificar onde o repositório foi declarado no arquivo
WORKSPACE, o que é particularmente útil para a depuração. Ele aparece como:> Click here to see where and how the repo was declared in the WORKSPACE file
Para cada dependência, como ela foi implementada no arquivo
MODULE.bazel. No exemplo de migração anterior, isso seria assim:Dependência do módulo do Bazel:
Migration of rules_pythonFound 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")`
- O script vai usar automaticamente a
perfect name matchse a encontrar. Em caso de erro, verifique se o nome foi adicionado corretamente.
- O script vai usar automaticamente a
Extensão do Python:
Migration of my_python_depspip.parse( hub_name = "my_python_deps", requirements_lock = "//:requirements_lock.txt", python_version = "3.11", ) use_repo(pip, "my_python_deps")
Extensão do Maven:
Migration of org.antlr (px_deps):maven.artifact( name = "px_deps", group = "org.antlr", artifact = "antlr4", version = "4.11.1" )
Extensão do Go:
Migration of org_golang_x_netgo_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", ], )
- Ele foi introduzido como um módulo Go com a ajuda de
go.mod. Sego.modego.sumnão estiverem disponíveis, o módulo Go será adicionado diretamente ao arquivoMODULE.bazel. gazelle_overrideé usado para adicionar diretivas específicas.
- Ele foi introduzido como um módulo Go com a ajuda de
Links úteis
- Páginas oficiais das extensões externas
- Posts e vídeos da comunidade
Feedback
Se você quiser contribuir, crie um problema ou PR no bazel-central-registry.