Công cụ di chuyển Bzlmod

Để đơn giản hoá quy trình thường phức tạp khi di chuyển từ WORKSPACE sang Bzlmod, bạn nên sử dụng tập lệnh di chuyển. Công cụ trợ giúp này tự động hoá nhiều bước liên quan đến việc di chuyển hệ thống quản lý phần phụ thuộc bên ngoài.

Lưu ý: Nếu bạn muốn dùng thử quy trình di chuyển Bzlmod do AI điều khiển, hãy xem phần Thiết lập tác nhân di chuyển Bzlmod.

Chức năng cốt lõi

Các chức năng chính của tập lệnh là:

  • Thu thập thông tin về phần phụ thuộc: Phân tích WORKSPACE tệp của dự án để xác định các kho lưu trữ bên ngoài do các mục tiêu bản dựng được chỉ định sử dụng, sử dụng experimental_repository_resolved_file của Bazel để tạo tệp phần phụ thuộc đã phân giải chứa thông tin này.
  • Xác định phần phụ thuộc trực tiếp: Sử dụng bazel query để xác định kho lưu trữ nào là phần phụ thuộc trực tiếp cho các mục tiêu được chỉ định.
  • Di chuyển sang Bzlmod: Dịch các phần phụ thuộc WORKSPACE có liên quan thành các phần phụ thuộc tương đương của Bzlmod. Đây là quy trình gồm 2 bước:
    1. Giới thiệu tất cả các phần phụ thuộc trực tiếp đã xác định vào tệp MODULE.bazel.
    2. Xây dựng các mục tiêu được chỉ định khi bật Bzlmod, sau đó xác định và khắc phục các lỗi có thể nhận dạng một cách lặp đi lặp lại. Bạn cần thực hiện bước này vì một số phần phụ thuộc có thể bị thiếu trong bước đầu tiên.
  • Tạo báo cáo di chuyển: Tạo tệp migration_info.md ghi lại quy trình di chuyển. Báo cáo này bao gồm danh sách các phần phụ thuộc trực tiếp, các nội dung khai báo Bzlmod đã tạo và mọi bước thủ công có thể cần thiết để hoàn tất quá trình di chuyển.

Công cụ di chuyển hỗ trợ:

  • Các phần phụ thuộc có trong Sổ đăng ký trung tâm Bazel
  • Quy tắc kho lưu trữ tuỳ chỉnh do người dùng xác định
  • Phần phụ thuộc của trình quản lý gói
    • Maven
    • Go
    • Python

Lưu ý quan trọng:

  • Công cụ di chuyển là một tiện ích hoạt động tối ưu nhất có thể. Luôn kiểm tra kỹ các đề xuất của công cụ này để đảm bảo tính chính xác.
  • Sử dụng công cụ di chuyển với Bazel 7 (không được hỗ trợ với Bazel 8).

Cách sử dụng công cụ di chuyển

Trước khi bắt đầu:

  • Nâng cấp lên bản phát hành Bazel 7 mới nhất, bản này hỗ trợ mạnh mẽ cả WORKSPACE và Bzlmod.
  • Xác minh rằng lệnh sau chạy thành công cho các mục tiêu bản dựng chính của dự án:

    bazel build --nobuild --enable_workspace --noenable_bzlmod <targets>
    

Lệnh chạy tập lệnh

Sau khi đáp ứng các điều kiện tiên quyết, hãy chạy các lệnh sau để sử dụng công cụ di chuyể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
cd <your project root>
migrate2bzlmod -t <targets>

Các tệp do tập lệnh này tạo

  • MODULE.bazel – Tệp kê khai trung tâm cho Bzlmod, khai báo siêu dữ liệu của dự án và các phần phụ thuộc trực tiếp của dự án đối với các mô-đun Bazel khác.
  • migration_info.md - Tệp cung cấp hướng dẫn từng bước về cách thực thi công cụ di chuyển , được thiết kế để hỗ trợ hoàn tất quy trình di chuyển theo cách thủ công (nếu cần) .
  • resolved_deps.py - Chứa danh sách toàn diện các phần phụ thuộc bên ngoài của dự án, được tạo bằng cách phân tích tệp WORKSPACE của dự án, đóng vai trò là tài liệu tham khảo trong quá trình chuyển đổi.
  • query_direct_deps - Chứa thông tin liên quan đến quá trình di chuyển về các mục tiêu được sử dụng, thu được bằng cách gọi Bazel bằng --output=build trên tệp WORKSPACE của dự án. Tệp này chủ yếu được tập lệnh di chuyển sử dụng.
  • extension_for_XXX – Tệp chứa định nghĩa tiện ích mô-đun. Công cụ di chuyển tạo các tệp này cho các phần phụ thuộc không phải là mô-đun Bazel tiêu chuẩn nhưng có thể được quản lý bằng các tiện ích mô-đun của Bzlmod.

Cờ

Các cờ có trong tập lệnh di chuyển này là:

  • --t/--target: Các mục tiêu cần di chuyển. Bạn có thể lặp lại cờ này và các mục tiêu sẽ được tích luỹ.
  • --i/--initial: Xoá các tệp MODULE.bazel, resolved_deps.py, migration_info.md và bắt đầu lại từ đầu – Phát hiện các phần phụ thuộc trực tiếp, giới thiệu các phần phụ thuộc này trong MODULE.bazel và chạy lại quá trình tạo các phần phụ thuộc đã phân giải.

