Nhóm thực thi

7.3 · 7.2 · 7.1 · 7.0 · 6.5

Nhóm thực thi cho phép nhiều nền tảng thực thi trong một mục tiêu. Mỗi nhóm thực thi có các phần phụ thuộc chuỗi công cụ riêng và thực hiện độ phân giải chuỗi công cụ riêng.

Thông tin khái quát

Nhóm thực thi cho phép tác giả quy tắc xác định các nhóm hành động, mỗi nhóm có thể có một nền tảng thực thi khác nhau. Nhiều nền tảng thực thi có thể cho phép thực thi các thao tác theo cách khác nhau, ví dụ: biên dịch một ứng dụng iOS trên một worker từ xa (linux) rồi liên kết/ký mã trên một worker mac cục bộ.

Việc có thể xác định các nhóm thao tác cũng giúp giảm thiểu việc sử dụng câu lệnh nhanh thao tác làm proxy để chỉ định thao tác. Thuật toán ghi nhớ không được đảm bảo là duy nhất và chỉ có thể tham chiếu đến một hành động. Điều này đặc biệt hữu ích trong việc phân bổ thêm tài nguyên cho bộ nhớ cụ thể và xử lý các thao tác chuyên sâu như liên kết trong các bản dựng C++ mà không phân bổ quá mức cho các tác vụ tốn ít công sức hơn.

Xác định nhóm thực thi

Trong quá trình xác định quy tắc, tác giả quy tắc có thể declare một tập hợp các nhóm thực thi. Trên mỗi nhóm thực thi, tác giả quy tắc có thể chỉ định mọi thứ cần thiết để chọn một nền tảng thực thi cho nhóm thực thi đó, cụ thể là mọi quy tắc ràng buộc thông qua exec_compatible_with và các loại chuỗi công cụ thông qua toolchain.

# foo.bzl
my_rule = rule(
    _impl,
    exec_groups = {
        link: exec_group(
            exec_compatible_with = [ "@platforms//os:linux" ]
            toolchains = ["//foo:toolchain_type"],
        ),
        test: exec_group(
            toolchains = ["//foo_tools:toolchain_type"],
        ),
    },
    attrs = {
        "_compiler": attr.label(cfg = config.exec("link"))
    },
)

Trong đoạn mã ở trên, bạn có thể thấy rằng các phần phụ thuộc công cụ cũng có thể chỉ định chuyển đổi cho một nhóm thực thi bằng cách sử dụng tham số thuộc tính cfg và mô-đun config. Mô-đun này hiển thị một hàm exec nhận một tham số chuỗi duy nhất là tên của nhóm thực thi mà phần phụ thuộc sẽ được tạo.

Giống như trên các quy tắc gốc, nhóm thực thi test sẽ xuất hiện theo mặc định trên các quy tắc kiểm thử Starlark.

Kế thừa nhóm thực thi

Ngoài việc xác định các quy tắc ràng buộc và chuỗi công cụ của riêng mình, một nhóm thực thi mới có thể khai báo rằng nhóm này muốn kế thừa từ nhóm thực thi mặc định của quy tắc bằng cách truyền tham số copy_from_rule = True. Bạn sẽ gặp lỗi nếu đặt copy_from_rule thành true và cũng truyền exec_compatible_with hoặc toolchains.

Một nhóm thực thi kế thừa từ nhóm thực thi mặc định sẽ sao chép các quy tắc ràng buộc, chuỗi công cụ và thuộc tính thực thi từ giá trị mặc định. Dữ liệu này bao gồm các điều kiện ràng buộc và thuộc tính thực thi được đặt ở cấp mục tiêu, chứ không chỉ các quy tắc do chính quy tắc chỉ định. Nói cách khác, với những thông tin sau:

# foo.bzl
my_rule = rule(
    _impl,
    exec_groups = {
        copied: exec_group(
            copy_from_rule = True,
            # This will inherit exec_compatible_with and toolchains.
            # Setting them here directly would be an error, however.
        ),
    },
    toolchains = ["//foo_tools:toolchain_type"],
    exec_compatible_with = ["@platforms//os:linux"],
)

# BUILD

my_rule(
    name = "demo",
    exec_compatible_with = [":local_constraint"],
)

Nhóm thực thi copied cho mục tiêu demo đã định cấu hình sẽ bao gồm tất cả: - //fool_tools:toolchain_type - @platforms//os:linux - :local_constraint

Truy cập vào các nhóm thực thi

Trong quá trình triển khai quy tắc, bạn có thể khai báo rằng các hành động sẽ chạy trên nền tảng thực thi của một nhóm thực thi. Bạn có thể thực hiện việc này bằng cách sử dụng tham số exec_group của các phương thức tạo hành động, cụ thể là ctx.actions.runctx.actions.run_shell.

