7

我刚刚开始与 Bazel 合作。所以,我提前道歉,我无法弄清楚这一点。

我正在尝试运行一个命令,将一堆文件输出到一个目录并使该目录可用于后续目标。我有两种不同的尝试:

  1. 使用一般规则
  2. 写我自己的规则

我天真地希望只用genrule. 但是,您似乎不能说“我不确切知道该命令将输出什么”并将目录放在outs. 现在我正在尝试编写一个可以使用的规则,ctx.actions.declare_directory但我还没有完全正确。我似乎无法摆脱tools我的工作空间并进入我的规则。

我的一般尝试看起来像这样:

genrule(
    name = "doit",
    srcs = [
        "doitConfigA",
        "doitConfigB",
    ],
    cmd = 'HOME=. ./$(location path/to/doit) install',

    # Neither of the below outs work - seems like bazel wants to know
    # exactly this list of files. I don't know the files that
    # will be output ahead of time.

    # This one looks at the `out_dir` that I already have and
    # expects the files to be the same which they might not be
    outs = glob(["out_dir/**/*.*"]),

    # this fails with:
    # "declared output 'out_dir' was not 
    # created by genrule. This is probably because the genrule actually 
    # didn't create this output, or because the output was a directory 
    # and the genrule was run remotely (note that only the contents of 
    # declared file outputs are copied from genrules run remotely)"
    outs = ['out_dir'],
    tools = ['path/to/doit'],
)

我的自定义规则尝试如下所示:

def _impl(ctx):
  dir = ctx.actions.declare_directory("out_dir")

  ctx.actions.run_shell(
      outputs=[dir],
      progress_message="Running doit install ...",
      command="HOME=. ./path/to/doit install",
      tools=[ctx.attr.tools],
  )

doit = rule(
    implementation=_impl,
    attrs={
      "tools": attr.label_list(allow_files=True),
    },
    outputs={"out": "out_dir"},
)

然后,为了运行我的doit规则,我的 BUILD 文件如下所示:

doit(
  name = 'doit',
  tools = ['path/to/doit'],
)

在我的 genrule 中,该命令运行,但它似乎不喜欢我尝试在 中使用目录outs。在我的自定义规则中,我似乎无法告诉 Bazel 我想./path/to/doit用作工作区中的工具,例如expected type 'File' for 'tools' element but got type 'list' instead...

似乎我必须缺少一些基本的东西,因为这肯定是运行命令并将一堆未知内容输出到目录的常见情况?

4

2 回答 2

7

a 的输出genrule 必须是一个固定的文件列表。作为一种解决方法,您可以从输出目录创建一个 zip。

我使用这种方法来操纵yarn install通常方法不可行的输出:

genrule(
  name = "node_modules",
  srcs = [
    "package.json",
    "yarn.lock",
  ],
  cmd = " && ".join([
    "yarn install --pure-lockfile",
    "zip -r $@ node_modules",
  ]),
  outs = [
    "node_modules.zip",
  ],
)

然后是使用 zip 的规则:

# Rule that generates a list of the folders in node_modules
genrule(
  name = "node_modules_ls",
  srcs = [
    ":node_modules",
  ],
  cmd = " && ".join([
    "unzip $(location :node_modules) -d . ",
    "ls > $@",
  ]),
  outs = [
    "out.txt",
  ],
)
于 2020-01-16T14:55:35.193 回答
4

不久前,我创建了这个示例,展示了如何使用带有云雀操作的目录:How to build static library from the Generated source files using Bazel Build。也许它仍然有效:)

Genrule 不起作用,这是太高级的用例。

于 2018-06-28T15:44:36.230 回答