Practical Bazel: Changing Behavior on Windows
Practical Bazel bazel windows
Published: 2020-11-05
Practical Bazel: Changing Behavior on Windows

Bazel started on Linux and Mac OS, and most people use Bazel on these platforms exclusively, but Bazel can execute on Windows as well. However, Windows has enough idiosynchatic differences that writing a single, operating-system agnostic rule that executes on both Windows and Linux/Mac is quite hard. Often it is easiest to have the rule detect whether it is running on Windows and execute different behavior.

A rule can detect whether it is running on Windows is by using configurable attributes, a.k.a. the select() statement. This can be made automatic by wrapping your custom rule in a macro that generates the select() statement for you automatically:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# my_rule.bzl
def _impl(ctx):
    if ctx.attr.private_is_windows:
        # Do windows specific things
    ...

my_rule_def = rule(
    attrs = {
        'private_is_windows': attr.bool(mandatory = True),
        ...
    },
    implementation = _impl
)

# All users of the rule should use the below `my_rule` wrapper
# not the rule definition above
def my_rule(name, **kwargs):
    my_rule_def(
        name = name,
        private_is_windows = select({
            "@bazel_tools//src/conditions:host_windows": True,
            "//conditions:default": False,
        }),
        **kwargs
    )
1
2
3
4
5
6
7
# BUILD
load('my_rule.bzl', 'my_rule')

my_rule(
    name = "my_rule",
    ...
)