Tạo macro cũ

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 cũ. Nếu chỉ cần hỗ trợ Bazel 8 trở lên, bạn nên sử dụng macro tượng trưng; hãy xem phần Tạo macro tượng trưng.

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ể 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 cũ để đổ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 trong một tệp .bzl riêng biệt và gọi tệp đó là miniature.bzl:

def miniature(name, src, size = "100x100", **kwargs):
    """Create a miniature of the src image.

    The generated file is prefixed with 'small_'.
    """
    native.genrule(
        name = name,
        srcs = [src],
        # Note that the line below will fail if `src` is not a filename string
        outs = ["small_" + src],
        cmd = "convert $< -resize " + size + " $@",
        **kwargs
    )

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

  • Theo quy ước, các macro cũ có đối số name, giống như các quy tắc.

  • Để ghi lại hành vi của một macro cũ, hãy sử dụng docstring như trong Python.

  • Để gọi genrule hoặc bất kỳ quy tắc gốc nào khác, hãy thêm tiền tố native..

  • Sử dụng **kwargs để chuyển tiếp các đối số 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ể sử dụng các thuộc tính chuẩn như visibility hoặc tags.

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"],
)

Cuối cùng, một lưu ý cảnh báo: macro giả định rằng src là một chuỗi tên tệp (nếu không, outs = ["small_" + src] sẽ không thành công). Vì vậy, src = "image.png" hoạt động; nhưng điều gì sẽ xảy ra nếu tệp BUILD sử dụng src = "//other/package:image.png" hoặc thậm chí là src = select(...)?

Bạn cần nhớ khai báo các giả định đó trong tài liệu của macro. Rất tiếc, các macro cũ, đặc biệt là các macro lớn, thường dễ bị lỗi vì bạn khó có thể nhận thấy và ghi lại tất cả các giả định như vậy trong mã của mình – và tất nhiên, một số người dùng macro sẽ không đọc tài liệu. Bạn nên sử dụng macro tượng trưng (nếu có thể) vì macro này có các tính năng kiểm tra tích hợp sẵn đối với các loại thuộc tính.