首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使bazel `sh_binary`目标依赖于其他二进制目标?

如何使bazel `sh_binary`目标依赖于其他二进制目标?
EN

Stack Overflow用户
提问于 2018-11-25 23:19:01
回答 3查看 13.1K关注 0票数 9

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

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

但是,似乎没有一种方法可以依赖只包含py_binary目标和数据文件的新包中现有的sh_binarycc_binary目标。试图这样做会导致一个错误,例如:

代码语言:javascript
复制
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)我需要调用这两种语言的混合来处理我的数据文件和(b)这些工具来自上游存储库,它们已经被设计为CLI工具。

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-11-26 12:50:30

您可以创建一个派生规则作为构建的一部分来运行这些工具,或者通过data属性创建一个依赖于这些工具的data并运行它们。

广义方法

这是一种更简单的方法,并允许您将这些工具作为构建的一部分来运行。

代码语言:javascript
复制
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中,您必须依赖于以下工具:

代码语言:javascript
复制
sh_binary(
    name = "foo",
    srcs = ["my_shbin.sh"],
    data = [
        "//tool_a:py",
        "//tool_b:cc",
    ],
)

然后,在sh_binary中,您必须使用内置于Bazel中的所谓“binaries库”来查找二进制文件的运行时路径。这个库的文档是在源文件中

这样做的目的是:

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

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

代码语言:javascript
复制
#!/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

重新定位路径参数中的__main__是工作区的名称。由于您的WORKSPACE文件中没有定义工作区名称的“工作区”规则,所以Bazel将使用默认的工作区名称,即__main__

票数 19
EN

Stack Overflow用户

发布于 2019-02-06 13:59:51

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

代码语言:javascript
复制
cc_binary(name = "foo", ...)
sh_test(name = "foo_test", srcs = ["foo_test.sh"], data = [":foo"])

foo_test.sh内部,工作目录是不同的,因此需要为二进制文件找到正确的prefix

代码语言:javascript
复制
#! /usr/bin/env bash

executable=prefix/foo

$executable ...
票数 5
EN

Stack Overflow用户

发布于 2020-11-15 05:18:49

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

BUILD含量

代码语言:javascript
复制
py_binary(
    name = "counter",
    srcs = ["counter.py"],
    main = "counter.py",
)

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

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

代码语言:javascript
复制
print("This is the counter tool.")

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

代码语言:javascript
复制
#!/bin/bash
set -eEuo pipefail

counter="$1"
shift

echo "This is the bash script, about to call the counter tool."
"$counter"

下面是一个演示,展示了调用Python工具的bash脚本:

代码语言:javascript
复制
$ 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/中的二进制文件)。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53472993

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档