diff --git a/foreign_cc/cmake.bzl b/foreign_cc/cmake.bzl index 8ba5a58cb..e6061989e 100644 --- a/foreign_cc/cmake.bzl +++ b/foreign_cc/cmake.bzl @@ -148,6 +148,7 @@ load( "//foreign_cc/private/framework:platform.bzl", "os_name", ) +load("//foreign_cc/private:transitions.bzl", "make_variant") load( "//toolchains/native_tools:tool_access.bzl", "get_cmake_data", @@ -416,3 +417,18 @@ cmake = rule( # version is updated to a release of Bazel containing the new default for this setting. incompatible_use_toolchain_transition = True, ) + +def cmake_variant(name, toolchain, **kwargs): + """ Wrapper macro around the cmake() rule to force usage of the given make variant toolchain. + + Args: + name: The target name + toolchain: The desired make variant toolchain to use, e.g. @rules_foreign_cc//toolchains:preinstalled_nmake_toolchain + **kwargs: Remaining keyword arguments + """ + make_variant( + name = name, + rule = cmake, + toolchain = toolchain, + **kwargs, + ) \ No newline at end of file diff --git a/foreign_cc/configure.bzl b/foreign_cc/configure.bzl index 897f7a3e9..69ace595d 100644 --- a/foreign_cc/configure.bzl +++ b/foreign_cc/configure.bzl @@ -19,6 +19,7 @@ load( "expand_locations", ) load("//foreign_cc/private/framework:platform.bzl", "os_name") +load("//foreign_cc/private:transitions.bzl", "make_variant") load("//toolchains/native_tools:tool_access.bzl", "get_make_data") def _configure_make(ctx): @@ -230,3 +231,18 @@ configure_make = rule( # version is updated to a release of Bazel containing the new default for this setting. incompatible_use_toolchain_transition = True, ) + +def configure_make_variant(name, toolchain, **kwargs): + """ Wrapper macro around the configure_make() rule to force usage of the given make variant toolchain. + + Args: + name: The target name + toolchain: The desired make variant toolchain to use, e.g. @rules_foreign_cc//toolchains:preinstalled_nmake_toolchain + **kwargs: Remaining keyword arguments + """ + make_variant( + name = name, + rule = configure_make, + toolchain = toolchain, + **kwargs, + ) \ No newline at end of file diff --git a/foreign_cc/defs.bzl b/foreign_cc/defs.bzl index 38e25c1c9..9a2447a9a 100644 --- a/foreign_cc/defs.bzl +++ b/foreign_cc/defs.bzl @@ -1,13 +1,16 @@ """Public entry point to all Foreign CC rules and supported APIs.""" load(":boost_build.bzl", _boost_build = "boost_build") -load(":cmake.bzl", _cmake = "cmake") -load(":configure.bzl", _configure_make = "configure_make") -load(":make.bzl", _make = "make") +load(":cmake.bzl", _cmake = "cmake", _cmake_variant = "cmake_variant") +load(":configure.bzl", _configure_make = "configure_make", _configure_make_variant = "configure_make_variant") +load(":make.bzl", _make = "make", _make_variant = "make_variant") load(":ninja.bzl", _ninja = "ninja") boost_build = _boost_build cmake = _cmake +cmake_variant = _cmake_variant configure_make = _configure_make +configure_make_variant = _configure_make_variant +make_variant = _make_variant make = _make ninja = _ninja diff --git a/foreign_cc/make.bzl b/foreign_cc/make.bzl index b511bf719..50c49b662 100644 --- a/foreign_cc/make.bzl +++ b/foreign_cc/make.bzl @@ -15,9 +15,9 @@ load( "CC_EXTERNAL_RULE_FRAGMENTS", "cc_external_rule_impl", "create_attrs", - "expand_locations", ) load("//foreign_cc/private:make_script.bzl", "create_make_script") +load("//foreign_cc/private:transitions.bzl", _make_variant = "make_variant") load("//toolchains/native_tools:tool_access.bzl", "get_make_data") def _make(ctx): @@ -106,3 +106,18 @@ make = rule( # version is updated to a release of Bazel containing the new default for this setting. incompatible_use_toolchain_transition = True, ) + +def make_variant(name, toolchain, **kwargs): + """ Wrapper macro around the make() rule to force usage of the given make variant toolchain. + + Args: + name: The target name + toolchain: The desired make variant toolchain to use, e.g. @rules_foreign_cc//toolchains:preinstalled_nmake_toolchain + **kwargs: Remaining keyword arguments + """ + _make_variant( + name = name, + rule = make, + toolchain = toolchain, + **kwargs, + ) diff --git a/foreign_cc/private/transitions.bzl b/foreign_cc/private/transitions.bzl new file mode 100644 index 000000000..04123c168 --- /dev/null +++ b/foreign_cc/private/transitions.bzl @@ -0,0 +1,69 @@ +"""This file contains rules for configuration transitions""" + +load("//foreign_cc:providers.bzl", "ForeignCcDepsInfo") + +def _extra_toolchains_transition_impl(settings, attrs): + return {"//command_line_option:extra_toolchains": attrs.extra_toolchains + settings["//command_line_option:extra_toolchains"]} + +_extra_toolchains_transition = transition( + implementation = _extra_toolchains_transition_impl, + inputs = ["//command_line_option:extra_toolchains"], + outputs = ["//command_line_option:extra_toolchains"], +) + +def _extra_toolchains_transitioned_foreign_cc_target_impl(ctx): + # Return the providers from the transitioned foreign_cc target + return [ + ctx.attr.target[DefaultInfo], + ctx.attr.target[CcInfo], + ctx.attr.target[ForeignCcDepsInfo], + ctx.attr.target[OutputGroupInfo], + ] + +extra_toolchains_transitioned_foreign_cc_target = rule( + doc = "A rule for adding extra toolchains to consider when building the given target", + implementation = _extra_toolchains_transitioned_foreign_cc_target_impl, + cfg = _extra_toolchains_transition, + attrs = { + "extra_toolchains": attr.string_list( + doc = "Additional toolchains to consider", + mandatory = True, + ), + "target": attr.label( + doc = "The target to build after considering the extra toolchains", + providers = [ForeignCcDepsInfo], + mandatory = True, + ), + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), + }, + incompatible_use_toolchain_transition = True, +) + +def make_variant(name, rule, toolchain, **kwargs): + """ Wrapper macro around foreign cc rules to force usage of the given make variant toolchain. + + Args: + name: The target name + rule: The configure_make() or make() rule to instantiate + toolchain: The desired make variant toolchain to use, e.g. @rules_foreign_cc//toolchains:preinstalled_nmake_toolchain + **kwargs: Remaining keyword arguments + """ + + make_variant_target_name = name + "_" + + tags = kwargs["tags"] if "tags" in kwargs else [] + + rule( + name = make_variant_target_name, + tags = tags + ["manual"], + **kwargs + ) + + extra_toolchains_transitioned_foreign_cc_target( + name = name, + extra_toolchains = [toolchain], + target = make_variant_target_name, + tags = tags, + ) diff --git a/foreign_cc/repositories.bzl b/foreign_cc/repositories.bzl index ba5fdc931..3cd6ec712 100644 --- a/foreign_cc/repositories.bzl +++ b/foreign_cc/repositories.bzl @@ -50,12 +50,6 @@ def rules_foreign_cc_dependencies( if register_default_tools: prebuilt_toolchains(cmake_version, ninja_version) - # `nmake` is a unique toolchin in that it's non-hermetic since it relies on the - # host environment but there does not appear to be any way to get `nmake` outside - # of installing Visual Studio. It is considered a default toolchain to add better - # support for MSVC Windows platforms. - native.register_toolchains(str(Label("//toolchains:preinstalled_nmake_toolchain"))) - if register_built_tools: built_toolchains( cmake_version = cmake_version, diff --git a/toolchains/BUILD.bazel b/toolchains/BUILD.bazel index 9700fb7ce..78f3a50db 100644 --- a/toolchains/BUILD.bazel +++ b/toolchains/BUILD.bazel @@ -72,7 +72,6 @@ toolchain( name = "preinstalled_nmake_toolchain", exec_compatible_with = [ "@platforms//os:windows", - "@bazel_tools//tools/cpp:msvc", ], toolchain = ":preinstalled_nmake", toolchain_type = ":make_toolchain", diff --git a/toolchains/toolchains.bzl b/toolchains/toolchains.bzl index 2db87180b..b561682fa 100644 --- a/toolchains/toolchains.bzl +++ b/toolchains/toolchains.bzl @@ -16,5 +16,4 @@ def preinstalled_toolchains(): str(Label("//toolchains:preinstalled_cmake_toolchain")), str(Label("//toolchains:preinstalled_make_toolchain")), str(Label("//toolchains:preinstalled_ninja_toolchain")), - str(Label("//toolchains:preinstalled_nmake_toolchain")), )