Use `bazel query` inside a build file - bazel

I am using Bazel with Golang, but the question is no Go-specific. I have a common go directory structure:
cmd/
├── mycommand/
│ ├── BUILD.bazel
│ ├── main.go
│ └── somefolder
│ └── other.go
├── othercommand/
│ ├── BUILD.bazel
│ └── main.go
pkg/
└── mypackage/
├── BUILD.bazel
└── init.go
BUILD.bazel
WORKSPACE
... and I'd like to reference targets under the cmd folder. I have a bazel query that will give me the list of those targets:
bazel query 'kind("go_binary", deps(//cmd/...))'
//cmd/mycommand:mycommand
//cmd/othercommand:othercommand
The question: How can I include this query in a BUILD.bazel file, something like the following:
pkg_tar(
name = "release",
srcs = kind("go_binary", deps(//cmd/...)),
mode = "0644",
)
...which gives
ERROR: /some/path/BUILD.bazel:10:12: name 'kind' is not defined
ERROR: /some/path/BUILD.bazel:10:30: name 'deps' is not defined

Build targets need to be statically referenced in BUILD files, so embedding queries as inputs to rule attributes does not work.
However, there are a couple of ways to dynamically generate targets to be used statically in the BUILD files:
1) Run a tool that generates a BUILD file before running Bazel. rules_go's Gazelle is a good example.
2) Write a repository rule that invokes non-hermetic tools to dynamically generate targets that your BUILD files can depend on.
Note that you may come across the genquery rule, which does let you perform a query on targets, but the rule outputs to a file during Bazel's execution phase, and not a Starlark list that can ingested into other rules' attributes during the analysis phase, which happens before the execution phase.

Related

BAZEL: Query all targets in bazel rule

Here is code structure
| //base_folder
├── file0.txt
├── BUILD
├── folder1
| ├── BUILD
| ├── file1
├── folder2
| ├── BUILD
| ├── file2
I'd like to know all the files or target information to do a further process.
I can use bazel query command but I cannot get them in the BAZEL rule implement.
bazel query 'kind(cc_library, //...)'
I tried genrule to run command. But "bazel query" cannot be used in the bazel-bin folder.
I tried genquery, but "//..." is not allowed in genquery.
Is there way I can get the target information in BAZEL rule?
bazel query is used to discover targets within a bazel workspace.
You can try:
If only interested in rules, then:
bazel query 'kind(.rule, //some/package:)'
//some/package:* could be substituted for any valid label expression, eg including all descending packages, //some/package/...
Reference : bazel query

go mod unable to find modules

I'm trying to build a Docker image using a go compiled binary as the ENTRYPOINT but I'm unable to compile the binary because the go mod is unable to find one of the required files.
the project structure looks like this:
editor/
├── container
│ ├── Dockerfile
│ └── src
│ ├── install-browsers.sh
│ ├── selenium-server-standalone-3.141.59.jar
│ └── webCopy
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── copier
│ ├── copier.go
│ ├── internal
│ │ └── utils.go
│ └── scripts
│ └── load.go
└── resource
└── handler.go
The file I'm trying to compile is webCopy/main.go
Inside that file I need to import the module editor/copier
The path to the editor module is:
bitbucket.org/backend/editor
which is inside the GOPATH
The error the go mod tidy gives me is:
go: finding module for package bitbucket.org/mvps/backend/editor/copier
bitbucket.org/backend/editor/container/src/webCopy imports
bitbucket.org/backend/editor/copier: cannot find module providing package bitbucket.org/mvps/backend/editor/copier: reading https://api.bitbucket.org/2.0/repositories/mvps/backend?fields=scm: 404 Not Found
I really don't want to mix the copier module inside the src of the container, the reason being I feel the submodules to the main should be separated, yet inside the editor module.
Furthermore, I'm using go.mod as a way to get a clean image by compiling main.go and using the binary to create a new clean artifact, so I would like to have the go.mod and go.sum files inside editor/container/src/webCopy/
btw. I have checked the package names and everything is properly named.
FYI if you are using a go modules build - you are no longer using GOPATH - so that is not the issue.
If you want a custom build - and not have to create laborious git key access to repo's from within a docker build - you can leverage the replace directive in go.mod
So add to .../webCopy/go.mod the following line:
replace bitbucket.org/backend/editor/copier => ../../../copier/
this will instruct the go build to use this relative path (instead of a direct https download)

