Removed `rust_toolchain.os` in favor of `rust_toolchain.exec_triple`. (#1960)

* Removed `rust_toolchain.os` in favor of `rust_toolchain.exec_triple`.

* Regenerate documentation
diff --git a/crate_universe/private/crates_vendor.bzl b/crate_universe/private/crates_vendor.bzl
index 3cd6ed5..0f9a625 100644
--- a/crate_universe/private/crates_vendor.bzl
+++ b/crate_universe/private/crates_vendor.bzl
@@ -42,7 +42,7 @@
 
 def _is_windows(ctx):
     toolchain = ctx.toolchains[Label("@rules_rust//rust:toolchain_type")]
-    return toolchain.target_triple.system == "windows"
+    return toolchain.target_os == "windows"
 
 def _get_output_package(ctx):
     # Determine output directory
diff --git a/docs/flatten.md b/docs/flatten.md
index 5f8bdd3..5fea2fd 100644
--- a/docs/flatten.md
+++ b/docs/flatten.md
@@ -1142,8 +1142,8 @@
 rust_toolchain(<a href="#rust_toolchain-name">name</a>, <a href="#rust_toolchain-allocator_library">allocator_library</a>, <a href="#rust_toolchain-binary_ext">binary_ext</a>, <a href="#rust_toolchain-cargo">cargo</a>, <a href="#rust_toolchain-clippy_driver">clippy_driver</a>, <a href="#rust_toolchain-debug_info">debug_info</a>,
                <a href="#rust_toolchain-default_edition">default_edition</a>, <a href="#rust_toolchain-dylib_ext">dylib_ext</a>, <a href="#rust_toolchain-env">env</a>, <a href="#rust_toolchain-exec_triple">exec_triple</a>, <a href="#rust_toolchain-experimental_use_cc_common_link">experimental_use_cc_common_link</a>,
                <a href="#rust_toolchain-extra_exec_rustc_flags">extra_exec_rustc_flags</a>, <a href="#rust_toolchain-extra_rustc_flags">extra_rustc_flags</a>, <a href="#rust_toolchain-global_allocator_library">global_allocator_library</a>, <a href="#rust_toolchain-llvm_cov">llvm_cov</a>,
-               <a href="#rust_toolchain-llvm_profdata">llvm_profdata</a>, <a href="#rust_toolchain-llvm_tools">llvm_tools</a>, <a href="#rust_toolchain-opt_level">opt_level</a>, <a href="#rust_toolchain-os">os</a>, <a href="#rust_toolchain-per_crate_rustc_flags">per_crate_rustc_flags</a>, <a href="#rust_toolchain-rust_doc">rust_doc</a>, <a href="#rust_toolchain-rust_std">rust_std</a>,
-               <a href="#rust_toolchain-rustc">rustc</a>, <a href="#rust_toolchain-rustc_lib">rustc_lib</a>, <a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>, <a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
+               <a href="#rust_toolchain-llvm_profdata">llvm_profdata</a>, <a href="#rust_toolchain-llvm_tools">llvm_tools</a>, <a href="#rust_toolchain-opt_level">opt_level</a>, <a href="#rust_toolchain-per_crate_rustc_flags">per_crate_rustc_flags</a>, <a href="#rust_toolchain-rust_doc">rust_doc</a>, <a href="#rust_toolchain-rust_std">rust_std</a>, <a href="#rust_toolchain-rustc">rustc</a>,
+               <a href="#rust_toolchain-rustc_lib">rustc_lib</a>, <a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>, <a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
 </pre>
 
 Declares a Rust toolchain for use.
@@ -1159,24 +1159,27 @@
 
 rust_toolchain(
     name = "rust_cpuX_impl",
+    binary_ext = "",
+    dylib_ext = ".so",
+    exec_triple = "cpuX-unknown-linux-gnu",
+    rust_doc = "@rust_cpuX//:rustdoc",
+    rust_std = "@rust_cpuX//:rust_std",
     rustc = "@rust_cpuX//:rustc",
     rustc_lib = "@rust_cpuX//:rustc_lib",
-    rust_std = "@rust_cpuX//:rust_std",
-    rust_doc = "@rust_cpuX//:rustdoc",
-    binary_ext = "",
     staticlib_ext = ".a",
-    dylib_ext = ".so",
     stdlib_linkflags = ["-lpthread", "-ldl"],
-    os = "linux",
+    target_triple = "cpuX-unknown-linux-gnu",
 )
 
 toolchain(
     name = "rust_cpuX",
     exec_compatible_with = [
         "@platforms//cpu:cpuX",
+        "@platforms//os:linux",
     ],
     target_compatible_with = [
         "@platforms//cpu:cpuX",
+        "@platforms//os:linux",
     ],
     toolchain = ":rust_cpuX_impl",
 )
@@ -1184,7 +1187,7 @@
 
 Then, either add the label of the toolchain rule to `register_toolchains` in the WORKSPACE, or pass it to the `"--extra_toolchains"` flag for Bazel, and it will be used.
 
-See @rules_rust//rust:repositories.bzl for examples of defining the @rust_cpuX repository with the actual binaries and libraries.
+See `@rules_rust//rust:repositories.bzl` for examples of defining the `@rust_cpuX` repository with the actual binaries and libraries.
 
 
 **ATTRIBUTES**
@@ -1210,7 +1213,6 @@
 | <a id="rust_toolchain-llvm_profdata"></a>llvm_profdata |  The location of the <code>llvm-profdata</code> binary. Can be a direct source or a filegroup containing one item. If <code>llvm_cov</code> is None, this can be None as well and rust code is not instrumented for coverage.   | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
 | <a id="rust_toolchain-llvm_tools"></a>llvm_tools |  LLVM tools that are shipped with the Rust toolchain.   | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
 | <a id="rust_toolchain-opt_level"></a>opt_level |  Rustc optimization levels.   | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{"dbg": "0", "fastbuild": "0", "opt": "3"}</code> |
-| <a id="rust_toolchain-os"></a>os |  The operating system for the current toolchain   | String | optional | <code>""</code> |
 | <a id="rust_toolchain-per_crate_rustc_flags"></a>per_crate_rustc_flags |  Extra flags to pass to rustc in non-exec configuration   | List of strings | optional | <code>[]</code> |
 | <a id="rust_toolchain-rust_doc"></a>rust_doc |  The location of the <code>rustdoc</code> binary. Can be a direct source or a filegroup containing one item.   | <a href="https://bazel.build/concepts/labels">Label</a> | required |  |
 | <a id="rust_toolchain-rust_std"></a>rust_std |  The Rust standard library.   | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
diff --git a/docs/rust_repositories.md b/docs/rust_repositories.md
index fc7386d..1e7e8f5 100644
--- a/docs/rust_repositories.md
+++ b/docs/rust_repositories.md
@@ -39,8 +39,8 @@
 rust_toolchain(<a href="#rust_toolchain-name">name</a>, <a href="#rust_toolchain-allocator_library">allocator_library</a>, <a href="#rust_toolchain-binary_ext">binary_ext</a>, <a href="#rust_toolchain-cargo">cargo</a>, <a href="#rust_toolchain-clippy_driver">clippy_driver</a>, <a href="#rust_toolchain-debug_info">debug_info</a>,
                <a href="#rust_toolchain-default_edition">default_edition</a>, <a href="#rust_toolchain-dylib_ext">dylib_ext</a>, <a href="#rust_toolchain-env">env</a>, <a href="#rust_toolchain-exec_triple">exec_triple</a>, <a href="#rust_toolchain-experimental_use_cc_common_link">experimental_use_cc_common_link</a>,
                <a href="#rust_toolchain-extra_exec_rustc_flags">extra_exec_rustc_flags</a>, <a href="#rust_toolchain-extra_rustc_flags">extra_rustc_flags</a>, <a href="#rust_toolchain-global_allocator_library">global_allocator_library</a>, <a href="#rust_toolchain-llvm_cov">llvm_cov</a>,
-               <a href="#rust_toolchain-llvm_profdata">llvm_profdata</a>, <a href="#rust_toolchain-llvm_tools">llvm_tools</a>, <a href="#rust_toolchain-opt_level">opt_level</a>, <a href="#rust_toolchain-os">os</a>, <a href="#rust_toolchain-per_crate_rustc_flags">per_crate_rustc_flags</a>, <a href="#rust_toolchain-rust_doc">rust_doc</a>, <a href="#rust_toolchain-rust_std">rust_std</a>,
-               <a href="#rust_toolchain-rustc">rustc</a>, <a href="#rust_toolchain-rustc_lib">rustc_lib</a>, <a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>, <a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
+               <a href="#rust_toolchain-llvm_profdata">llvm_profdata</a>, <a href="#rust_toolchain-llvm_tools">llvm_tools</a>, <a href="#rust_toolchain-opt_level">opt_level</a>, <a href="#rust_toolchain-per_crate_rustc_flags">per_crate_rustc_flags</a>, <a href="#rust_toolchain-rust_doc">rust_doc</a>, <a href="#rust_toolchain-rust_std">rust_std</a>, <a href="#rust_toolchain-rustc">rustc</a>,
+               <a href="#rust_toolchain-rustc_lib">rustc_lib</a>, <a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>, <a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
 </pre>
 
 Declares a Rust toolchain for use.
@@ -56,24 +56,27 @@
 
 rust_toolchain(
     name = "rust_cpuX_impl",
+    binary_ext = "",
+    dylib_ext = ".so",
+    exec_triple = "cpuX-unknown-linux-gnu",
+    rust_doc = "@rust_cpuX//:rustdoc",
+    rust_std = "@rust_cpuX//:rust_std",
     rustc = "@rust_cpuX//:rustc",
     rustc_lib = "@rust_cpuX//:rustc_lib",
-    rust_std = "@rust_cpuX//:rust_std",
-    rust_doc = "@rust_cpuX//:rustdoc",
-    binary_ext = "",
     staticlib_ext = ".a",
-    dylib_ext = ".so",
     stdlib_linkflags = ["-lpthread", "-ldl"],
-    os = "linux",
+    target_triple = "cpuX-unknown-linux-gnu",
 )
 
 toolchain(
     name = "rust_cpuX",
     exec_compatible_with = [
         "@platforms//cpu:cpuX",
+        "@platforms//os:linux",
     ],
     target_compatible_with = [
         "@platforms//cpu:cpuX",
+        "@platforms//os:linux",
     ],
     toolchain = ":rust_cpuX_impl",
 )
@@ -81,7 +84,7 @@
 
 Then, either add the label of the toolchain rule to `register_toolchains` in the WORKSPACE, or pass it to the `"--extra_toolchains"` flag for Bazel, and it will be used.
 
-See @rules_rust//rust:repositories.bzl for examples of defining the @rust_cpuX repository with the actual binaries and libraries.
+See `@rules_rust//rust:repositories.bzl` for examples of defining the `@rust_cpuX` repository with the actual binaries and libraries.
 
 
 **ATTRIBUTES**
@@ -107,7 +110,6 @@
 | <a id="rust_toolchain-llvm_profdata"></a>llvm_profdata |  The location of the <code>llvm-profdata</code> binary. Can be a direct source or a filegroup containing one item. If <code>llvm_cov</code> is None, this can be None as well and rust code is not instrumented for coverage.   | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
 | <a id="rust_toolchain-llvm_tools"></a>llvm_tools |  LLVM tools that are shipped with the Rust toolchain.   | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
 | <a id="rust_toolchain-opt_level"></a>opt_level |  Rustc optimization levels.   | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{"dbg": "0", "fastbuild": "0", "opt": "3"}</code> |
-| <a id="rust_toolchain-os"></a>os |  The operating system for the current toolchain   | String | optional | <code>""</code> |
 | <a id="rust_toolchain-per_crate_rustc_flags"></a>per_crate_rustc_flags |  Extra flags to pass to rustc in non-exec configuration   | List of strings | optional | <code>[]</code> |
 | <a id="rust_toolchain-rust_doc"></a>rust_doc |  The location of the <code>rustdoc</code> binary. Can be a direct source or a filegroup containing one item.   | <a href="https://bazel.build/concepts/labels">Label</a> | required |  |
 | <a id="rust_toolchain-rust_std"></a>rust_std |  The Rust standard library.   | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
diff --git a/rust/private/repository_utils.bzl b/rust/private/repository_utils.bzl
index 0a8acd1..f418810 100644
--- a/rust/private/repository_utils.bzl
+++ b/rust/private/repository_utils.bzl
@@ -247,7 +247,6 @@
     staticlib_ext = "{staticlib_ext}",
     dylib_ext = "{dylib_ext}",
     stdlib_linkflags = [{stdlib_linkflags}],
-    os = "{system}",
     default_edition = "{default_edition}",
     exec_triple = "{exec_triple}",
     target_triple = "{target_triple}",
@@ -312,7 +311,6 @@
         allocator_library = allocator_library_label,
         global_allocator_library = global_allocator_library_label,
         stdlib_linkflags = stdlib_linkflags,
-        system = target_triple.system,
         default_edition = default_edition,
         exec_triple = exec_triple.str,
         target_triple = target_triple.str,
diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl
index 1cdc425..0cc569e 100644
--- a/rust/private/rust.bzl
+++ b/rust/private/rust.bzl
@@ -96,7 +96,7 @@
               "please file an issue!").format(crate_type))
 
     prefix = "lib"
-    if toolchain.target_triple and toolchain.target_triple.system == "windows" and crate_type not in ("lib", "rlib"):
+    if toolchain.target_triple and toolchain.target_os == "windows" and crate_type not in ("lib", "rlib"):
         prefix = ""
     if toolchain.target_arch == "wasm32" and crate_type == "cdylib":
         prefix = ""
diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl
index b69e6e4..1feba50 100644
--- a/rust/private/rustc.bzl
+++ b/rust/private/rustc.bzl
@@ -115,13 +115,9 @@
     else:
         pre = ""
 
-    target_arch = ""
-    if toolchain.target_triple:
-        target_arch = toolchain.target_triple.arch
-
     result = {
-        "CARGO_CFG_TARGET_ARCH": target_arch,
-        "CARGO_CFG_TARGET_OS": toolchain.os,
+        "CARGO_CFG_TARGET_ARCH": "" if toolchain.target_arch == None else toolchain.target_arch,
+        "CARGO_CFG_TARGET_OS": "" if toolchain.target_os == None else toolchain.target_os,
         "CARGO_CRATE_NAME": crate_name,
         "CARGO_PKG_AUTHORS": "",
         "CARGO_PKG_DESCRIPTION": "",
@@ -455,9 +451,9 @@
 
     # Take the absolute value of hash() since it could be negative.
     path_hash = abs(hash(lib.path))
-    lib_name = get_lib_name_for_windows(lib) if toolchain.os.startswith("windows") else get_lib_name_default(lib)
+    lib_name = get_lib_name_for_windows(lib) if toolchain.target_os.startswith("windows") else get_lib_name_default(lib)
 
-    if toolchain.os.startswith("windows"):
+    if toolchain.target_os.startswith("windows"):
         prefix = ""
         extension = ".lib"
     elif lib_name.endswith(".pic"):
@@ -524,7 +520,7 @@
             if _is_dylib(lib):
                 continue
             artifact = get_preferred_artifact(lib, use_pic)
-            name = get_lib_name_for_windows(artifact) if toolchain.os.startswith("windows") else get_lib_name_default(artifact)
+            name = get_lib_name_for_windows(artifact) if toolchain.target_os.startswith("windows") else get_lib_name_default(artifact)
 
             # On Linux-like platforms, normally library base names start with
             # `lib`, following the pattern `lib[name].(a|lo)` and we pass
@@ -534,10 +530,10 @@
             # FIXME: Under the native-link-modifiers unstable rustc feature,
             # we could use -lstatic:+verbatim instead.
             needs_symlink_to_standardize_name = (
-                (toolchain.os.startswith("linux") or toolchain.os.startswith("mac") or toolchain.os.startswith("darwin")) and
+                toolchain.target_os.startswith(("linux", "mac", "darwin")) and
                 artifact.basename.endswith(".a") and not artifact.basename.startswith("lib")
             ) or (
-                toolchain.os.startswith("windows") and not artifact.basename.endswith(".lib")
+                toolchain.target_os.startswith("windows") and not artifact.basename.endswith(".lib")
             )
 
             # Detect cases where we need to disambiguate library dependencies
@@ -871,7 +867,7 @@
         json = ["artifacts"]
         if error_format == "short":
             json.append("diagnostic-short")
-        elif error_format == "human" and toolchain.os != "windows":
+        elif error_format == "human" and toolchain.target_os != "windows":
             # If the os is not windows, we can get colorized output.
             json.append("diagnostic-rendered-ansi")
 
@@ -1190,7 +1186,7 @@
     # For a cdylib that might be added as a dependency to a cc_* target on Windows, it is important to include the
     # interface library that rustc generates in the output files.
     interface_library = None
-    if toolchain.os == "windows" and crate_info.type == "cdylib":
+    if toolchain.target_os == "windows" and crate_info.type == "cdylib":
         # Rustc generates the import library with a `.dll.lib` extension rather than the usual `.lib` one that msvc
         # expects (see https://github.com/rust-lang/rust/pull/29520 for more context).
         interface_library = ctx.actions.declare_file(crate_info.output.basename + ".lib", sibling = crate_info.output)
@@ -1204,10 +1200,10 @@
     pdb_file = None
     dsym_folder = None
     if crate_info.type in ("cdylib", "bin"):
-        if toolchain.os == "windows":
+        if toolchain.target_os == "windows":
             pdb_file = ctx.actions.declare_file(crate_info.output.basename[:-len(crate_info.output.extension)] + "pdb", sibling = crate_info.output)
             action_outputs.append(pdb_file)
-        elif toolchain.os == "darwin":
+        elif toolchain.target_os == "darwin":
             dsym_folder = ctx.actions.declare_directory(crate_info.output.basename + ".dSYM", sibling = crate_info.output)
             action_outputs.append(dsym_folder)
 
@@ -1306,7 +1302,7 @@
         # a (lib)foo_bar output file.
         if crate_info.type == "cdylib":
             output_lib = crate_info.output.basename
-            if toolchain.os != "windows":
+            if toolchain.target_os != "windows":
                 # Strip the leading "lib" prefix
                 output_lib = output_lib[3:]
 
@@ -1584,7 +1580,7 @@
 
     # Windows has no rpath equivalent, so always return an empty depset.
     # Fuchsia assembles shared libraries during packaging.
-    if toolchain.os == "windows" or toolchain.os == "fuchsia":
+    if toolchain.target_os == "windows" or toolchain.target_os == "fuchsia":
         return depset([])
 
     dylibs = [
@@ -1600,9 +1596,9 @@
     # without a version of Bazel that includes
     # https://github.com/bazelbuild/bazel/pull/13427. This is known to not be
     # included in Bazel 4.1 and below.
-    if toolchain.os != "linux" and toolchain.os != "darwin":
+    if toolchain.target_os != "linux" and toolchain.target_os != "darwin":
         fail("Runtime linking is not supported on {}, but found {}".format(
-            toolchain.os,
+            toolchain.target_os,
             dep_info.transitive_noncrates,
         ))
 
@@ -1822,10 +1818,10 @@
 
     use_pic = _should_use_pic(cc_toolchain, feature_configuration, crate_type, compilation_mode)
 
-    if toolchain.os == "windows":
+    if toolchain.target_os == "windows":
         make_link_flags = _make_link_flags_windows
         get_lib_name = get_lib_name_for_windows
-    elif toolchain.os.startswith("mac") or toolchain.os.startswith("darwin") or toolchain.os.startswith("ios"):
+    elif toolchain.target_os.startswith(("mac", "darwin", "ios")):
         make_link_flags = _make_link_flags_darwin
         get_lib_name = get_lib_name_default
     else:
diff --git a/rust/private/rustdoc_test.bzl b/rust/private/rustdoc_test.bzl
index 10be63e..e621d20 100644
--- a/rust/private/rustdoc_test.bzl
+++ b/rust/private/rustdoc_test.bzl
@@ -130,7 +130,7 @@
         owner = ctx.label,
     )
 
-    if toolchain.os == "windows":
+    if toolchain.target_os == "windows":
         test_runner = ctx.actions.declare_file(ctx.label.name + ".rustdoc_test.bat")
     else:
         test_runner = ctx.actions.declare_file(ctx.label.name + ".rustdoc_test.sh")
diff --git a/rust/private/utils.bzl b/rust/private/utils.bzl
index dfaf3f3..6cb8b06 100644
--- a/rust/private/utils.bzl
+++ b/rust/private/utils.bzl
@@ -135,7 +135,7 @@
 # so the following doesn't work:
 #     args.add_all(
 #         cc_toolchain.dynamic_runtime_lib(feature_configuration = feature_configuration),
-#         map_each = lambda x: get_lib_name(x, for_windows = toolchain.os.startswith("windows)),
+#         map_each = lambda x: get_lib_name(x, for_windows = toolchain.target_os.startswith("windows)),
 #         format_each = "-ldylib=%s",
 #     )
 def get_lib_name_for_windows(lib):
@@ -679,7 +679,7 @@
     # 3) process_wrapper is enabled (this is disabled when compiling process_wrapper itself),
     # 4) the crate_type is rlib or lib.
     return toolchain._pipelined_compilation and \
-           toolchain.os != "windows" and \
+           toolchain.exec_triple.system != "windows" and \
            ctx.attr._process_wrapper and \
            crate_type in ("rlib", "lib")
 
diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl
index 7ceb6c8..6b2aac7 100644
--- a/rust/toolchain.bzl
+++ b/rust/toolchain.bzl
@@ -559,11 +559,7 @@
 
     exec_triple = triple(ctx.attr.exec_triple)
 
-    exec_os = ctx.attr.os
-    if not ctx.attr.os:
-        exec_os = exec_triple.system
-
-    if not exec_os:
+    if not exec_triple.system:
         fail("No system was provided for the execution platform. Please update {}".format(
             ctx.label,
         ))
@@ -576,10 +572,12 @@
     target_triple = None
     target_json = None
     target_arch = None
+    target_os = None
 
     if ctx.attr.target_triple:
         target_triple = triple(ctx.attr.target_triple)
         target_arch = target_triple.arch
+        target_os = target_triple.system
 
     elif ctx.attr.target_json:
         # Ensure the data provided is valid json
@@ -593,6 +591,8 @@
 
         if "arch" in target_json_content:
             target_arch = target_json_content["arch"]
+        if "os" in target_json_content:
+            target_os = target_json_content["os"]
     else:
         fail("Either `target_triple` or `target_json` must be provided. Please update {}".format(
             ctx.label,
@@ -615,7 +615,6 @@
         llvm_cov = ctx.file.llvm_cov,
         llvm_profdata = ctx.file.llvm_profdata,
         make_variables = make_variable_info,
-        os = exec_os,
         rust_doc = sysroot.rustdoc,
         rust_std = sysroot.rust_std,
         rust_std_paths = depset([file.dirname for file in sysroot.rust_std.to_list()]),
@@ -632,6 +631,7 @@
         target_arch = target_arch,
         target_flag_value = target_json.path if target_json else target_triple.str,
         target_json = target_json,
+        target_os = target_os,
         target_triple = target_triple,
 
         # Experimental and incompatible flags
@@ -731,9 +731,6 @@
                 "opt": "3",
             },
         ),
-        "os": attr.string(
-            doc = "The operating system for the current toolchain",
-        ),
         "per_crate_rustc_flags": attr.string_list(
             doc = "Extra flags to pass to rustc in non-exec configuration",
         ),
@@ -824,24 +821,27 @@
 
 rust_toolchain(
     name = "rust_cpuX_impl",
+    binary_ext = "",
+    dylib_ext = ".so",
+    exec_triple = "cpuX-unknown-linux-gnu",
+    rust_doc = "@rust_cpuX//:rustdoc",
+    rust_std = "@rust_cpuX//:rust_std",
     rustc = "@rust_cpuX//:rustc",
     rustc_lib = "@rust_cpuX//:rustc_lib",
-    rust_std = "@rust_cpuX//:rust_std",
-    rust_doc = "@rust_cpuX//:rustdoc",
-    binary_ext = "",
     staticlib_ext = ".a",
-    dylib_ext = ".so",
     stdlib_linkflags = ["-lpthread", "-ldl"],
-    os = "linux",
+    target_triple = "cpuX-unknown-linux-gnu",
 )
 
 toolchain(
     name = "rust_cpuX",
     exec_compatible_with = [
         "@platforms//cpu:cpuX",
+        "@platforms//os:linux",
     ],
     target_compatible_with = [
         "@platforms//cpu:cpuX",
+        "@platforms//os:linux",
     ],
     toolchain = ":rust_cpuX_impl",
 )
@@ -850,7 +850,7 @@
 Then, either add the label of the toolchain rule to `register_toolchains` in the WORKSPACE, or pass \
 it to the `"--extra_toolchains"` flag for Bazel, and it will be used.
 
-See @rules_rust//rust:repositories.bzl for examples of defining the @rust_cpuX repository \
+See `@rules_rust//rust:repositories.bzl` for examples of defining the `@rust_cpuX` repository \
 with the actual binaries and libraries.
 """,
 )
diff --git a/test/toolchain/toolchain_test.bzl b/test/toolchain/toolchain_test.bzl
index 04010ec..2b820e7 100644
--- a/test/toolchain/toolchain_test.bzl
+++ b/test/toolchain/toolchain_test.bzl
@@ -121,7 +121,6 @@
         dylib_ext = ".so",
         exec_triple = "x86_64-unknown-none",
         target_triple = "x86_64-unknown-none",
-        os = "linux",
         rust_doc = ":mock_rustdoc",
         rust_std = ":std_libs",
         rustc = ":mock_rustc",
diff --git a/test/unit/toolchain/toolchain_test.bzl b/test/unit/toolchain/toolchain_test.bzl
index 7b0e726..d4056f1 100644
--- a/test/unit/toolchain/toolchain_test.bzl
+++ b/test/unit/toolchain/toolchain_test.bzl
@@ -85,7 +85,6 @@
         binary_ext = "",
         dylib_ext = ".so",
         exec_triple = "x86_64-unknown-none",
-        os = "linux",
         rust_doc = ":mock_rustdoc",
         rust_std = ":std_libs",
         rustc = ":mock_rustc",
@@ -101,7 +100,6 @@
         binary_ext = "",
         dylib_ext = ".so",
         exec_triple = "x86_64-unknown-none",
-        os = "linux",
         rust_doc = ":mock_rustdoc",
         rust_std = ":std_libs",
         rustc = ":mock_rustc",
@@ -115,7 +113,6 @@
         binary_ext = "",
         dylib_ext = ".so",
         exec_triple = "x86_64-unknown-none",
-        os = "linux",
         rust_doc = ":mock_rustdoc",
         rust_std = ":std_libs",
         rustc = ":mock_rustc",
@@ -137,7 +134,6 @@
         binary_ext = "",
         dylib_ext = ".so",
         exec_triple = "x86_64-unknown-none",
-        os = "linux",
         rust_doc = ":mock_rustdoc",
         rust_std = ":std_libs",
         rustc = ":mock_rustc",