如何使bazel"sh_binary"目标依赖于其他二进制目标



我已经设置了bazel来构建许多CLI工具,用于执行各种数据库维护任务。每一个都是一个py_binarycc_binary目标,从命令行调用,并带有某个数据文件的路径:它处理该文件并将结果存储在数据库中。

现在,我需要创建一个包含数据文件和shell脚本的依赖包,这些脚本调用这些CLI工具来执行特定于应用程序的数据库操作。

然而,似乎没有办法依赖于仅包含sh_binary目标和数据文件的新包中的现有py_binarycc_binary目标。尝试这样做会导致如下错误:

ERROR: /workspace/shbin/BUILD.bazel:5:12: in deps attribute of sh_binary rule //shbin:run: py_binary rule '//pybin:counter' is misplaced here (expected sh_library)

有没有一种方法可以使用sh_binary从shell脚本调用/依赖现有的bazel二进制目标?

我在这里实现了一个完整的示例:https://github.com/psigen/bazel-mixed-binaries


备注:

我不能用py_librarycc_library代替py_binarycc_binary。这是因为(a(我需要调用这两种语言的混合物来处理我的数据文件,而

我也无法将所有数据文件放入CLI工具包中——有多个特定于应用程序的包,它们不能混合使用。

您可以创建一个genrule来作为构建的一部分运行这些工具,也可以通过data属性创建一个依赖于这些工具的sh_binary并运行它们。

genrule方法

这是一种更简单的方法,可以让您在构建过程中运行这些工具。

genrule(
name = "foo",
tools = [
"//tool_a:py",
"//tool_b:cc",
],
srcs = [
"//source:file1",
":file2",
],
outs = [
"output_file1",
"output_file2",
],
cmd = "$(location //tool_a:py) --input=$(location //source:file1) --output=$(location output_file1) && $(location //tool_b:cc) < $(location :file2) > $(location output_file2)",
)

sh_binary方法

这更复杂,但允许您将sh_binary作为构建的一部分(如果它在genrule.tools中,类似于前面的方法(或在构建之后(在bazel-bin下(运行。

sh_binary中,数据必须取决于工具:

sh_binary(
name = "foo",
srcs = ["my_shbin.sh"],
data = [
"//tool_a:py",
"//tool_b:cc",
],
)

然后,在sh_binary中,您必须使用Bazel中内置的所谓"Bash runfiles库"来查找二进制文件的运行时路径。该库的文档在其源文件中。

想法是:

  1. sh_binary必须取决于特定的目标
  2. 您必须将一些样板代码复制粘贴到shbinary的顶部(原因在这里描述(
  3. 然后可以使用rlocation函数查找二进制文件的运行时路径

例如,您的my_shbin.sh可能如下所示:

#!/bin/bash
# --- begin runfiles.bash initialization ---
...
# --- end runfiles.bash initialization ---
path=$(rlocation "__main__/tool_a/py")
if [[ ! -f "${path:-}" ]]; then
echo >&2 "ERROR: could not look up the Python tool path"
exit 1
fi
$path --input=$1 --output=$2

rlocation path参数中的__main__是工作区的名称。由于WORKSPACE文件中没有定义工作区名称的"工作区"规则,Bazel将使用默认的工作区名称,即__main__

一个干净的方法是使用args$(location):

BUILD:的内容

py_binary(
name = "counter",
srcs = ["counter.py"],
main = "counter.py",
)
sh_binary(
name = "run",
srcs = ["run.sh"],
data = [":counter"],
args = ["$(location :counter)"],
)

counter.py(您的工具(的内容:

print("This is the counter tool.")

run.sh(您的bash脚本(的内容:

#!/bin/bash
set -eEuo pipefail
counter="$1"
shift
echo "This is the bash script, about to call the counter tool."
"$counter"

这里有一个演示显示bash脚本调用Python工具:

$ bazel run //example:run 2>/dev/null
This is the bash script, about to call the counter tool.
This is the counter tool.

同样值得一提的是(文档中的(这个注释:

当您在bazel之外运行目标时(例如,通过手动执行bazel-bin/中的二进制文件(,不会传递参数。

对我来说,一种更简单的方法是在data部分中添加cc_binary作为依赖项。在prefix/BUILD

cc_binary(name = "foo", ...)
sh_test(name = "foo_test", srcs = ["foo_test.sh"], data = [":foo"])

foo_test.sh中,工作目录不同,因此您需要为二进制找到正确的prefix

#! /usr/bin/env bash
executable=prefix/foo
$executable ...

相关内容

最新更新