Robbie
Robbie

Reputation: 297

What is the proper way to optionally compile a library with a build flag (to place in `target_compatible_with`)?

Suppose I have a library implementation that I only want to compile when the user specifies it at build time.

Should I use the features flag?

If so, how could I use the features flag to constrain compilation like you can with target_compatible_with in cc_library, cc_test, and cc_binary?

If not, what is the best way to constrain this? Adjusting the platforms flag disturbs default platform detection.

Upvotes: 4

Views: 1487

Answers (2)

Brian Silverman
Brian Silverman

Reputation: 3858

Sounds like you want a user-defined build setting that is a command-line flag. The easiest way is to use one of the common build settings rules, and instantiate it in a BUILD file (call it flags/BUILD for this example):

load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
bool_flag(
    name = "flag",
    build_setting_default = False,
    visibility = ["//visibility:public"],
)

Then you can set it from the command line with --//flags:flag. If you want a less ugly syntax, build setting aliases are also available.

Once you have something which can trigger a config_setting, making an optional library is pretty straightforwards. First you want to disable the library itself when the flag isn't set:

config_setting(
    name = "have_flag",
    flag_values = {
        "//flags:flag": "true",
    },
)

cc_library(
    name = "sometimes",
    target_compatible_with = select({
        ":have_flag": [],
        "//conditions:default": ["@platforms//:incompatible"],
    }),
)

Anything marked as requiring @platforms//:incompatible will never be compatible with any real platform, so this will skip the library when you bazel build //... without the flag and make it an error for anything to depend on it.

I'm guessing you have other targets that depend on this library when enabled, which can be handled similarly:

cc_binary(
    name = "thing",
    deps = [
        "//:something_else",
    ] + select({
        ":have_flag": [":sometimes"],
        "//conditions:default": [],
    }),
)

If you want to define a preprocessor macro to tell the dependent code whether to use the optional dependency (or swap out source files, or change link options, etc), then you can use select like that for copts, defines, srcs, and most of the other cc_library/cc_binary attributes.

Upvotes: 6

Vertexwahn
Vertexwahn

Reputation: 8172

Make use of the tag manual, e.g.:

cc_test(name = "my_test"
        ...
        tags = ["manual"]
)

Upvotes: 2

Related Questions