Para simplificar o processo, muitas vezes complexo, de migração de WORKSPACE
para Bzlmod, é
altamente recomendável usar o script de migração. Essa ferramenta
auxiliar automatiza muitas das etapas envolvidas na migração do seu sistema externo de
gerenciamento de dependências.
Observação: se você quiser testar a migração do Bzlmod com tecnologia de IA, confira 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:análise do arquivo
WORKSPACE
do 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 com essas informações. - Identificação de dependências diretas:uso de
bazel query
para determinar quais repositórios são dependências diretas dos destinos especificados. - Migração para o Bzlmod:tradução das dependências
WORKSPACE
relevantes para os equivalentes do Bzlmod. Esse processo é realizado em duas etapas:- Introduza todas as dependências diretas identificadas no arquivo
MODULE.bazel
. - Crie os 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 faltando na primeira etapa.
- Introduza todas as dependências diretas identificadas no arquivo
- Gerar um relatório de migração:criar um arquivo
migration_info.md
que documenta o processo de migração. Esse relatório inclui uma lista de dependências diretas, as declarações Bzlmod geradas e as etapas manuais que podem ser necessárias para concluir a migração.
A ferramenta de migração é compatível com:
- Dependências disponíveis no Registro central do Bazel
- Regras personalizadas do repositório 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 para WORKSPACE e Bzlmod.
Verifique se o seguinte comando é 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 cdmigrate2bzlmod -t
Arquivos gerados por esse script
MODULE.bazel
: o arquivo de manifesto central do Bzlmod, que declara os metadados do projeto e suas dependências diretas em outros módulos do Bazel.migration_info.md
: um arquivo com instruções detalhadas sobre como a ferramenta de migração foi executada, projetado 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 arquivoWORKSPACE
do 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 ao invocar o Bazel com--output=build
no arquivoWORKSPACE
do projeto. Esse arquivo é usado 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 pode ser repetida, e os destinos são acumulados.--i
/--initial
: exclui os arquivosMODULE.bazel
,resolved_deps.py
emigration_info.md
e começa do zero. Detecta dependências diretas, as introduz em MODULE.bazel e executa novamente a geração de dependências resolvidas.
Limpeza pós-migração
- Exclua
migration_info.md
,resolved_deps.py
equery_direct_deps
. - Limpe os comentários do arquivo
MODULE.bazel
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 seguinte cenário em que
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 de
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 (precisa ser o Bazel 7) e adicionar um alias ao script de migração.
Em seguida, executar migrate2bzlmod -t=//...
gera:
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 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
RESOLVED
descreve todas as dependências resolvidas pela ferramenta e adicionadas ao arquivoMODULE.bazel
. - A palavra-chave
IMPORTANT
descreve informações significativas que valem a pena investir tempo. - Neste exemplo, todas as dependências foram resolvidas, pelo menos com a flag
--nobuild
. - É importante executar o build completo (comando especificado) e corrigir manualmente possíveis erros (por exemplo, conjunto de ferramentas não registrado corretamente).
- O arquivo
migration_info.md
contém detalhes sobre a migração. Confira os detalhes nesta seção.
Transformações
Esta seção ilustra a migração do 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 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 - 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 de 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 semelhante à do WORKSPACE, substitua-a por single_version_override. Isso é útil para depurar diferenças entre WORKSPACE e 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
. Exemplo:bazel mod show_repo @rules_python
Confira informações sobre uma extensão de módulo com o comando
show_extension
. Exemplo:bazel mod show_extension @rules_python//python/extensions:pip.bzl%pip
Use o modo do fornecedor para criar uma cópia local de um repositório quando quiser monitorar ou controlar a origem dele. 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 flag --i
for usada. O relatório contém:
- Comando para teste local.
- 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 é especialmente útil para a depuração. Você pode entender isso 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_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")`
- O script vai usar automaticamente o
perfect name match
se o encontrar. Em caso de erro, verifique se o nome foi adicionado corretamente.
- O script vai usar automaticamente o
Extensão do 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")
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 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", ], )
- Ele foi introduzido como um módulo Go com a ajuda de
go.mod
. Sego.mod
ego.sum
nã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
- Postagens e vídeos na Comunidade
Feedback
Se quiser contribuir, crie um problema ou PR em bazel-central-registry.