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

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.

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

Use `bazel query` inside a build file

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.

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

How can I execute *.class file in any folder?

this is my project tree:
.
├── README.md
├── package.json
└── src
└── xyz
└── pagenote
├── HandlerTestA.class
├── HandlerTestB.class
├── Main.class
If I am in the folder src, I can execute Main.class by
src# java xyz.pagenote.Main
It works, but I want to execute it in the current folder, I have tried
.# java ./src/xyz/pagenote/Main
It doesn't work, what can I do?
For the command java, the default classpath is the current working directory (.).
So when executing xyz.pagenote.Main from the src directory, and the classpath flag is not specified, java will look for the class file in src/xyz/pagenote.class
So to execute from a directory other than src, you have to specify the classpath like:
$ java -classpath /path/to/src xyz.pagenote.Main
I find the solution, we can point a classpath for java:
.# java -classpath ./src xyz.pagenote.Main
this command will let java execute it right

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.

Resources