Selectively build targets based on platform

2,488 views
Skip to first unread message

sgr...@google.com

unread,
Sep 7, 2017, 7:07:04 PM9/7/17
to bazel-discuss
My project has parts that build on Linux, parts that build on Windows, and parts that build on both. I am looking for a way to ignore Windows-only targets when building on Linux and vice-versa. I have a config_setting for each platform, so to pass different compiler options or have different srcs I can simply use a select. I can make Bazel ignore cc_library rules by wrapping all srcs, hdrs, and deps in select statements so that on the unsupported platform they are all blank. However, when I try it for cc_binary rules it fails during linking with an error about main.

Is there some annotation or usage of select that will allow me to mark a rule to not build (or only build) on a certain platform?

Austin Schuh

unread,
Sep 11, 2017, 7:53:32 PM9/11/17
to sgr...@google.com, bazel-discuss
We have been tagging targets with armhf-debian-only, etc, and using --build_tag_filters and --test_tag_filters to filter them out.  We are in the process of automatically adding those tag filters to our //tools/bazel script so it's transparent to the user rather than requiring them to run //tools/bazel-excludes

Austin

On Thu, Sep 7, 2017 at 4:07 PM sgreens via bazel-discuss <bazel-...@googlegroups.com> wrote:
My project has parts that build on Linux, parts that build on Windows, and parts that build on both. I am looking for a way to ignore Windows-only targets when building on Linux and vice-versa. I have a config_setting for each platform, so to pass different compiler options or have different srcs I can simply use a select. I can make Bazel ignore cc_library rules by wrapping all srcs, hdrs, and deps in select statements so that on the unsupported platform they are all blank. However, when I try it for cc_binary rules it fails during linking with an error about main.

Is there some annotation or usage of select that will allow me to mark a rule to not build (or only build) on a certain platform?

--
You received this message because you are subscribed to the Google Groups "bazel-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-discuss/1ea1febd-9d67-4191-8078-584453e6f90f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Greg Estren

unread,
Sep 14, 2017, 1:10:23 PM9/14/17
to bazel-discuss
We also have experimental support for automatically "skipping" incompatible targets when running bazel build //foo:all  (with no need for select). Check out --experimental_auto_cpu_environment_group. This was intended for skipping tests, and I'm not sure offhand what it does for simple binaries.

This approach wouldn't require you to remember custom flags at the command line. But it's opaque right now and would require a bit of investment to work for your use case.

About the linking error, can you just have a non-supported platform include a dummy_main.cc that does nothing, automatically crash dumps, or what not?

Ian Cottrell

