Squashed 'third_party/rules_rust/' content from commit bf59038ca

git-subtree-dir: third_party/rules_rust
git-subtree-split: bf59038cac11798cbaef9f3bf965bad8182b97fa
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: I5a20e403203d670df467ea97dde9a4ac40339a8d
diff --git a/rust/platform/BUILD.bazel b/rust/platform/BUILD.bazel
new file mode 100644
index 0000000..459b9fb
--- /dev/null
+++ b/rust/platform/BUILD.bazel
@@ -0,0 +1,26 @@
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+load(":platform.bzl", "declare_config_settings")
+
+package(default_visibility = ["//visibility:public"])
+
+declare_config_settings()
+
+package_group(
+    name = "function_transition_allowlist",
+    packages = [
+        "//...",
+    ],
+)
+
+bzl_library(
+    name = "bzl_lib",
+    srcs = glob(["**/*.bzl"]),
+    visibility = ["//rust:__subpackages__"],
+)
+
+alias(
+    name = "rules",
+    actual = ":bzl_lib",
+    deprecation = "Please use the `@rules_rust//platform:bzl_lib` target instead",
+    visibility = ["//rust:__subpackages__"],
+)
diff --git a/rust/platform/channel/BUILD.bazel b/rust/platform/channel/BUILD.bazel
new file mode 100644
index 0000000..84fc8c7
--- /dev/null
+++ b/rust/platform/channel/BUILD.bazel
@@ -0,0 +1,22 @@
+package(default_visibility = ["//visibility:public"])
+
+# Allows toolchains and targets to constrain themselves based on Rust release
+# channels, for example when depending on features only available in Nightly.
+#
+# https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
+constraint_setting(name = "channel")
+
+constraint_value(
+    name = "beta",
+    constraint_setting = ":channel",
+)
+
+constraint_value(
+    name = "nightly",
+    constraint_setting = ":channel",
+)
+
+constraint_value(
+    name = "stable",
+    constraint_setting = ":channel",
+)
diff --git a/rust/platform/cpu/BUILD.bazel b/rust/platform/cpu/BUILD.bazel
new file mode 100644
index 0000000..476f8cf
--- /dev/null
+++ b/rust/platform/cpu/BUILD.bazel
@@ -0,0 +1,5 @@
+constraint_value(
+    name = "wasm32",
+    constraint_setting = "@platforms//cpu",
+    visibility = ["//visibility:public"],
+)
diff --git a/rust/platform/os/BUILD.bazel b/rust/platform/os/BUILD.bazel
new file mode 100644
index 0000000..7692abe
--- /dev/null
+++ b/rust/platform/os/BUILD.bazel
@@ -0,0 +1,11 @@
+constraint_value(
+    name = "unknown",
+    constraint_setting = "@platforms//os",
+    visibility = ["//visibility:public"],
+)
+
+constraint_value(
+    name = "wasi",
+    constraint_setting = "@platforms//os",
+    visibility = ["//visibility:public"],
+)
diff --git a/rust/platform/platform.bzl b/rust/platform/platform.bzl
new file mode 100644
index 0000000..ca3bef9
--- /dev/null
+++ b/rust/platform/platform.bzl
@@ -0,0 +1,89 @@
+"""Definitions for support config settings and platform definitions"""
+
+load("@bazel_skylib//lib:selects.bzl", "selects")
+load(
+    ":triple_mappings.bzl",
+    "SUPPORTED_PLATFORM_TRIPLES",
+    "cpu_arch_to_constraints",
+    "system_to_constraints",
+    "triple_to_constraint_set",
+)
+
+_SUPPORTED_CPU_ARCH = [
+    "aarch64",
+    "arm",
+    "i686",
+    "powerpc",
+    "s390x",
+    "x86_64",
+]
+
+_SUPPORTED_SYSTEMS = [
+    "android",
+    "darwin",
+    "freebsd",
+    "ios",
+    "linux",
+    "windows",
+]
+
+# buildifier: disable=unnamed-macro
+def declare_config_settings():
+    """Helper function for declaring `config_setting`s"""
+    for cpu_arch in _SUPPORTED_CPU_ARCH:
+        native.config_setting(
+            name = cpu_arch,
+            constraint_values = cpu_arch_to_constraints(cpu_arch),
+        )
+
+    for system in _SUPPORTED_SYSTEMS:
+        native.config_setting(
+            name = system,
+            constraint_values = system_to_constraints(system),
+        )
+
+    # Add alias for OSX to "darwin" to match what users will be expecting.
+    native.alias(
+        name = "osx",
+        actual = ":darwin",
+    )
+
+    # Add alias for OSX to "macos" to be consistent with the long-term
+    # direction of `@platforms` in using the OS's modern name.
+    native.alias(
+        name = "macos",
+        actual = ":darwin",
+    )
+
+    all_supported_triples = SUPPORTED_PLATFORM_TRIPLES
+    for triple in all_supported_triples:
+        native.config_setting(
+            name = triple,
+            constraint_values = triple_to_constraint_set(triple),
+        )
+
+    native.platform(
+        name = "wasm",
+        constraint_values = [
+            str(Label("//rust/platform/cpu:wasm32")),
+            str(Label("//rust/platform/os:unknown")),
+        ],
+    )
+
+    native.platform(
+        name = "wasi",
+        constraint_values = [
+            str(Label("//rust/platform/cpu:wasm32")),
+            str(Label("//rust/platform/os:wasi")),
+        ],
+    )
+
+    selects.config_setting_group(
+        name = "unix",
+        match_any = [
+            ":android",
+            ":darwin",
+            ":freebsd",
+            ":linux",
+        ],
+    )
diff --git a/rust/platform/triple.bzl b/rust/platform/triple.bzl
new file mode 100644
index 0000000..13a59a4
--- /dev/null
+++ b/rust/platform/triple.bzl
@@ -0,0 +1,54 @@
+"""Triples are a way to define information about a platform/system. This module provides
+a way to convert a triple string into a well structured object to avoid constant string
+parsing in starlark code.
+
+Triples can be described at the following link: 
+https://clang.llvm.org/docs/CrossCompilation.html#target-triple
+"""
+
+def triple(triple):
+    """Constructs a struct containing each component of the provided triple
+
+    Args:
+        triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu`
+
+    Returns:
+        struct:
+            - arch (str): The triple's CPU architecture
+            - vendor (str): The vendor of the system
+            - system (str): The name of the system
+            - abi (str, optional): The abi to use or None if abi does not apply.
+            - triple (str): The original triple
+    """
+    if triple == "wasm32-wasi":
+        return struct(
+            arch = "wasm32",
+            system = "wasi",
+            vendor = "wasi",
+            abi = None,
+            triple = triple,
+        )
+
+    component_parts = triple.split("-")
+    if len(component_parts) < 3:
+        fail("Expected target triple to contain at least three sections separated by '-'")
+
+    cpu_arch = component_parts[0]
+    vendor = component_parts[1]
+    system = component_parts[2]
+    abi = None
+
+    if system == "androideabi":
+        system = "android"
+        abi = "eabi"
+
+    if len(component_parts) == 4:
+        abi = component_parts[3]
+
+    return struct(
+        arch = cpu_arch,
+        vendor = vendor,
+        system = system,
+        abi = abi,
+        triple = triple,
+    )
diff --git a/rust/platform/triple_mappings.bzl b/rust/platform/triple_mappings.bzl
new file mode 100644
index 0000000..852ffe7
--- /dev/null
+++ b/rust/platform/triple_mappings.bzl
@@ -0,0 +1,280 @@
+"""Helpers for constructing supported Rust platform triples"""
+
+load("//rust/platform:triple.bzl", "triple")
+
+# All T1 Platforms should be supported, but aren't, see inline notes.
+SUPPORTED_T1_PLATFORM_TRIPLES = [
+    "i686-apple-darwin",
+    "i686-pc-windows-msvc",
+    "i686-unknown-linux-gnu",
+    "x86_64-apple-darwin",
+    "x86_64-pc-windows-msvc",
+    "x86_64-unknown-linux-gnu",
+    # N.B. These "alternative" envs are not supported, as bazel cannot distinguish between them
+    # and others using existing @platforms// config_values
+    #
+    #"i686-pc-windows-gnu",
+    #"x86_64-pc-windows-gnu",
+]
+
+# Some T2 Platforms are supported, provided we have mappings to @platforms// entries.
+# See @rules_rust//rust/platform:triple_mappings.bzl for the complete list.
+SUPPORTED_T2_PLATFORM_TRIPLES = [
+    "aarch64-apple-darwin",
+    "aarch64-apple-ios",
+    "aarch64-linux-android",
+    "aarch64-unknown-linux-gnu",
+    "arm-unknown-linux-gnueabi",
+    "armv7-unknown-linux-gnueabi",
+    "i686-linux-android",
+    "i686-unknown-freebsd",
+    "powerpc-unknown-linux-gnu",
+    "s390x-unknown-linux-gnu",
+    "wasm32-unknown-unknown",
+    "wasm32-wasi",
+    "x86_64-apple-ios",
+    "x86_64-linux-android",
+    "x86_64-unknown-freebsd",
+]
+
+SUPPORTED_PLATFORM_TRIPLES = SUPPORTED_T1_PLATFORM_TRIPLES + SUPPORTED_T2_PLATFORM_TRIPLES
+
+# CPUs that map to a "@platforms//cpu entry
+_CPU_ARCH_TO_BUILTIN_PLAT_SUFFIX = {
+    "aarch64": "aarch64",
+    "arm": "arm",
+    "armv7": "armv7",
+    "armv7s": None,
+    "asmjs": None,
+    "i386": "i386",
+    "i586": None,
+    "i686": "x86_32",
+    "le32": None,
+    "mips": None,
+    "mipsel": None,
+    "powerpc": "ppc",
+    "powerpc64": None,
+    "powerpc64le": None,
+    "s390": None,
+    "s390x": "s390x",
+    "thumbv7m": "armv7",
+    "wasm32": None,
+    "x86_64": "x86_64",
+}
+
+# Systems that map to a "@platforms//os entry
+_SYSTEM_TO_BUILTIN_SYS_SUFFIX = {
+    "android": "android",
+    "bitrig": None,
+    "darwin": "osx",
+    "dragonfly": None,
+    "eabi": "none",
+    "emscripten": None,
+    "freebsd": "freebsd",
+    "ios": "ios",
+    "linux": "linux",
+    "nacl": None,
+    "netbsd": None,
+    "openbsd": "openbsd",
+    "solaris": None,
+    "unknown": None,
+    "wasi": None,
+    "windows": "windows",
+}
+
+_SYSTEM_TO_BINARY_EXT = {
+    "android": "",
+    "darwin": "",
+    "eabi": "",
+    "emscripten": ".js",
+    "freebsd": "",
+    "ios": "",
+    "linux": "",
+    # This is currently a hack allowing us to have the proper
+    # generated extension for the wasm target, similarly to the
+    # windows target
+    "unknown": ".wasm",
+    "wasi": ".wasm",
+    "windows": ".exe",
+}
+
+_SYSTEM_TO_STATICLIB_EXT = {
+    "android": ".a",
+    "darwin": ".a",
+    "eabi": ".a",
+    "emscripten": ".js",
+    "freebsd": ".a",
+    "ios": ".a",
+    "linux": ".a",
+    "unknown": "",
+    "wasi": "",
+    "windows": ".lib",
+}
+
+_SYSTEM_TO_DYLIB_EXT = {
+    "android": ".so",
+    "darwin": ".dylib",
+    "eabi": ".so",
+    "emscripten": ".js",
+    "freebsd": ".so",
+    "ios": ".dylib",
+    "linux": ".so",
+    "unknown": ".wasm",
+    "wasi": ".wasm",
+    "windows": ".dll",
+}
+
+# See https://github.com/rust-lang/rust/blob/master/src/libstd/build.rs
+_SYSTEM_TO_STDLIB_LINKFLAGS = {
+    # NOTE: Rust stdlib `build.rs` treats android as a subset of linux, rust rules treat android
+    # as its own system.
+    "android": ["-ldl", "-llog", "-lgcc"],
+    "bitrig": [],
+    # TODO(gregbowyer): If rust stdlib is compiled for cloudabi with the backtrace feature it
+    # includes `-lunwind` but this might not actually be required.
+    # I am not sure which is the common configuration or how we encode it as a link flag.
+    "cloudabi": ["-lunwind", "-lc", "-lcompiler_rt"],
+    "darwin": ["-lSystem", "-lresolv"],
+    "dragonfly": ["-lpthread"],
+    "eabi": [],
+    "emscripten": [],
+    # TODO(bazelbuild/rules_cc#75):
+    #
+    # Right now bazel cc rules does not specify the exact flag setup needed for calling out system
+    # libs, that is we dont know given a toolchain if it should be, for example,
+    # `-lxxx` or `/Lxxx` or `xxx.lib` etc.
+    #
+    # We include the flag setup as they are _commonly seen_ on various platforms with a cc_rules
+    # style override for people doing things like gnu-mingw on windows.
+    #
+    # If you are reading this ... sorry! set the env var `BAZEL_RUST_STDLIB_LINKFLAGS` to
+    # what you need for your specific setup, for example like so
+    # `BAZEL_RUST_STDLIB_LINKFLAGS="-ladvapi32:-lws2_32:-luserenv"`
+    "freebsd": ["-lexecinfo", "-lpthread"],
+    "fuchsia": ["-lzircon", "-lfdio"],
+    "illumos": ["-lsocket", "-lposix4", "-lpthread", "-lresolv", "-lnsl", "-lumem"],
+    "ios": ["-lSystem", "-lobjc", "-framework Security", "-framework Foundation", "-lresolv"],
+    # TODO: This ignores musl. Longer term what does Bazel think about musl?
+    "linux": ["-ldl", "-lpthread"],
+    "nacl": [],
+    "netbsd": ["-lpthread", "-lrt"],
+    "openbsd": ["-lpthread"],
+    "solaris": ["-lsocket", "-lposix4", "-lpthread", "-lresolv"],
+    "unknown": [],
+    "uwp": ["ws2_32.lib"],
+    "wasi": [],
+    "windows": ["advapi32.lib", "ws2_32.lib", "userenv.lib"],
+}
+
+def cpu_arch_to_constraints(cpu_arch):
+    plat_suffix = _CPU_ARCH_TO_BUILTIN_PLAT_SUFFIX[cpu_arch]
+
+    if not plat_suffix:
+        fail("CPU architecture \"{}\" is not supported by rules_rust".format(cpu_arch))
+
+    return ["@platforms//cpu:{}".format(plat_suffix)]
+
+def vendor_to_constraints(_vendor):
+    # TODO(acmcarther): Review:
+    #
+    # My current understanding is that vendors can't have a material impact on
+    # constraint sets.
+    return []
+
+def system_to_constraints(system):
+    sys_suffix = _SYSTEM_TO_BUILTIN_SYS_SUFFIX[system]
+
+    if not sys_suffix:
+        fail("System \"{}\" is not supported by rules_rust".format(sys_suffix))
+
+    return ["@platforms//os:{}".format(sys_suffix)]
+
+def abi_to_constraints(abi):
+    # iOS simulator
+    if abi == "sim":
+        return ["@build_bazel_apple_support//constraints:simulator"]
+    else:
+        # TODO(acmcarther): Implement when C++ toolchain is more mature and we
+        # figure out how they're doing this
+        return []
+
+def triple_to_system(target_triple):
+    """Returns a system name for a given platform triple
+
+    **Deprecated**: Use triple() from triple.bzl directly.
+
+    Args:
+        target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu`
+
+    Returns:
+        str: A system name
+    """
+    return triple(target_triple).system
+
+def triple_to_arch(target_triple):
+    """Returns a system architecture name for a given platform triple
+
+    **Deprecated**: Use triple() from triple.bzl directly.
+
+    Args:
+        target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu`
+
+    Returns:
+        str: A cpu architecture
+    """
+    return triple(target_triple).arch
+
+def triple_to_abi(target_triple):
+    """Returns a system abi name for a given platform triple
+
+    **Deprecated**: Use triple() from triple.bzl directly.
+
+    Args:
+        target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu`
+
+    Returns:
+        str: The triple's abi
+    """
+    return triple(target_triple).system
+
+def system_to_dylib_ext(system):
+    return _SYSTEM_TO_DYLIB_EXT[system]
+
+def system_to_staticlib_ext(system):
+    return _SYSTEM_TO_STATICLIB_EXT[system]
+
+def system_to_binary_ext(system):
+    return _SYSTEM_TO_BINARY_EXT[system]
+
+def system_to_stdlib_linkflags(system):
+    return _SYSTEM_TO_STDLIB_LINKFLAGS[system]
+
+def triple_to_constraint_set(target_triple):
+    """Returns a set of constraints for a given platform triple
+
+    Args:
+        target_triple (str): A platform triple. eg: `x86_64-unknown-linux-gnu`
+
+    Returns:
+        list: A list of constraints (each represented by a list of strings)
+    """
+    if target_triple == "wasm32-wasi":
+        return [
+            "@rules_rust//rust/platform/cpu:wasm32",
+            "@rules_rust//rust/platform/os:wasi",
+        ]
+    if target_triple == "wasm32-unknown-unknown":
+        return [
+            "@rules_rust//rust/platform/cpu:wasm32",
+            "@rules_rust//rust/platform/os:unknown",
+        ]
+
+    triple_struct = triple(target_triple)
+
+    constraint_set = []
+    constraint_set += cpu_arch_to_constraints(triple_struct.arch)
+    constraint_set += vendor_to_constraints(triple_struct.vendor)
+    constraint_set += system_to_constraints(triple_struct.system)
+    constraint_set += abi_to_constraints(triple_struct.abi)
+
+    return constraint_set