Bazel:如何获得生成文件的路径?

Bazel:如何获得生成文件的路径?,bazel,Bazel,在Bazel中,给定构建目标,脚本(在Bazel之外运行)如何获得生成文件的路径 场景:我正在使用Bazel进行构建,完成后,我想将结果复制到服务器。我只需要知道要复制哪些文件。我可以硬编码文件列表,但我不想这样做 一个简单的示例:此Bazel脚本: genrule( name = "main", srcs = ["main.in"], outs = ["main.out"], cmd = "cp $< $@", ) 还有:bazel-genfiles/m

在Bazel中,给定构建目标,脚本(在Bazel之外运行)如何获得生成文件的路径

场景:我正在使用Bazel进行构建,完成后,我想将结果复制到服务器。我只需要知道要复制哪些文件。我可以硬编码文件列表,但我不想这样做

一个简单的示例:此Bazel脚本:

genrule(
    name = "main",
    srcs = ["main.in"],
    outs = ["main.out"],
    cmd = "cp $< $@",
)
还有:
bazel-genfiles/main.out
。但是我可以使用什么机器可读的技术来获得这条路径呢?(我可以解析
bazel build
的输出,但我们不希望这样做。)

我找到的最接近的方法是使用
bazel查询--output=xml:main
,它以xml格式转储有关
:main
的信息。输出包括以下行:

<rule-output name="//:main.out"/>
bazel查询的输出--output=xml:mylib
不包含
或任何其他有用的内容:

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<query version="2">
  <rule class="cc_library" location="/Users/mikemorearty/src/bazel/test1/BUILD:8:1" name="//:mylib">
    <string name="name" value="mylib"/>
    <list name="srcs">
      <label value="//:foo.c"/>
    </list>
    <rule-input name="//:foo.c"/>
    <rule-input name="//tools/defaults:crosstool"/>
    <rule-input name="@bazel_tools//tools/cpp:stl"/>
  </rule>
</query>

在两次运行
bazel
之间,输出路径应相同。也就是说,如果您构建
//path/to:target
,然后
bazel clean
并再次构建,它应该生成相同的文件。由于此输出文件是常量,因此可以运行

ls "$(bazel info bazel-genfiles)/main.out"
我相信这将为您提供一个参考,一旦构建发生,该文件将在何处创建(它不会为您构建)

如果您希望从目标文件转换为依赖于您正在运行的
规则的文件名*
。例如,在中,输出路径取决于
go\u库
目标的参数。UGo团队最近为他们的项目记录了规则


一般来说,二进制输出路径在不同版本之间应该是稳定的,并且您可以依赖它们,而不会有太大的差异。然而,在我的经验中,这个问题通常是一个迹象,你应该考虑把以前的外部过程的Bazel作为一个GeNeTror或自定义规则。例如,我以前使用这个技巧来组装一个NPM包,但现在我完成了整个工作,并且有一个生成.tar的目标,我想上传到NPM。也许您可以继续介绍一些您感兴趣的具体内容,我们也许可以通过一个不依赖于外部系统的解决方案来了解Bazel构建路径。

您可以使用来查询此信息 动作图

这里有一个稍微丰富一点的示例,其中有一个数据库中的两个输出文件 一般规则:

数据并不完全在一个地方,但请注意:

  • ID为
    2
    3
    的工件对应于我们的两个期望值 输出文件,并将这些工件的输出位置列为 相对于工作区根目录的磁盘上文件的路径
  • 目标ID为
    0
    工件
    条目与工件关联 IDs
    2
    3
    ;及
  • ID为
    “0”
    目标
    条目与
    /:main
    标签
考虑到这种简单的结构,我们可以轻松地编写一个脚本来 列出与提供的标签对应的所有输出文件。我找不到合适的工作 直接依赖Bazel对
分析.proto
或其 来自外部存储库的语言绑定,因此您可以修补 将以下脚本插入
bazelbuild/bazel
存储库本身:

工具/列表输出/列表输出.py

