Tạo macro tượng trưng

QUAN TRỌNG: Hướng dẫn này dành cho macro tượng trưng – hệ thống macro mới được giới thiệu trong Bazel 8. Nếu cần hỗ trợ các phiên bản Bazel cũ hơn, bạn nên viết một macro cũ thay thế; hãy xem bài viết Tạo macro cũ.

Hãy tưởng tượng bạn cần chạy một công cụ trong quá trình xây dựng. Ví dụ: bạn có thể muốn tạo hoặc xử lý trước một tệp nguồn hoặc nén một tệp nhị phân. Trong hướng dẫn này, bạn sẽ tạo một macro tượng trưng để đổi kích thước hình ảnh.

Macro phù hợp với các tác vụ đơn giản. Nếu bạn muốn thực hiện bất kỳ thao tác nào phức tạp hơn, chẳng hạn như thêm tính năng hỗ trợ cho một ngôn ngữ lập trình mới, hãy cân nhắc việc tạo một quy tắc. Quy tắc giúp bạn có thêm quyền kiểm soát và tính linh hoạt.

Cách dễ nhất để tạo một macro đổi kích thước hình ảnh là sử dụng genrule:

genrule(
    name = "logo_miniature",
    srcs = ["logo.png"],
    outs = ["small_logo.png"],
    cmd = "convert $< -resize 100x100 $@",
)

cc_binary(
    name = "my_app",
    srcs = ["my_app.cc"],
    data = [":logo_miniature"],
)

Nếu cần đổi kích thước nhiều hình ảnh, bạn có thể muốn sử dụng lại mã. Để thực hiện việc đó, hãy xác định một hàm triển khai và một khai báo macro trong một tệp .bzl riêng biệt, rồi gọi tệp miniature.bzl:

# Implementation function
def _miniature_impl(name, visibility, src, size, **kwargs):
    native.genrule(
        name = name,
        visibility = visibility,
        srcs = [src],
        outs = [name + "_small_" + src.name],
        cmd = "convert $< -resize " + size + " $@",
        **kwargs,
    )

# Macro declaration
miniature = macro(
    doc = """Create a miniature of the src image.

    The generated file name will be prefixed with `name + "_small_"`.
    """,
    implementation = _miniature_impl,
    # Inherit most of genrule's attributes (such as tags and testonly)
    inherit_attrs = native.genrule,
    attrs = {
        "src": attr.label(
            doc = "Image file",
            allow_single_file = True,
            # Non-configurable because our genrule's output filename is
            # suffixed with src's name. (We want to suffix the output file with
            # srcs's name because some tools that operate on image files expect
            # the files to have the right file extension.)
            configurable = False,
        ),
        "size": attr.string(
            doc = "Output size in WxH format",
            default = "100x100",
        ),
        # Do not allow callers of miniature() to set srcs, cmd, or outs -
        # _miniature_impl overrides their values when calling native.genrule()
        "srcs": None,
        "cmd": None,
        "outs": None,
    },
)

Một vài nhận xét:

  • Các hàm triển khai macro tượng trưng phải có namevisibility tham số. Các hàm này nên được dùng cho mục tiêu chính của macro.

  • Để ghi lại hành vi của một macro tượng trưng, hãy sử dụng các tham số doc cho macro() và các thuộc tính của macro đó.

  • Để gọi genrule hoặc bất kỳ quy tắc gốc nào khác, hãy sử dụng native..

  • Sử dụng **kwargs để chuyển tiếp các đối số kế thừa bổ sung đến cơ bảngenrule (hoạt động giống như trong Python). Điều này rất hữu ích để người dùng có thể đặt các thuộc tính tiêu chuẩn như tags hoặc testonly.

Bây giờ, hãy sử dụng macro từ tệp BUILD:

load("//path/to:miniature.bzl", "miniature")

miniature(
    name = "logo_miniature",
    src = "image.png",
)

cc_binary(
    name = "my_app",
    srcs = ["my_app.cc"],
    data = [":logo_miniature"],
)