Bazel:如何导入/构建一个 go_binary 用于 go_test。

huangapple go评论81阅读模式
英文:

Bazel: how to import/build a go_binary for a go_test

问题

我正在使用bazel在我的CI系统上运行一个go测试。这个go测试需要使用从另一个go文件构建的辅助二进制文件。

目录结构如下所示:

some/of/my/path
├── BUILD.bazel
├── my_utils.go
├── my_test.go
└── my_tool
    ├── BUILD.bazel
    └── my_tool.go

也就是说,my_test.go中的代码将使用从my_tool目录构建的可执行二进制文件。

在非bazel情况下,我可以使用go build ./mytool来获取my_test.go所需的可执行二进制文件。为了适应bazel环境,我在bazel文件中编写了以下内容:

  • some/of/my/path/BUILD.bazel中:
load("io_bazel_rules_go/go:def.bzl", "go_library", "go_test")

go_library(
    name = "testutils",
    srcs = ["my_utils.go"],
    importpath = "some/of/my/path",
    visibility = ["//visibility:public"],
    deps = [
        "@org_golang_x_net//context",
        ... (其他依赖项与此无关)
    ],
)

go_test(
    name = "my_test",
    size = "enormous",
    srcs = ["mytest.go"],
    embed = [":testutils"],
    deps = [
        "//some/of/my/path/my_tool:my_tool",
    ],
)
  • some/of/my/path/my_tool/BUILD.bazel中:
load("io_bazel_rules_go/go:def.bzl", "go_binary", "go_library")

go_library(
    name = "my_tool_lib",
    srcs = ["my_tool.go"],
    importpath = "some/of/my/path/my_tool",
    visibility = ["//visibility:private"],
    deps = ["some dependency"],
)

go_binary(
    name = "my_tool",
    embed = [":my_tool_lib"],
    visibility = ["//visibility:public"],
)

因此,当我运行bazel run时,它将构建my_tool的go二进制文件,供go测试my_test使用(请参阅go测试的deps字段)。

然而,在CI中,我遇到了以下错误:

ERROR: /home/agent/work/.go/src/some/of/my/path/BUILD.bazel:20:8: in go_test rule //some/of/my/path:my_test:
Traceback (most recent call last):
  File "/home/agent/.cache/bazel/_bazel_agent/40f5e2a2e18a7cdb4cd075f919d8072b/external/io_bazel_rules_go/go/private/rules/test.bzl", line 66, column 43, in _go_test_impl
    internal_source = go.library_to_source(go, ctx.attr, internal_library, ctx.coverage_instrumented())
  File "/home/agent/.cache/bazel/_bazel_agent/40f5e2a2e18a7cdb4cd075f919d8072b/external/io_bazel_rules_go/go/private/context.bzl", line 247, column 26, in _library_to_source
    _check_binary_dep(go, dep, "deps")
  File "/home/agent/.cache/bazel/_bazel_agent/40f5e2a2e18a7cdb4cd075f919d8072b/external/io_bazel_rules_go/go/private/context.bzl", line 295, column 13, in _check_binary_dep
    fail("rule {rule} depends on executable {dep} via {edge}. This is not safe for cross-compilation. Depend on go_library instead.".format(
Error in fail: rule //some/of/my/path:my_test depends on executable //some/of/my/path/my_tool:my_tool via deps. This is not safe for cross-compilation. Depend on go_library instead.
ERROR: Analysis of target '//some/of/my/path:my_test' failed; build aborted: Analysis of target '//some/of/my/path:my_test' failed
INFO: Elapsed time: 79.552s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (595 packages loaded, 12182 targets configured)
ERROR: Build failed. Not running target
FAILED: Build did NOT complete successfully (595 packages loaded, 12182 targets configured)
Process exited with code 1

但是我的目标是使用这个二进制文件。我应该如何更改配置以实现这一目标?

英文:

I'm using bazel to run a go test on my CI system. The go test will need to use a helper binary built from another go file.

The dir structure looks like the following:


    some/of/my/path
    ├── BUILD.bazel
    ├── my_utils.go
    ├── my_test.go
    └── my_tool
        ├── BUILD.bazel
        └── my_tool.go

I.e. the code in my_test.go is going to use the executable binary built from dir my_tool.

In a non-bazel case, I can just go build ./mytool to get the executable binary that my_test.go needs. To accommodate this the bazel world, I write the following in the bazel files:

  • In some/of/my/path/BUILD.bazel:

    load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
    
    go_library(
        name = "testutils",
        srcs = ["my_utils.go"],
        importpath = "some/of/my/path",
        visibility = ["//visibility:public"],
        deps = [
            "@org_golang_x_net//context",
            ... (some other dependencies, not related)
        ],
    )
    
    go_test(
        name = "my_test",
        size = "enormous",
        srcs = ["mytest.go"],
        embed = [":testutils"],
        deps = [
            "//some/of/my/path/my_tool:my_tool",
        ],
    )

  • In some/of/my/path/my_tool/BUILD.bazel

    load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
    
    go_library(
        name = "my_tool_lib",
        srcs = ["my_tool.go"],
        importpath = "some/of/my/path/my_tool",
        visibility = ["//visibility:private"],
        deps = ["some dependency"],
    )
    
    go_binary(
        name = "my_tool",
        embed = [":my_tool_lib"],
        visibility = ["//visibility:public"],
    )

So the idea is when I hit bazel run, it will build the my_tool go binary, which the go test my_test can use (see the deps field of the go test).

While in the CI I hit this error:


    ERROR: /home/agent/work/.go/src/some/of/my/path/BUILD.bazel:20:8: in go_test rule //some/of/my/path:my_test:
    Traceback (most recent call last):
      File "/home/agent/.cache/bazel/_bazel_agent/40f5e2a2e18a7cdb4cd075f919d8072b/external/io_bazel_rules_go/go/private/rules/test.bzl", line 66, column 43, in _go_test_impl
        internal_source = go.library_to_source(go, ctx.attr, internal_library, ctx.coverage_instrumented())
      File "/home/agent/.cache/bazel/_bazel_agent/40f5e2a2e18a7cdb4cd075f919d8072b/external/io_bazel_rules_go/go/private/context.bzl", line 247, column 26, in _library_to_source
        _check_binary_dep(go, dep, "deps")
      File "/home/agent/.cache/bazel/_bazel_agent/40f5e2a2e18a7cdb4cd075f919d8072b/external/io_bazel_rules_go/go/private/context.bzl", line 295, column 13, in _check_binary_dep
        fail("rule {rule} depends on executable {dep} via {edge}. This is not safe for cross-compilation. Depend on go_library instead.".format(
    Error in fail: rule //some/of/my/path:my_test depends on executable //some/of/my/path/my_tool:my_tool via deps. This is not safe for cross-compilation. Depend on go_library instead.
    ERROR: Analysis of target '//some/of/my/path:my_test' failed; build aborted: Analysis of target '//some/of/my/path:my_test' failed
    INFO: Elapsed time: 79.552s
    INFO: 0 processes.
    FAILED: Build did NOT complete successfully (595 packages loaded, 12182 targets configured)
    ERROR: Build failed. Not running target
    FAILED: Build did NOT complete successfully (595 packages loaded, 12182 targets configured)
    Process exited with code 1

But my goal is to use the binary. How should I change the configs to achieve that?

答案1

得分: 1

你需要使用data而不是depsdeps用于链接到二进制文件中的内容,而data用于二进制文件在运行时使用的内容。

一旦你的二进制文件在data中,可以使用runfiles.go来运行它。将@io_bazel_rules_go//go/tools/bazel:go_default_library添加到deps中(这是你想要链接的库),然后使用FindBinary来找到路径。

英文:

You want data, not deps. deps is for things linked into a binary, data is for things the binary uses at runtime.

Once your binary is in data, use runfiles.go to run it. Add @io_bazel_rules_go//go/tools/bazel:go_default_library to deps (it's a library you want linked in), and then use FindBinary to find the path.

huangapple
  • 本文由 发表于 2022年1月23日 08:28:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/70818261.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定