1# Copyright 2024 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""A rule for letting enabled toolchain features drive build configuration.""" 15 16load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") 17load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain") 18 19def _cc_toolchain_feature_is_enabled_impl(ctx): 20 toolchain = find_cpp_toolchain(ctx) 21 feature_configuration = cc_common.configure_features( 22 ctx = ctx, 23 cc_toolchain = toolchain, 24 ) 25 val = cc_common.is_enabled( 26 feature_configuration = feature_configuration, 27 feature_name = ctx.attr.feature_name, 28 ) 29 return [ 30 config_common.FeatureFlagInfo(value = str(val)), 31 BuildSettingInfo(value = val), 32 ] 33 34_cc_toolchain_feature_is_enabled = rule( 35 implementation = _cc_toolchain_feature_is_enabled_impl, 36 attrs = { 37 "feature_name": attr.string( 38 mandatory = True, 39 doc = "The feature name to match against", 40 ), 41 "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), 42 }, 43 doc = """Extracts a matching, enabled feature from the current C/C++ toolchain. 44 45This rule is a bridge that allows feature presence/absence to be communicated 46from a toolchain configuration as if it was just a `bool_flag`. 47 48This allows toolchain features to become branches in `select()` statements: 49 50```py 51_cc_toolchain_feature_is_enabled( 52 name = "toolchain_flavor_chocolate", 53 feature_name = "toolchain_flavor_chocolate", 54) 55 56config_setting( 57 name = "chocolate", 58 flag_values = {":toolchain_flavor_chocolate": "True"}, 59) 60 61cc_library( 62 name = "libfoo", 63 copts = select({ 64 ":chocolate": ["-fno-dog-food"], 65 "//conditions:default": [], 66 }), 67 srcs = ["foo.cc"], 68) 69``` 70""", 71 toolchains = use_cpp_toolchain(), 72 fragments = ["cpp"], 73) 74 75def pw_cc_toolchain_feature_is_enabled(*, name, feature_name, **kwargs): 76 _cc_toolchain_query_name = name + ".value" 77 _cc_toolchain_feature_is_enabled( 78 name = _cc_toolchain_query_name, 79 feature_name = feature_name, 80 **kwargs 81 ) 82 83 native.config_setting( 84 name = name, 85 flag_values = {":{}".format(_cc_toolchain_query_name): "True"}, 86 ) 87