Bazel:输出目录的genrule

11

我刚开始使用Bazel工具,因此,我很抱歉还没有找到解决方法。

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

  1. 使用genrule
  2. 编写自己的规则

我最初希望只使用 genrule 就能实现此功能。但是,似乎无法在 outs 中放置一个目录并说“我不知道这个命令会输出什么”。现在我正在尝试编写一条规则,可以使用 ctx.actions.declare_directory,但我还没有完全弄清楚。我似乎无法将 tools 从我的工作区传输到我的规则中。

我的genrule尝试看起来像这样:

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作为工具,例如“期望'tools'元素的类型为'File',但实际上得到了'type 'list''”。似乎我必须缺少一些基本知识,因为运行命令并将大量未知内容输出到目录中肯定是常见情况吧?
3个回答

8
< p > 一个< code >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",
  ],
)

1
我不喜欢这个,但是它能用。+1 - edc
请注意,应该使用工具“zipper”生成可重复的压缩包。 - sdgfsdh

4

1

2
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Steven

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接