I'm trying to conditionally compile a C++ library with bazel depending on if a particular flag is set when building/running one of the target that use the library or the library itself.
My library has something like:
//libraryheader.hpp
#ifdef MY_MACRO
#pragma message("MY_MACRO is defined")
//do something
#else
// do something else
#endif
Here's what I've tried. The BUILD file looks something like
#BUILD
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
use_the_feature_macro = string_flag(
name = "use_the_feature",
build_setting_default = "",
)
cc_library(
name = "my_library",
testonly = True,
srcs = [
"somefile.cpp",
],
hdrs = [
"libraryheader.hpp",
],
copts = select({
":use_the_feature_macro": ["-DMY_MACRO"],
"//conditions:default": [],
}),
data = [],
visibility = ["//path/to/smth:__subpackages__"],
deps = [
"//path/to/smth:targ1",
...
],
)
When trying to build with a command like bazel build --use_the_feature //path/to:my_library
I keep getting errors about the unrecognized option. I've also tried with `bazel build --//path/to:use_feature //path/to:my_library but it doesn't work. Still unrecognised option
ERROR: --use_the_feature :: Unrecognized option: --use_the_feature
What I whish to achieve is to be able to conditionally compile the library both when compiling the library by itself or when compiling a target that uses the library. For now, looking at the bazel documentation I don't know if I should use string_flag or config_setting and the examples on their github are quite difficult to understand.
What you seem to be missing is a config_setting
that depends on the flag value, which then you can use in your select()
.
Here is a complete working example:
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
config_setting(
name = "feature_is_used",
flag_values = {
":use_the_feature": "yes",
},
)
string_flag(
name = "use_the_feature",
build_setting_default = "",
)
cc_library(
name = "my_library",
testonly = True,
srcs = ["somefile.cpp"],
hdrs = ["libraryheader.hpp"],
copts = select({
":feature_is_used": ["-DMY_MACRO"],
"//conditions:default": [],
}),
)
Then you can use bazel build --//:use_the_feature=yes :my_library
to build with the macro. There's nothing special about the word "yes", you can enable macros one-by-one this way, or you can switch to using a bool_flag
if you want a single toggle.
For completeness, here are the remaining files needed for the build:
MODULE.bazel
bazel_dep(name = "bazel_skylib", version = "1.5.0")
libraryheader.hpp
// libraryheader.hpp
#ifdef MY_MACRO
#pragma message("MY_MACRO is defined")
// do something
#else
// do something else
#endif
somefile.cpp
can be empty.