diff options
Diffstat (limited to 'pw_toolchain_bazel/cc_toolchain/private/toolchain_feature.bzl')
-rw-r--r-- | pw_toolchain_bazel/cc_toolchain/private/toolchain_feature.bzl | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/pw_toolchain_bazel/cc_toolchain/private/toolchain_feature.bzl b/pw_toolchain_bazel/cc_toolchain/private/toolchain_feature.bzl new file mode 100644 index 000000000..e16d331da --- /dev/null +++ b/pw_toolchain_bazel/cc_toolchain/private/toolchain_feature.bzl @@ -0,0 +1,215 @@ +# Copyright 2023 The Pigweed Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +"""Implementation of the pw_cc_toolchain_feature rule.""" + +load( + "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", + "feature", + "flag_group", + "flag_set", +) +load( + "//cc_toolchain/private:providers.bzl", + "ToolchainFeatureInfo", +) +load("//cc_toolchain/private:utils.bzl", "ACTION_MAP") + +TOOLCHAIN_FEATURE_INFO_ATTRS = { + "aropts": "List[str]: Flags to pass to all archive actions", + "asmopts": "List[str]: Flags to pass to assembler actions", + "copts": "List[str]: Flags to pass to all C/C++ compile actions", + "conlyopts": "List[str]: Flags to pass to C compile actions", + "cxxopts": "List[str]: Flags to pass to C++ compile actions", + "linkopts": "List[str]: Flags to pass to C compile actions", + "linker_files": "List[File]: Files to link", + "cxx_builtin_include_directories": "List[str]: Paths to C++ standard library include directories", + "builtin_sysroot": "str: Path to the directory containing the sysroot", +} + +def _dict_to_str(dict_to_stringify): + """Converts a dictionary to a multi-line string. + + Args: + dict_to_stringify (Dict[str, str]): Dictionary to stringify. + + Returns: + str: Multi-line string representing the dictionary, or {empty}. + """ + result = [] + for key in dict_to_stringify.keys(): + result.append(" {}: {}".format(key, dict_to_stringify[key])) + if not result: + return "{empty}" + return "\n".join(["{"] + result + ["}"]) + +def _feature_flag_set(actions, flags): + """Transforms a list of flags and actions into a flag_set. + + Args: + actions (List[str]): Actions that the provided flags will be applied to. + flags (List[str]): List of flags to apply to the specified actions. + + Returns: + flag_set: A flag_set binding the provided flags to the specified + actions. + """ + return flag_set( + actions = actions, + flag_groups = ([ + flag_group( + flags = flags, + ), + ]), + ) + +def _check_args(ctx, **kwargs): + """Checks that args provided to build_toolchain_feature_info are valid. + + Args: + ctx: The context of the current build rule. + **kwargs: All attributes supported by pw_cc_toolchain_feature. + + Returns: + None + """ + for key in kwargs.keys(): + if key not in TOOLCHAIN_FEATURE_INFO_ATTRS: + fail( + "Unknown attribute \"{}\" used by {}. Valid attributes are:\n{}".format( + key, + ctx.label, + _dict_to_str(TOOLCHAIN_FEATURE_INFO_ATTRS), + ), + ) + +def _build_flag_sets(**kwargs): + """Transforms a dictionary of arguments into a list of flag_sets. + + Args: + **kwargs: All attributes supported by pw_cc_toolchain_feature. + + Returns: + List[flag_set]: A list of flag_sets that bind all provided flags to + their appropriate actions. + """ + all_flags = [] + for action in ACTION_MAP.keys(): + if kwargs[action]: + all_flags.append(_feature_flag_set(ACTION_MAP[action], kwargs[action])) + return all_flags + +def _initialize_args(**kwargs): + """Initializes build_toolchain_feature_info arguments. + + Args: + **kwargs: All attributes supported by pw_cc_toolchain_feature. + + Returns: + Dict[str, Any]: Dictionary containing arguments default initialized to + be compatible with _build_flag_sets. + """ + initialized_args = {} + for action in ACTION_MAP.keys(): + if action in kwargs: + initialized_args[action] = kwargs[action] + else: + initialized_args[action] = [] + + if "linker_files" in kwargs: + linker_files = kwargs["linker_files"] + linker_flags = [file.path for file in linker_files] + + initialized_args["linkopts"] = initialized_args["linkopts"] + linker_flags + initialized_args["linker_files"] = depset(linker_files) + else: + initialized_args["linker_files"] = depset() + + if "cxx_builtin_include_directories" in kwargs: + initialized_args["cxx_builtin_include_directories"] = kwargs["cxx_builtin_include_directories"] + else: + initialized_args["cxx_builtin_include_directories"] = [] + + if "builtin_sysroot" in kwargs: + initialized_args["builtin_sysroot"] = kwargs["builtin_sysroot"] + else: + initialized_args["builtin_sysroot"] = None + return initialized_args + +def build_toolchain_feature_info(ctx, **kwargs): + """Builds a ToolchainFeatureInfo provider. + + Args: + ctx: The context of the current build rule. + **kwargs: All attributes supported by pw_cc_toolchain_feature. + + Returns: + ToolchainFeatureInfo, DefaultInfo: All providers supported by + pw_cc_toolchain_feature. + """ + _check_args(ctx, **kwargs) + + initialized_args = _initialize_args(**kwargs) + + new_feature = feature( + name = ctx.attr.name, + enabled = True, + flag_sets = _build_flag_sets(**initialized_args), + ) + + return [ + ToolchainFeatureInfo( + feature = new_feature, + cxx_builtin_include_directories = initialized_args["cxx_builtin_include_directories"], + builtin_sysroot = initialized_args["builtin_sysroot"], + ), + DefaultInfo(files = initialized_args["linker_files"]), + ] + +def _pw_cc_toolchain_feature_impl(ctx): + """Rule that provides ToolchainFeatureInfo. + + Args: + ctx: The context of the current build rule. + + Returns: + ToolchainFeatureInfo, DefaultInfo + """ + return build_toolchain_feature_info( + ctx = ctx, + aropts = ctx.attr.aropts, + asmopts = ctx.attr.asmopts, + copts = ctx.attr.copts, + conlyopts = ctx.attr.conlyopts, + cxxopts = ctx.attr.cxxopts, + linkopts = ctx.attr.linkopts, + linker_files = ctx.files.linker_files, + cxx_builtin_include_directories = ctx.attr.cxx_builtin_include_directories, + builtin_sysroot = ctx.attr.builtin_sysroot, + ) + +pw_cc_toolchain_feature = rule( + implementation = _pw_cc_toolchain_feature_impl, + attrs = { + "aropts": attr.string_list(), + "asmopts": attr.string_list(), + "copts": attr.string_list(), + "conlyopts": attr.string_list(), + "cxxopts": attr.string_list(), + "linkopts": attr.string_list(), + "linker_files": attr.label_list(allow_files = True), + "cxx_builtin_include_directories": attr.string_list(), + "builtin_sysroot": attr.string(), + }, + provides = [ToolchainFeatureInfo, DefaultInfo], +) |