#Bazel作者版权所有。版权所有。
#
#根据Apache许可证2.0版(以下简称“许可证”)获得许可;
#除非遵守许可证,否则不得使用此文件。
#您可以通过以下方式获得许可证副本:
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
#除非适用法律要求或书面同意,软件
#根据许可证进行的分发是按“原样”进行分发的,
#无任何明示或暗示的保证或条件。
#请参阅许可证以了解管理权限和权限的特定语言
#许可证下的限制。
r“”解析'aquery'结果以列出为目标创建的输出。
将此二进制代码与'bazel aquery'结合使用,以确定
磁盘上用于输出目标文件的路径。
用法示例:首先,查询所选目标的动作图
要分析:
bazel aquery//path/to:target--output=textproto>/tmp/aquery\u结果
然后,从Bazel存储库:
bazel运行//工具/列表输出--\
--查询结果/tmp/查询结果\
--标签//路径/到:目标\
;
这将打印由给定的
目标,比如:
bazel out/k8 fastbuild/foo.genfile
bazel out/k8 fastbuild/bar.genfile
如果提供的标签未出现在输出图形中,则会出现错误
被抚养。
"""
从未来导入绝对导入
来自未来进口部
来自未来导入打印功能
导入系统
从absl导入应用程序
从absl导入标志
从google.protobuf导入文本\u格式
从src.main.protobuf导入分析\u pb2
flags.DEFINE_字符串(
“结果”,
没有一个
“包含`bazel aquery…--output=textproto`.结果的文件的路径”,
)
flags.DEFINE_字符串(
“标签”,
没有一个
“要打印其输出的标签。”,
)
def die(消息):
sys.stderr.write(“致命:%s\n”%(消息,))
系统出口(1)
def干管(未使用的_argv):
如果flags.flags.aquery_结果为无:
raise app.UsageError(“缺少“---aquery\u result`argument.”)
如果flags.flags.label为无:
raise app.UsageError(“缺少“---label`argument.”)
如果flags.flags.aquery_结果==“-”:
aquery_result=sys.stdin.read()
其他:
打开(flags.flags.aquery_result)作为填充:
aquery_result=infle.read()
label=flags.flags.label
action\u graph\u container=analysis\u pb2.ActionGraphContainer()
文本
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<query version="2">
  <rule class="cc_library" location="/Users/mikemorearty/src/bazel/test1/BUILD:8:1" name="//:mylib">
    <string name="name" value="mylib"/>
    <list name="srcs">
      <label value="//:foo.c"/>
    </list>
    <rule-input name="//:foo.c"/>
    <rule-input name="//tools/defaults:crosstool"/>
    <rule-input name="@bazel_tools//tools/cpp:stl"/>
  </rule>
</query>
ls "$(bazel info bazel-genfiles)/main.out"
$ ls
BUILD  main.in  WORKSPACE
$ cat WORKSPACE
$ cat BUILD
genrule(
    name = "main",
    srcs = ["main.in"],
    outs = ["main.o1", "main.o2"],
    cmd = "cp $< $(location main.o1); cp $< $(location main.o2)",
)
$ cat main.in
hello
$ bazel aquery //:main --output=textproto >aquery_result 2>/dev/null
$ cat aquery_result
artifacts {
  id: "0"
  exec_path: "main.in"
}
artifacts {
  id: "1"
  exec_path: "external/bazel_tools/tools/genrule/genrule-setup.sh"
}
artifacts {
  id: "2"
  exec_path: "bazel-out/k8-fastbuild/genfiles/main.o1"
}
artifacts {
  id: "3"
  exec_path: "bazel-out/k8-fastbuild/genfiles/main.o2"
}
actions {
  target_id: "0"
  action_key: "dd7fd759bbecce118a399c6ce7b0c4aa"
  mnemonic: "Genrule"
  configuration_id: "0"
  arguments: "/bin/bash"
  arguments: "-c"
  arguments: "source external/bazel_tools/tools/genrule/genrule-setup.sh; cp main.in bazel-out/k8-fastbuild/genfiles/main.o1; cp main.in bazel-out/k8-fastbuild/genfiles/main.o2"
  input_dep_set_ids: "0"
  output_ids: "2"
  output_ids: "3"
}
targets {
  id: "0"
  label: "//:main"
  rule_class_id: "0"
}
dep_set_of_files {
  id: "0"
  direct_artifact_ids: "0"
  direct_artifact_ids: "1"
}
configuration {
  id: "0"
  mnemonic: "k8-fastbuild"
  platform_name: "k8"
}
rule_classes {
  id: "0"
  name: "genrule"
}