簡體   English   中英

如何在 Bazel 規則中運行其他規則的可執行文件?

[英]How can you run the executables of other rules within a Bazel rule?

假設我有一個自定義規則my_object 看起來像:

my_object(
  name = "foo",
  deps = [
    //services/image-A:push,
    //services/image-B:push,
  ]
)

deps中的標簽是rules_dockercontainer_push規則。

我希望能夠bazel run //:foo並讓它在deps列表中推送 Docker 圖像。 我該怎么做呢?

這似乎是一個特定情況,通常只是希望在自定義規則的可執行文件中運行其他規則的可執行文件。

這里要做的是讓my_object output 成為執行其他可執行文件的可執行文件。

考慮這個例子:

def _impl1(ctx):
  ctx.actions.write(
    output = ctx.outputs.executable,
    is_executable = True,
    content = "echo %s 123" % ctx.label.name)
  return DefaultInfo(executable = ctx.outputs.executable)


exec_rule1 = rule(
  implementation = _impl1,
  executable = True,
)


def _impl2(ctx):

  executable_paths = []
  runfiles = ctx.runfiles()
  for dep in ctx.attr.deps:
    # the "./" is needed if the executable is in the current directory
    # (i.e. in the workspace root)
    executable_paths.append("./" + dep.files_to_run.executable.short_path)
    # collect the runfiles of the other executables so their own runfiles
    # will be available when the top-level executable runs
    runfiles = runfiles.merge(dep.default_runfiles)

  ctx.actions.write(
    output = ctx.outputs.executable,
    is_executable = True,
    content = "\n".join(executable_paths))

  return DefaultInfo(
    executable = ctx.outputs.executable,
    runfiles = runfiles)


exec_rule2 = rule(
  implementation = _impl2,
  executable = True,
  attrs = {
    "deps": attr.label_list(),
  },
)

BUILD.bazel

load(":defs.bzl", "exec_rule1", "exec_rule2")

exec_rule1(name = "foo")
exec_rule1(name = "bar")
exec_rule2(name = "baz", deps = [":foo", ":bar"])

然后運行它:

$ bazel run //:baz
INFO: Analyzed target //:baz (4 packages loaded, 19 targets configured).
INFO: Found 1 target...
Target //:baz up-to-date:
  bazel-bin/baz
INFO: Elapsed time: 0.211s, Critical Path: 0.01s
INFO: 0 processes.
INFO: Build completed successfully, 6 total actions
INFO: Build completed successfully, 6 total actions
foo 123
bar 123

我設法通過在規則中實現DefaultInfo來實現這一點。

def build_all_impl(ctx):
    targets = ctx.attr.targets
    run_files = []
    for target in targets:
        run_files = run_files + target.files.to_list()
    DefaultInfo(
        runfiles = ctx.runfiles(run_files),
    )

build_all = rule(
    implementation = build_all_impl,
    attrs = {
        "targets": attr.label_list(
            doc = "target to build",
        ),
    },
)

然后通過運行 build_all 規則

build_all(
    name = "all",
    targets = [
        ":target-1",
        ":target-2",
        ...
    ],
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM