warchantua
warchantua

Reputation: 1231

How to limit rule to a subset of cpp toolchains?

I have a rule like this

do_action = rule (
    implementation = _impl,
    attrs = {
        ...
        "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
    },
    fragments = ["cpp"],
    toolchains = [
        "@bazel_tools//tools/cpp:toolchain_type",
        ],
)

I define custom cc_toolchain for a custom cpu:

toolchain(
    name = "cc-toolchain-%{toolchain_name}",
    toolchain = ":cc-compiler-%{toolchain_name}",
    # can be run on this platform
    target_compatible_with = [
        "@platforms//os:windows",
        "@platforms//cpu:x86_64",
    ],
    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)

cc_toolchain_suite(
    name = "toolchain",
    toolchains = {
        "%{cpu}": ":cc-compiler-%{toolchain_name}",
    },
)

I use --crostool_top to select this toolchain when needed.

I want to allow my custom rule to be invoked only if --crostool_top matches one of my custom toolchains. How to do this?

Upvotes: 0

Views: 226

Answers (1)

Brian Silverman
Brian Silverman

Reputation: 3868

Add a new constraint_setting with a constraint_value which only your toolchains are target_compatible_with, and then make all targets which use your rules target_compatible_with it.

Something like this in a BUILD file:

constraint_setting(name = "is_my_toolchain")

constraint_value(
  name = "yes_my_toolchain",
  constraint_setting = ":is_my_toolchain",
)

And then add yes_my_toolchain to target_compatible_with on all your toolchains.

Easiest way to force using it with every usage of your rule is with a macro. Rename the actual rule to _do_action (so it's private and can't be loaded directly from any BUILD file) and add:

def do_action(target_compatible_with = [], **kwargs):
  _do_action(
    target_compatible_with = target_compatible_with + [
      "//your_package:yes_my_toolchain",
    ],
    **kwargs
  )

Upvotes: 1

Related Questions