bazel - 使用相同生成的输出文件实例化 Bazel 宏两次

标签 bazel bazel-rules starlark skylark bazel-extra-action

假设我有一个 Bazel 宏,它使用生成器规则在给定输入文件的情况下生成输出文件:

def my_generator(
        name,
        input_file,
        output_file,
        **kwargs):
    args = []
    args.extend(["--arg1", "$(location %s)" % output_file])
    args.extend(["arg2", "$(locations %s)" % input_file])

    cmd_params = " ".join(args)

    native.genrule(
        name = name,
        srcs = [input_file],
        outs = [output_file],
        cmd = "python $(location //path/to:target_generator) %s" % cmd_params,
        tools = ["/path/to/tool:mytool"],
    )

然后我之前使用这个宏作为:

my_generator(
    name = "gen1",
    input_file = ":targetToGeneratetextFile",
    output_file = "outputfile.txt",
    visibility = ["//myproject/oath/to/current/package/test:__subpackages__"],
)

目标作为 input_file 传递。这很有效。

然后我想用不同的输入重用它但生成相同的输出,其中输入现在是项目中的一个文件,但在另一个文件夹中。

my_generator(
    name = "gen2",
    input_file = "//path/to/the/file/realFile.txt",
    output_file = "outputfile.txt",
    visibility = ["//myproject/oath/to/current/package/test:__subpackages__"],
)

我以这种方式遇到了两个错误:

  1. 实际上,Bazel 找不到 realFile.txt:它尝试将其作为目标读取:

no such package '//path/to/the/file/realFile.txt': BUILD file not found in any of the following directories. Add a BUILD file to a directory to mark it as a package

如果我复制当前包文件夹中的文件,它能够读取它。

  1. Bazel 提示 gen1gen2 正在写入/覆盖相同的输出文件 outputfile.txt:

Error in genrule: generated file 'outputfile.txt' in rule 'gen2' conflicts with existing generated file from rule 'gen1', defined at ...

我该如何解决这些问题?

我认为问题在于这两个调用都已执行,而我希望它们根据某个目标执行,即目标 A 只需要运行 gen1 和目标 B gen2 独家。如果可能的话,我不会这样做,但是例如将这些调用中的每一个移动到它们所属的目标中可能是避免此问题的解决方案。

编辑 我在想做这样的事情的解决方案:

my_generator(
    name = "gen2",
    input_file = select({
       ":opt1": [":targetToGeneratetextFile"],
       ":opt2": ["realTextFile.txt"],
       "//conditions:default": [":targetToGeneratetextFile"],
    }),
    output_file = "outputfile.txt",
    visibility = ["//myproject/oath/to/current/package/test:__subpackages__"],
)

使用正确的 config_setting 然后使用正确的标志从目标调用它,但我收到错误:

expected value of type 'string' for element 0 of attribute 'srcs' in 'genrule' rule, but got select({":opt1": [":targetToGeneratetextFile"], ":opt2": ["realTextFile.txt"],"//conditions:default": [":targetToGeneratetextFile"], })

最佳答案

label //path/to/the/file/realFile.txt//path/to/the/file/realFile.txt:realFile.txt 的简写, 又名 <repository root>/path/to/the/file/realFile.txt/realFile.txt .根据包含 BUILD 文件的最深嵌套文件夹的位置(决定包),您正在寻找类似 //path/to/the/file:realFile.txt 的内容。或 //path/to:the/file/realFile.txt相反。

你不能有两条规则来写入同一个文件,因为如果你 bazel build 那么 Bazel 就无法判断以哪种方式构建它。文件。一些替代方案:

  • 将它们放在单独的包中(也就是带有 BUILD 文件的单独文件夹)
  • 以不同的方式命名,例如 gen1_outputfile.txtgen2_outputfile.txt , 或 gen1/outputfile.txtgen2/outputfile.txt .您可以在 srcs = [name + '/outputfile.txt'] 之类的宏中自动执行此操作.
  • 使用单个规则通过适当的选择生成它,例如您的编辑。

随着 select ,你正在尝试创建这样的东西:

genrule(
    srcs = select({..., "//conditions:default": [":targetToGeneratetextFile"]}),
    ...
)

但是正如所写的那样,你有这个:

genrule(
    srcs = [select({..., "//conditions:default": [":targetToGeneratetextFile"]})],
    ...
)

有效地,介于select之间的列表的值和宏主体,您正在创建一个嵌套列表。我会将您的宏参数更改为 input_files然后做 srcs = input_files在主体中,因此宏的调用者可以根据需要将内容打包到列表中。

关于bazel - 使用相同生成的输出文件实例化 Bazel 宏两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73164371/

相关文章:

bazel - 我如何需要沙箱?

python - 使用 Bazel 为 AWS Lambda 创建 Python zip

github - 使用 Bazel 拉取 GitHub 存储库

bazel - 是否有 Bazel 命令行来确定一个或多个给定标签的输出的绝对路径?

bazel - 如何删除 py_library 导入中的文件夹名称?

bazel - 如何将 Starlark 脚本正确加载到另一个脚本中?

bazel - 获取 Bazel 工具链配置文件中包的运行时路径

c++ - 如何使用 Eigen 和 Bazel 构建一个简单的 C++ 演示?

java - 在 bazel 构建中将 mvn 作为工具运行