I came across this problem today and managed to come up with a possible workaround. I'm not sure if this works for your use case, but I wanted to share it on the off-chance that it's useful for somebody else too.
Essentially, I wanted to have something like:
bool_flag(
name = "thing",
build_setting_default = select({
":linux": True,
":darwin": False,
}),
)
config_setting(
name = "use_thing",
flag_values = {":thing": "true"},
)
select({
":use_thing": "foo",
"//conditions:default": "bar",
})
Instead, for my workaround, I ended up creating:
string_flag(
name = "thing",
build_setting_default = "auto",
values = ["auto", "yes", "no"],
)
I then used a macro to generate a load of config_settings from this:
config_setting(
name = "yes_thing",
flag_values = {":thing": "yes"},
)
config_setting(
name = "yes_thing_linux",
flag_values = {":thing": "yes"},
constraint_values = [":linux_toolchain"],
)
config_setting(
name = "yes_thing_darwin",
flag_values = {":thing": "yes"},
constraint_values = [":darwin_toolchain"],
)
...
When you use the config_settings in a select, you can then effectively have a default value by specifying the auto case for each of :linux and :darwin:
selects.with_or({
(":auto_thing", ":no_thing"): "bar",
(":auto_thing_linux", ":yes_thing_linux"): "foo",
})
This example effectively allows us to say that :linux has a default value of yes, and everything else has a default value of no. The nice thing about this is that we can also make some options unsupported—for example, :yes_thing_darwin is not covered so :thing cannot be set to yes on :darwin.
Since this part stumped me at first, the reason that :auto_thing and :auto_thing_linux are allowed in the same select is because :auto_thing_linux is an unambiguous specialisation of :auto_thing.