Tạo macro tượng trưng

Báo cáo vấn đề Xem nguồn Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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ũ, bạn nên viết một macro cũ; hãy xem phần 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 tệp nguồn hoặc nén 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 làm gì đó 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à sự 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 hơn, bạn có thể sử dụng lại mã này. Để thực hiện việc đó, hãy định nghĩa một hàm triển khai và một khai báo macro trong một tệp .bzl riêng biệt và gọi tệp đó là 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:

  • Hàm triển khai macro tượng trưng phải có tham số namevisibility. Bạn nên sử dụng các biến này 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 genrule cơ bản (cách này 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 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"],
)