Dọn dẹp sau khi di chuyển

  • Xoá migration_info.md, resolved_deps.pyquery_direct_deps.
  • Dọn dẹp các nhận xét khỏi tệp MODULE.bazel đã dùng cho quá trình di chuyển, chẳng hạn như # -- bazel_dep definitions -- #.

Ví dụ về quá trình di chuyển

Để xem tập lệnh di chuyển đang hoạt động, hãy xem xét tình huống sau khi các phần phụ thuộc Python, Maven và Go được khai báo trong tệp WORKSPACE.

Nhấp vào đây để xem tệp 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",
    ],
)

Ngoài ra, để minh hoạ cách sử dụng tiện ích mô-đun, macro tuỳ chỉnh được gọi từ WORKSPACE và được xác định trong my_custom_macro.bzl.

Nhấp vào đây để xem tệp 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)

Mục tiêu cuối cùng là có tệp MODULE.bazel và xoá tệp WORKSPACE mà không ảnh hưởng đến trải nghiệm người dùng.

Bước đầu tiên là làm theo Cách sử dụng công cụ di chuyển, chủ yếu là kiểm tra phiên bản Bazel (phải là Bazel 7) và thêm bí danh vào tập lệnh di chuyển.

Sau đó, việc chạy migrate2bzlmod -t=//... sẽ tạo ra:

  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.

cung cấp thông tin quan trọng sau:

  • Tạo tệp ./resolved_deps.py, chứa thông tin về tất cả các kho lưu trữ bên ngoài được khai báo và tải bằng tệp WORKSPACE.
  • Từ khoá RESOLVED mô tả tất cả các phần phụ thuộc được công cụ phân giải và thêm vào tệp MODULE.bazel.
  • Từ khoá IMPORTANT mô tả thông tin quan trọng đáng để đầu tư thời gian.
  • Tất cả các phần phụ thuộc đã được phân giải trong ví dụ này, ít nhất là bằng cờ --nobuild.
  • Bạn cần chạy bản dựng đầy đủ (lệnh được chỉ định) và khắc phục lỗi tiềm ẩn theo cách thủ công (ví dụ: chuỗi công cụ không được đăng ký đúng cách).
  • Tệp migration_info.md chứa thông tin chi tiết về quá trình di chuyển. Xem thông tin chi tiết trong phần này.

Phép biến đổi

Phần này minh hoạ quá trình di chuyển mã từ tệp WORKSPACE sang MODULE.bazel.

WORKSPACE – Mô-đun 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ô-đun Bazel

bazel_dep(name = "rules_shell", version = "0.6.1")

WORKSPACE – Tiện ích 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 – Tiện ích 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 – Tiện ích 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 – Tiện ích 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 – Tiện ích 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 – Tiện ích 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 – Quy tắc kho lưu trữ

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 – Quy tắc kho lưu trữ

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 – Tiện ích mô-đun

load(":my_custom_macro.bzl", "my_custom_macro")

my_custom_macro(
    name = "my_custom_repo",
)

MODULE.bazel – Tiện ích mô-đun

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)

Mẹo gỡ lỗi

Phần này cung cấp các lệnh và thông tin hữu ích để giúp gỡ lỗi các vấn đề có thể phát sinh trong quá trình di chuyển Bzlmod.

Mẹo hữu ích

  • Ghi đè phiên bản – Không hiếm khi việc nâng cấp phiên bản của một phần phụ thuộc gây ra vấn đề. Bzlmod có thể thay đổi phiên bản của phần phụ thuộc do thuật toán MVS. Để sử dụng phiên bản tương tự hoặc giống như trong WORKSPACE, hãy ghi đè bằng single_version_override. Xin lưu ý rằng tính năng này hữu ích cho việc gỡ lỗi sự khác biệt giữa WORKSPACE và Bzlmod, nhưng bạn không nên dựa vào tính năng này về lâu dài.

    single_version_override(module_name = "{dep_name}", version = "{version}")

  • Sử dụng lệnh bazel mod.

    • Kiểm tra phiên bản của một kho lưu trữ được chỉ định bằng lệnh show_repo. Ví dụ:

      bazel mod show_repo @rules_python

    • Kiểm tra thông tin về tiện ích mô-đun bằng lệnh show_extension. Ví dụ:

      bazel mod show_extension @rules_python//python/extensions:pip.bzl%pip

  • Sử dụng chế độ nhà cung cấp để tạo bản sao cục bộ của kho lưu trữ khi bạn muốn giám sát hoặc kiểm soát nguồn của kho lưu trữ. Ví dụ:

    bazel vendor --enable_bzlmod --vendor_dir=vendor_src --repo=@protobuf

Tạo báo cáo di chuyển

Tệp này được cập nhật mỗi khi tập lệnh di chuyển chạy hoặc được tạo lại từ đầu nếu đây là lần chạy đầu tiên hoặc nếu cờ --i được sử dụng. Báo cáo chứa:

Phản hồi

Nếu bạn muốn đóng góp, hãy tạo Vấn đề hoặc Yêu cầu kéo tại bazel-central-registry.