Bazel: how to get the path of a binary that I built along a bazel test

Issue

I’m writing a go test with bazel. The test will build a binary first, and mount the binary to a docker container. So I need to know the path of the binary I built.

The file system structure is like this:

The dir structure looks like the following:

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

where I’d like to build a go binary with go files at my_tool dir.

From my previous question’s answer, I got to know that I can use the data entry of in go_test from some/of/my/path/BUILD.bazel to build the binary:

go_test(
    name = "my_test",
    srcs = ["my_test.go"],
    data = glob(["testdata/**"]) + [
        "//some/of/my/path/my_tool:my_tool",
    ],
    gotags = ["my_test"],
    deps = [
        "//pkg/util/contextutil",
        "//pkg/util/log",
    ...
    ],
)

which did build the go binary for my_tool. But now the question is, how do I know where is the built binary of my_tool in my_test.go?

In my_test.go, I need to write something like this:

package my_lucky_test

...

pathForMyTool := some_path
hostConfig := container.HostConfig{
Binds := []string {""%s/my_tool-bin:/workding-dir/my_tool-bin", pathForMyTool"}
}

My question is how can I get the absolute path of "my_tool-bin"?

Solution

Simply run;

bazel build //some/of/my/path:my_test

It should print out the path of the binary to stdout.

As an alternative to your current approach might I suggest that you make use of bazelbuild/rules_docker#go_image which is a Bazel aware method for building containers.

EDIT: OP has clarified the question, though I am leaving the original answer above as others may find it useful.

When you bundle a binary/test with some data, the files under the data attribute become a set of ‘runfiles’. There are various libraries in each language for resolving runfiles. For golang you’ll want to use the bazel pkg in rules_go, to resolve your runfiles. e.g.

go_test(
    name = "my_test",
    srcs = ["my_test.go"],
    data = glob(["testdata/**"]) + [
        "//some/of/my/path/my_tool:my_tool",
    ],
    gotags = ["my_test"],
    deps = [
        "//pkg/util/contextutil",
        "//pkg/util/log",
        # NEW dep
        "@rules_go//rules_go/go/tools/bazel",
    ...
    ],
)

Your my_test.go;

package my_lucky_test

# NEW
import(
    "github.com/bazelbuild/rules_go/go/tools/bazel"
)

#...

pathForMyTool, ok := bazel.FindBinary("some/of/my/path/my_tool", "my_tool")
if !ok {
    # Error handling
}
hostConfig := container.HostConfig{
    Binds := []string {""%s/my_tool-bin:/workding-dir/my_tool-bin", pathForMyTool}
}

Answered By – silvergasp

Answer Checked By – David Marino (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.