What is a top-level target when building `//...` in Bazel? - bazel

According to the Bazel glossary:
A build target is top-level if it’s requested on the Bazel command
line. For example, if //:foo depends on //:bar, and bazel build //:foo
is called, then for this build, //:foo is top-level, and //:bar isn’t
top-level, although both targets will need to be built. An important
difference between top-level and non-top-level targets is that command
flags set on the Bazel command line (or via .bazelrc) will set the
configuration for top-level targets, but might be modified by a
transition for non-top-level targets.
However, if the user runs bazel build //... then are all targets considered top-level or none?
This is relevant to the remote caching option --remote_download_outputs

What is returned by the expansion of the * and ... wildcards is considered top-level.

Related

Configure bazel toolchain without modifying project/workspace

I have a Bazel project (the new tcmalloc) I'm trying to integrate into a typical GNU Make project that uses it's own build of compiler/libc++. The goal is to not fork the upstream project.
If I pass all the C++ options correctly to bazel (one set of which is -nostdinc++ -I<path to libc++>), Bazel is uhappy The include path '/home/vlovich/myproject/deps/toolchain/libc++/trunk/include' references a path outside of the execution root. (tcmalloc is a git submodule sibling # deps/tcmalloc). It's possible to get this "working" by giving Bazel a custom script to invoke as the compiler that injects those flags so that Bazel never sees them. However, I'd like to just define a toolchain to work properly.
I've read all the documentation I could find on this topic but it's not clear to me how to glue all these docs together.
Specifically not really clear where I should place the toolchain definition files or how to tell Bazel to find those definitions. Is there a way to give bazel a directory that it uses to find toolchain definitions? Am I expected to create a top-level WORKSPACE # /home/vlovich/myproject & register tcmalloc and my toolchain there, & then invoke bazel from /home/vlovich/myproject instead of /home/vlovich/myproject/deps/tcmalloc?
Toolchain support is rather complicated, and it is hard to understand, if you are not a bazel maintainer.
You can use CC and CXX environment variables to set a different compiler like: CC=your_c_compiler CXX=your_c++_compiler bazel build .... You can write your own custom script wrapper which will act as a normal C++ compiler
That -I<path to libc++> does not work, because all normal include paths have to be defined in srcs attribute or via dependencies indicated by the deps attribute. For system-wide dependencies use -isystem Read more about it https://stackoverflow.com/a/44061589/4638604

Change cc_binary link type without modyfing a target

I want to build my cc_binary target in a dynamic mode linkstatic=False, but without modifying a target definition.
My use case: I want to build static binaries in the CI, but for development purposes I want to use dynamic linking to speedup incremental builds. Probably some flag in bazel build/test invocation would be the best
Check out the --dynamic_mode flag.

bazel WORKSPACE file not behaving as documented?

Consider the following hierarchy:
WORKSPACE
foo/
BUILD
foo.sh
bar/
BUILD
bar.sh
Where, e.g., foo/BUILD contains
sh_binary(
name = "foo",
srcs = ["foo.sh"],
)
and similarly for bar/BUILD. As expected, bazel cquery //... prints:
INFO: Analyzed 2 targets (0 packages loaded, 0 targets configured).
INFO: Found 2 targets...
//bar:bar (a5d130b)
//foo:foo (a5d130b)
According to https://docs.bazel.build/versions/master/build-ref.html, "Bazel ignores any directory trees in a workspace rooted at a subdirectory containing a WORKSPACE file (as they form another workspace)."
Therefore, if I touch bar/WORKSPACE, I should expect bar to no longer be part of my workspace, and its contents should be ignored by bazel. Why, then, do I still get the same query results?
$ ls bar
BUILD WORKSPACE bar.sh
$ bazel cquery //...
INFO: Analyzed 2 targets (0 packages loaded, 0 targets configured).
INFO: Found 2 targets...
//bar:bar (a5d130b)
//foo:foo (a5d130b)
Bazel version is 3.7.0.
I answered this in the slack thread the author created, but for posterity, the confusion here was due to the author's interpretation (and possibly poor verbiage) in the documentation.
A WORKSPACE file alone doesn't "instantiate" or "define" a wholly separate workspace, as the author of this question assumed -- as such, Bazel won't treat that subdirectory any differently from any other package. Instead, the workspace needs to be defined as an "external repository" -- that is to say, "external" to the parent workspace, not necessarily a repository whose source code lives somewhere else.
You can do this using local_repository like so:
WORKSPACE
local_repository(
name = "bar_workspace_name",
path = "bar",
)
I may be projecting an actual behavior of bazel into interpreting the intended meaning of the sentence when I suppose the "ignoring" it speaks of goes in the other direction not descending into nested directories, but crawling up towards root. Essentially...
If you have that bar/WORKSPACE file, it does not change the behavior when looking at it from bar/'s parent and //bar still appears as package in that workspace.
However, it impact the behavior should you run bazel with bar/ for its working directory. As it tries to find the workspace root it stops WORKSPACE therein bar/ becomes its own // in that case (and by extension its parent is not accessible as part of the same workspace).
Or in practical terms... try the same thing:
bazel cquery //...
but in bar:
(cd bar/ && bazel cquery //... )
Once with and once without bar/WORKSPACE.

How to specify "default" target labels when running bazel test

We're considering migrating to Bazel from Make. To make the transition easier I would like to have bazel test (no flags / options) run the current directory's tests, if any.
So instead of bazel test my_tests bazel test would find the current directory's BUILD file, find any *_test rules and run those.
If you want to do exactly as you said then you can use your own script.
When you run “bazel” it actually looks to see if there is a script named “bazel” under tools directory of the current workspace. So if you have an executable under “$workspace/tools/bazel” bazel will run that instead of the bazel binary itself.
This means you can write a script that checks if the only argument is “test” and if so calls “bazel-real test :all”
It can also check the exit code to see if there were no tests (it’s a specific error code) and return 0 instead
You can use the all target pattern to match all targets in the current package: bazel test :all
You can read more about it here: https://docs.bazel.build/versions/master/user-manual.html#target-patterns
Note however that if there are no test targets in the current package, bazel will give an error: "ERROR: No test targets were found, yet testing was requested.". In this case bazel will give an exit code of 4: https://docs.bazel.build/versions/master/user-manual.html#what-exit-code-will-i-get
I recommend creating a alias called bazel-test to bazel test :all.

Can I ignore some folder (containing bazel configuration) while building the project recursively?

For some reasons, practical or not, rxjs npm package stores BAZEL.build configuration in the package, so when I'm trying to build my project (which has node_modules folder) bazel tries automatically to build something that it's not supposed to build at all.
My question would be - what is canonical way of ignoring some specific folder while building bazel project recursively?
The only way to achieve what I'm looking for that I know of is to point to it explicitly in the command line
bazel build //... --deleted_packages=node_modules/rxjs/src (see user manual)
But I don't want to type this every time.
Bazel recently added a feature for ignoring folders (similar to gitignore).
Simply add node_modules to the .bazelignore file in the root of your project.
Yes, this is expressible as a bazel target pattern:
bazel build -- //... -//node_modules/rxjs/src/...
Full documentation is available at https://docs.bazel.build/versions/master/user-manual.html#target-patterns

Resources