# foo.bzl
def _impl(ctx):
  ctx.actions.run(
     inputs = [ctx.attr._some_tool, ctx.srcs[0]]
     exec_group = "compile",
     # ...
  )

Tác giả quy tắc cũng có thể truy cập vào chuỗi công cụ đã phân giải của các nhóm thực thi, tương tự như cách bạn có thể truy cập vào chuỗi công cụ đã phân giải của một mục tiêu:

# foo.bzl
def _impl(ctx):
  foo_info = ctx.exec_groups["link"].toolchains["//foo:toolchain_type"].fooinfo
  ctx.actions.run(
     inputs = [foo_info, ctx.srcs[0]]
     exec_group = "link",
     # ...
  )

Sử dụng nhóm thực thi để thiết lập thuộc tính thực thi

Các nhóm thực thi được tích hợp với thuộc tính exec_properties có trên mọi quy tắc và cho phép trình ghi mục tiêu chỉ định một tập hợp các thuộc tính chuỗi, sau đó được truyền đến cơ chế thực thi. Ví dụ: nếu muốn đặt một số thuộc tính, chẳng hạn như bộ nhớ, cho mục tiêu và phân bổ bộ nhớ cao hơn cho một số hành động nhất định, bạn sẽ viết một mục exec_properties bằng khoá tăng cường nhóm thực thi, chẳng hạn như:

# BUILD
my_rule(
    name = 'my_target',
    exec_properties = {
        'mem': '12g',
        'link.mem': '16g'
    }
    
)

Tất cả thao tác với exec_group = "link" sẽ thấy từ điển thuộc tính thực thi là {"mem": "16g"}. Như bạn thấy ở đây, chế độ cài đặt cấp nhóm thực thi sẽ ghi đè chế độ cài đặt cấp mục tiêu.

Nhóm thực thi cho quy tắc gốc

Bạn có thể sử dụng các nhóm thực thi sau đây cho các hành động được xác định theo quy tắc gốc:

  • test: Thao tác của trình chạy kiểm thử.
  • cpp_link: Thao tác liên kết C++.

Tạo nhóm thực thi để đặt thuộc tính thực thi

Đôi khi, bạn muốn sử dụng một nhóm thực thi để cung cấp các hành động cụ thể với các thuộc tính thực thi khác nhau, nhưng thực sự không muốn các chuỗi công cụ hoặc quy tắc ràng buộc khác với quy tắc. Đối với những trường hợp này, bạn có thể tạo nhóm thực thi bằng tham số copy_from_rule:

# foo.bzl

# Creating an exec group with `copy_from_rule=True` is the same as explicitly
# setting the exec group's toolchains and constraints to the same values as the
# rule's respective parameters.
my_rule = rule(
    _impl,
    exec_compatible_with = ["@platforms//os:linux"],
    toolchains = ["//foo:toolchain_type"],
    exec_groups = {
        # The following two groups have the same toolchains and constraints:
        foo: exec_group(copy_from_rule = True),
        "bar": exec_group(
            exec_compatible_with = ["@platforms//os:linux"],
            toolchains = ["//foo:toolchain_type"],
        ),
    },
)

#

Nhóm thực thi và thuộc tính thực thi nền tảng

Bạn có thể xác định exec_properties cho các nhóm thực thi tuỳ ý trên các mục tiêu nền tảng (không giống như exec_properties được đặt trực tiếp trên một mục tiêu, trong đó các thuộc tính cho các nhóm thực thi không xác định sẽ bị từ chối). Sau đó, các mục tiêu sẽ kế thừa exec_properties của nền tảng thực thi. Nền tảng này ảnh hưởng đến nhóm thực thi mặc định cũng như mọi nhóm thực thi có liên quan khác.

Ví dụ: giả sử việc chạy kiểm thử C++ yêu cầu có sẵn một số tài nguyên, nhưng không bắt buộc phải có tài nguyên để biên dịch và liên kết; bạn có thể lập mô hình như sau:

constraint_setting(name = "resource")
constraint_value(name = "has_resource", constraint_setting = ":resource")

platform(
    name = "platform_with_resource",
    constraint_values = [":has_resource"],
    exec_properties = {
        "test.resource": "...",
    },
)

cc_test(
    name = "my_test",
    srcs = ["my_test.cc"],
    exec_compatible_with = [":has_resource"],
)

exec_properties được xác định trực tiếp trên các mục tiêu sẽ được ưu tiên hơn những mục tiêu kế thừa từ nền tảng thực thi.