Can I depend on all the Bazel targets matching a pattern, without listing them individually?

I have a directory structure that looks like this:
some-root/
└── my-stuff/
├── BUILD
├── foo/
│ └── BUILD
├── bar/
│ └── BUILD
└── baz/
└── BUILD
I'd like to have a target like //some-root/my-stuff:update which runs all of //some-root/my-stuff/foo:update, //some-root/my-stuff/bar:update, //some-root/my-stuff/baz:update.
I can do this by listing each target as a dependency. However, if I have many of these and I want to be able to add more it becomes a pain (it's easy to add a bunch of subdirectories and miss adding one to the parent BUILD file).
Is there a way to do a wildcard labels or otherwise discover labels from file paths? I'm able to do bazel test //some-root/my-stuff/... to run all tests under a path, but I can't seem to use that pattern inside of a BUILD file and what I'd want is more like bazel run //some-root/my-stuff/...:update which doesn't work either.
You can get all labels with the name update from the command line:
bazel query "attr(name, '^update$', //...)"
and take the output of query and manually edit your dependencies.
But unfortunately you can not put this into a genquery rule (which would generate the list of targets to depend on), because
queries containing wildcard target specifications (e.g. //pkg:* or //pkg:all) are not allowed

Derive Bazel label from source file path

Given a path to a source file within the workspace, how can I derive the label that Bazel uses to refer to the file. This seems to depend on what packages exist. For example, if I have this structure:
.
├── BUILD
├── WORKSPACE
└── src
└── bar
└── foo.go
Then the label for src/bar/foo.go is //src/bar/foo.go. However, if I have this structure:
.
├── BUILD
├── WORKSPACE
└── src
├── BUILD
└── bar
├── BUILD
└── foo.go
Then the label for the same file is //src/bar:foo.go.
Is there a way to get Bazel to tell me what the label that identifies a file is, or must I to derive it based on the presence/absence of BUILD files at various levels of the workspace tree?
If a valid label exists for path/to/file.txt, running bazel query path/to/file.txt will return you the absolute label.
e.g. for the first example:
$ bazel query src/bar/foo.go
//:src/bar/foo.go
and for the second example:
$ bazel query src/bar/foo.go
//src/bar:foo.go
If the file is not referenced in any rule (filegroup, exports_files, etc) in any BUILD file, it will not have a label.

How do I derive the BUILD file from a produced target?

Our monolith repo looks something like this:
├── bin
└── ...
└── source
├── foo
├── BUILD
└── ...
└── bar
├── BUILD
└── ...
└── ...
We have thousands of BUILD files producing thousands of targets into the bin directory.
Now that we have all these compiled binaries in the bin directory, it would be nice to have a method for deriving which BUILD file put it there.
I don't want to hand-write a tool that recursively parses all of the BUILD file's build rules and prints the answer. Is this something that can be achieved with bazel query?
Most of our build rules are pretty typical:
cc_binary(
name="foo",
...
)
py_binary(
name="bar.py",
...
)
The end goal would be to run something like:
where-source ./bin/foo
./source/foo/BUILD created ./bin/foo
If you trim off the bin/ (I assume you're using --symlink_prefix?), you can use bazel query:
# Where did bin/foo/bar/baz get defined?
$ bazel query foo/bar/baz
//foo/bar:baz
Or, to get detailed info about the location:
$ bazel query --output=location foo/bar/baz
/home/kchodorow/gitroot/proj/source/foo/bar/BUILD:3:1: go_binary rule //foo/bar:baz
Or, to get the definition of the target itself:
$ bazel query --output=build foo/bar/baz
go_binary(
name = "baz",
srcs = ["//foo/bar/baz.go"],
)
See What build rule contains file src/main/java/com/example/cache/LRUCache.java as a source? and the rest of that page for more examples of bazel query.

Resources