unread,
Sep 14, 2017, 1:21:36 PM9/14/17
to Greg Estren, bazel-discuss
I generally do this by marking the rules as manual (so they don't match glob forms), and then having a non manual rule depend on them using select. I find this nicer because there is no special magic, no extra command line arguments, it's very easy to read and reason about.

Austin Schuh

unread,
Sep 14, 2017, 1:27:07 PM9/14/17
to Greg Estren, bazel-discuss
Oooh, that looks promising.  Do you have any examples, (even half baked)?  I'd love to clean what we have up.

Austin

Greg Estren

unread,
Sep 14, 2017, 2:51:27 PM9/14/17
to bazel-discuss
What this feature does is mix Bazel's (somewhat undocumented) constraint system with the target CPU. There are three steps:

  1. Define a set of environment rules defining the CPUs you care about:

    cpus/BUILD:
    environment(name = "x86")
    environment(name = "arm")
    environment_group(
        name = "cpus",
        environments = [":x86", ":arm"],
        defaults = [":x86"]
    )

  2. Tag your binaries you want to be CPU-specific:

    //myproject/BUILD:
    cc_binary(
        name = "x86only",
        srcs = ["x86main.cc"],
        restricted_to = ["//cpus:x86"]

  3. Add CPU skipping to your command line or .bazelrc:

    $ bazel build //myproject:all --experimental_auto_cpu_environment_group=//cpus:cpus

As I mentioned above, this was built specifically for tests. I'm not sure offhand if it works for binaries. Also, this checking is restricted just to CPU, which may or may not be what you want to filter on. Ultimately we should integrate this with Bazel's upcoming platform semantics (which builds on the concepts above) to provide as much granularity and flexibility as you want.

If you find this useful but it doesn't quite work, feel free to file issues and assign them to me.

sgr...@google.com

unread,
Sep 14, 2017, 7:02:22 PM9/14/17
to bazel-discuss
Thanks for all the replies!

Greg, I think I see what you mean by investment. It seems like in order to make a rule "restricted_to" a cpu, I'd need to mark every rule it depends on as "compatible_with" that cpu. I'm excited about the platform semantics effort, though.

Austin, are you using scripts to automatically change the build_tag_filters based on the platform you're building on? How do you do that?

Austin Schuh

unread,
Sep 14, 2017, 9:30:30 PM9/14/17
to sgr...@google.com, bazel-discuss
On Thu, Sep 14, 2017 at 4:02 PM sgreens via bazel-discuss <bazel-...@googlegroups.com> wrote:
Thanks for all the replies!

Greg, I think I see what you mean by investment. It seems like in order to make a rule "restricted_to" a cpu, I'd need to mark every rule it depends on as "compatible_with" that cpu. I'm excited about the platform semantics effort, though.

Austin, are you using scripts to automatically change the build_tag_filters based on the platform you're building on? How do you do that?

 Yes, we have a script which looks for -c, --cpu= and --compiler= and some --config= options and invokes bazel with --build_tag_filters and --test_tag_filters (and all the other flags).  This lets us also exclude targets when building with MSAN, ASAN, etc.

I'm gently pushing our guys to put that in //tools:bazel so that it gets added all the time automatically.  We used to do it with bazel query, which was a lot slower.

Thanks Greg.  I'm going to have to explore restricted_to.  That would be awesome.

Austin

matthew....@spacex.com

unread,
Sep 20, 2017, 10:22:47 PM9/20/17
to bazel-discuss
I've been trying to find a solution to this problem, too. The problem I ran into is that I have a couple configurations in bazel.rc that set build_tag_filter or test_tag_filter. Specifying it again separately based on the target platform conflicts, because you can't pass those flags multiple times and have them accumulate.

Full integration with the platform semantics would be awesome - it would let us be as specific as we want, without the clunky tag filters. I went ahead and opened https://github.com/bazelbuild/bazel/issues/3780 to capture that request.

Austin Schuh

unread,
Oct 12, 2017, 8:24:18 PM10/12/17
to Greg Estren, bazel-discuss
Greg,

On Thu, Sep 14, 2017 at 11:51 AM 'Greg Estren' via bazel-discuss <bazel-...@googlegroups.com> wrote:
What this feature does is mix Bazel's (somewhat undocumented) constraint system with the target CPU. There are three steps:

  1. Define a set of environment rules defining the CPUs you care about:

    cpus/BUILD:
    environment(name = "x86")
    environment(name = "arm")
    environment_group(
        name = "cpus",
        environments = [":x86", ":arm"],
        defaults = [":x86"]
    )

  2. Tag your binaries you want to be CPU-specific:

    //myproject/BUILD:
    cc_binary(
        name = "x86only",
        srcs = ["x86main.cc"],
        restricted_to = ["//cpus:x86"]

  3. Add CPU skipping to your command line or .bazelrc:

    $ bazel build //myproject:all --experimental_auto_cpu_environment_group=//cpus:cpus

As I mentioned above, this was built specifically for tests. I'm not sure offhand if it works for binaries. Also, this checking is restricted just to CPU, which may or may not be what you want to filter on. Ultimately we should integrate this with Bazel's upcoming platform semantics (which builds on the concepts above) to provide as much granularity and flexibility as you want.

If you find this useful but it doesn't quite work, feel free to file issues and assign them to me.

The 0.6.0 upgrade was more painful than expected so this took longer than I wanted.

There are a couple error messages that are pretty poor, but it works!!!  (I'll file some bugs against you per your request.)  I was able to restrict our arm only targets properly.  I'm going to have to roll this out to some of our other repos too now.  I'm now really looking forwards to the upcoming platform semantics, which should let us get rid of our wrapper scripts if I'm reading it right.

Austin

Greg Estren

unread,
Oct 17, 2017, 5:09:09 PM10/17/17
to Austin Schuh, bazel-discuss
Happy to hear this is working for you, Austin. And thanks for the bug report!
Reply all
Reply to author
Forward
0 new messages