You can use an outgoing-edge user-defined transition as detailed in Brian's answer, but one thing to note is that if the test target is built / run on its own (as a top-level target explicitly, or captured by a target pattern like //...
, //:all
, //:*
, or if a target depends on it directly), then it won't get the configuration transition. If you use an incoming-edge transition, you can put a target between the cc_test
and the cc_library
that will cause the select
in the cc_library
to always pick the branch the test wants:
WORKSPACE
:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "bazel_skylib",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
],
sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()
BUILD
:
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
load(":defs.bzl", "my_flag_config_cc_alias")
string_flag(
name = "my_flag",
values = ["a", "b"],
build_setting_default = "a",
)
cc_binary(
name = "main",
srcs = ["main.c"],
deps = [":foo"],
)
cc_test(
name = "test_foo",
srcs = ["test_foo.c"],
deps = [":foo_configured_with_my_flag"],
)
my_flag_config_cc_alias(
name = "foo_configured_with_my_flag",
actual = ":foo",
my_flag_value = "b",
)
cc_library(
name = "foo",
srcs = ["foo.c"],
deps = select({
":use_a": [":a"],
":use_b": [":b"],
"//conditions:default": [":a"],
}),
)
cc_library(
name = "a",
srcs = ["a.c"],
)
cc_library(
name = "b",
srcs = ["b.c"],
)
config_setting(
name = "use_a",
flag_values = {
":my_flag": "a"
}
)
config_setting(
name = "use_b",
flag_values = {
":my_flag": "b"
}
)
defs.bzl
:
def _my_flag_config_cc_alias_tranistion_impl(settings, attr):
new_settings = dict(settings)
new_settings["//:my_flag"] = attr.my_flag_value
return new_settings
_my_flag_config_cc_alias_transition = transition(
implementation = _my_flag_config_cc_alias_tranistion_impl,
inputs = ["//:my_flag"],
outputs = ["//:my_flag"],
)
def _my_flag_config_cc_alias_impl(ctx):
return ctx.attr.actual[CcInfo] # forward the CcInfo of the actual target
my_flag_config_cc_alias = rule(
implementation = _my_flag_config_cc_alias_impl,
cfg = _my_flag_config_cc_alias_transition, # "incoming edge" transition
attrs = {
"actual": attr.label(),
"my_flag_value": attr.string(),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
},
)
main.c
:
#include <stdio.h>
int getFoo();
int main() {
printf("value is %d\n", getFoo());
return 0;
}
test_foo.c
:
int getFoo();
int main() {
if (getFoo() == 1000) {
return 0;
} else {
return 1;
}
}
foo.c
:
int getBar();
int getFoo() {
return getBar() * 2;
}
a.c
:
int getBar() {
return 10;
}
b.c
:
int getBar() {
return 500;
}
$ bazel run main
INFO: Analyzed target //:main (39 packages loaded, 174 targets configured).
INFO: Found 1 target...
Target //:main up-to-date:
bazel-bin/main
INFO: Elapsed time: 0.523s, Critical Path: 0.07s
INFO: 8 processes: 4 internal, 4 linux-sandbox.
INFO: Build completed successfully, 8 total actions
INFO: Build completed successfully, 8 total actions
value is 20
$ bazel run main --//:my_flag=a
INFO: Analyzed target //:main (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //:main up-to-date:
bazel-bin/main
INFO: Elapsed time: 0.104s, Critical Path: 0.01s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Build completed successfully, 1 total action
value is 20
$ bazel run main --//:my_flag=b
INFO: Build option --//:my_flag has changed, discarding analysis cache.
INFO: Analyzed target //:main (0 packages loaded, 174 targets configured).
INFO: Found 1 target...
Target //:main up-to-date:
bazel-bin/main
INFO: Elapsed time: 0.297s, Critical Path: 0.05s
INFO: 4 processes: 2 internal, 2 linux-sandbox.
INFO: Build completed successfully, 4 total actions
INFO: Build completed successfully, 4 total actions
value is 1000
$ bazel test test_foo
INFO: Build option --//:my_flag has changed, discarding analysis cache.
INFO: Analyzed target //:test_foo (11 packages loaded, 762 targets configured).
INFO: Found 1 test target...
Target //:test_foo up-to-date:
bazel-bin/test_foo
INFO: Elapsed time: 0.579s, Critical Path: 0.15s
INFO: 15 processes: 7 internal, 8 linux-sandbox.
INFO: Build completed successfully, 15 total actions
//:test_foo PASSED in 0.0s
Executed 1 out of 1 test: 1 test passes.
INFO: Build completed successfully, 15 total actions