Squashed 'third_party/bazel-toolchain/' content from commit a912bb381

Change-Id: Ie1ff8ed3b3948cca1d1b6227097c95e5a048de86
git-subtree-dir: third_party/bazel-toolchain
git-subtree-split: a912bb381b36437be0eeb22de11f0ea198450b4e
Signed-off-by: Brian Silverman <bsilver16834@gmail.com>
diff --git a/toolchain/BUILD.bazel b/toolchain/BUILD.bazel
new file mode 100644
index 0000000..2cceb2c
--- /dev/null
+++ b/toolchain/BUILD.bazel
@@ -0,0 +1,23 @@
+# Copyright 2018 The Bazel 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
+#
+#     http://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.
+
+# This BUILD file exports the templates and static files needed for dynamic toolchain configuration.
+# See internal/configure.bzl for how they are used.
+
+exports_files(
+    glob(
+        ["*"],
+        exclude = ["BUILD.bazel"],
+    ),
+)
diff --git a/toolchain/BUILD.llvm_repo b/toolchain/BUILD.llvm_repo
new file mode 100644
index 0000000..9920705
--- /dev/null
+++ b/toolchain/BUILD.llvm_repo
@@ -0,0 +1,126 @@
+# Copyright 2021 The Bazel 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
+#
+#     http://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.
+
+package(default_visibility = ["//visibility:public"])
+
+# Some targets may need to directly depend on these files.
+exports_files(glob([
+    "bin/*",
+    "lib/*",
+]))
+
+## LLVM toolchain files
+
+filegroup(
+    name = "clang",
+    srcs = [
+        "bin/clang",
+        "bin/clang++",
+        "bin/clang-cpp",
+    ],
+)
+
+filegroup(
+    name = "ld",
+    srcs = [
+        "bin/ld.lld",
+    ],
+)
+
+filegroup(
+    name = "include",
+    srcs = glob([
+        "include/c++/**",
+        "lib/clang/*/include/**",
+    ]),
+)
+
+filegroup(
+    name = "bin",
+    srcs = glob(["bin/**"]),
+)
+
+filegroup(
+    name = "lib",
+    srcs = glob(
+        [
+            "lib/lib*.a",
+            "lib/clang/*/lib/**/*.a",
+        ],
+        exclude = [
+            "lib/libLLVM*.a",
+            "lib/libclang*.a",
+            "lib/liblld*.a",
+        ],
+    ) + glob(
+        [
+            "lib/lib*.dylib",
+            "lib/clang/*/lib/**/*.dylib",
+        ],
+        allow_empty = True,
+    ),
+)
+
+filegroup(
+    name = "ar",
+    srcs = ["bin/llvm-ar"],
+)
+
+filegroup(
+    name = "as",
+    srcs = [
+        "bin/clang",
+        "bin/llvm-as",
+    ],
+)
+
+filegroup(
+    name = "nm",
+    srcs = ["bin/llvm-nm"],
+)
+
+filegroup(
+    name = "objcopy",
+    srcs = ["bin/llvm-objcopy"],
+)
+
+filegroup(
+    name = "objdump",
+    srcs = ["bin/llvm-objdump"],
+)
+
+filegroup(
+    name = "profdata",
+    srcs = ["bin/llvm-profdata"],
+)
+
+filegroup(
+    name = "dwp",
+    srcs = ["bin/llvm-dwp"],
+)
+
+filegroup(
+    name = "ranlib",
+    srcs = ["bin/llvm-ranlib"],
+)
+
+filegroup(
+    name = "readelf",
+    srcs = ["bin/llvm-readelf"],
+)
+
+filegroup(
+    name = "strip",
+    srcs = ["bin/llvm-strip"],
+)
diff --git a/toolchain/BUILD.toolchain.tpl b/toolchain/BUILD.toolchain.tpl
new file mode 100644
index 0000000..d0335ed
--- /dev/null
+++ b/toolchain/BUILD.toolchain.tpl
@@ -0,0 +1,36 @@
+# Copyright 2018 The Bazel 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
+#
+#     http://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.
+
+package(default_visibility = ["//visibility:public"])
+
+load("@rules_cc//cc:defs.bzl", "cc_toolchain", "cc_toolchain_suite")
+load("%{cc_toolchain_config_bzl}", "cc_toolchain_config")
+
+# Following filegroup targets are used when not using absolute paths and shared
+# between different toolchains.
+
+filegroup(
+    name = "empty",
+    srcs = [],
+)
+
+filegroup(
+    name = "wrapper-files",
+    srcs = [
+        "bin/cc_wrapper.sh",
+        "bin/host_libtool_wrapper.sh",
+    ],
+)
+
+%{cc_toolchains}
diff --git a/toolchain/cc_toolchain_config.bzl b/toolchain/cc_toolchain_config.bzl
new file mode 100644
index 0000000..1f0395b
--- /dev/null
+++ b/toolchain/cc_toolchain_config.bzl
@@ -0,0 +1,303 @@
+# Copyright 2021 The Bazel 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
+#
+#     http://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.
+
+load(
+    "@bazel_tools//tools/cpp:unix_cc_toolchain_config.bzl",
+    unix_cc_toolchain_config = "cc_toolchain_config",
+)
+load(
+    "//toolchain/internal:common.bzl",
+    _check_os_arch_keys = "check_os_arch_keys",
+    _host_tool_features = "host_tool_features",
+    _host_tools = "host_tools",
+    _os_arch_pair = "os_arch_pair",
+)
+
+# Macro for calling cc_toolchain_config from @bazel_tools with setting the
+# right paths and flags for the tools.
+def cc_toolchain_config(
+        name,
+        host_arch,
+        host_os,
+        target_arch,
+        target_os,
+        toolchain_path_prefix,
+        tools_path_prefix,
+        wrapper_bin_prefix,
+        sysroot_path,
+        additional_include_dirs,
+        llvm_version,
+        host_tools_info = {}):
+    host_os_arch_key = _os_arch_pair(host_os, host_arch)
+    target_os_arch_key = _os_arch_pair(target_os, target_arch)
+    _check_os_arch_keys([host_os_arch_key, target_os_arch_key])
+
+    # A bunch of variables that get passed straight through to
+    # `create_cc_toolchain_config_info`.
+    # TODO: What do these values mean, and are they actually all correct?
+    host_system_name = host_arch
+    (
+        toolchain_identifier,
+        target_system_name,
+        target_cpu,
+        target_libc,
+        compiler,
+        abi_version,
+        abi_libc_version,
+    ) = {
+        "darwin-x86_64": (
+            "clang-x86_64-darwin",
+            "x86_64-apple-macosx",
+            "darwin",
+            "macosx",
+            "clang",
+            "darwin_x86_64",
+            "darwin_x86_64",
+        ),
+        "linux-x86_64": (
+            "clang-x86_64-linux",
+            "x86_64-unknown-linux-gnu",
+            "k8",
+            "glibc_unknown",
+            "clang",
+            "clang",
+            "glibc_unknown",
+        ),
+        "linux-aarch64": (
+            "clang-aarch64-linux",
+            "aarch64-unknown-linux-gnu",
+            "aarch64",
+            "glibc_unknown",
+            "clang",
+            "clang",
+            "glibc_unknown",
+        ),
+    }[target_os_arch_key]
+
+    # Unfiltered compiler flags:
+    unfiltered_compile_flags = [
+        # Do not resolve our symlinked resource prefixes to real paths.
+        "-no-canonical-prefixes",
+        # Reproducibility
+        "-Wno-builtin-macro-redefined",
+        "-D__DATE__=\"redacted\"",
+        "-D__TIMESTAMP__=\"redacted\"",
+        "-D__TIME__=\"redacted\"",
+        "-fdebug-prefix-map={}=__bazel_toolchain_llvm_repo__/".format(toolchain_path_prefix),
+    ]
+
+    is_xcompile = not (host_os == target_os and host_arch == target_arch)
+
+    # Default compiler flags:
+    compile_flags = [
+        "--target=" + target_system_name,
+        # Security
+        "-U_FORTIFY_SOURCE",  # https://github.com/google/sanitizers/issues/247
+        "-fstack-protector",
+        "-fno-omit-frame-pointer",
+        # Diagnostics
+        "-fcolor-diagnostics",
+        "-Wall",
+        "-Wthread-safety",
+        "-Wself-assign",
+    ]
+
+    dbg_compile_flags = ["-g", "-fstandalone-debug"]
+
+    opt_compile_flags = [
+        "-g0",
+        "-O2",
+        "-D_FORTIFY_SOURCE=1",
+        "-DNDEBUG",
+        "-ffunction-sections",
+        "-fdata-sections",
+    ]
+
+    link_flags = [
+        "--target=" + target_system_name,
+        "-lm",
+        "-no-canonical-prefixes",
+    ]
+    link_libs = []
+
+    # Linker flags:
+    if host_os == "darwin" and not is_xcompile:
+        # lld is experimental for Mach-O, so we use the native ld64 linker.
+        use_lld = False
+        link_flags.extend([
+            "-headerpad_max_install_names",
+            "-undefined",
+            "dynamic_lookup",
+        ])
+    else:
+        # Note that for xcompiling from darwin to linux, the native ld64 is
+        # not an option because it is not a cross-linker, so lld is the
+        # only option.
+        use_lld = True
+        link_flags.extend([
+            "-fuse-ld=lld",
+            "-Wl,--build-id=md5",
+            "-Wl,--hash-style=gnu",
+            "-Wl,-z,relro,-z,now",
+        ])
+
+    # Flags related to C++ standard.
+    # The linker has no way of knowing if there are C++ objects; so we
+    # always link C++ libraries.
+    if not is_xcompile:
+        cxx_flags = [
+            "-std=c++17",
+            "-stdlib=libc++",
+        ]
+        if use_lld:
+            # For single-platform builds, we can statically link the bundled
+            # libraries.
+            link_flags.extend([
+                "-L{}lib".format(toolchain_path_prefix),
+                "-l:libc++.a",
+                "-l:libc++abi.a",
+                "-l:libunwind.a",
+                # Compiler runtime features.
+                "-rtlib=compiler-rt",
+            ])
+            link_libs.extend([
+                # To support libunwind.
+                "-lpthread",
+                "-ldl",
+            ])
+        else:
+            # TODO: Not sure how to achieve static linking of bundled libraries
+            # with ld64; maybe we don't really need it.
+            link_flags.extend([
+                "-lc++",
+                "-lc++abi",
+            ])
+    else:
+        cxx_flags = [
+            "-std=c++17",
+            "-stdlib=libstdc++",
+        ]
+
+        # For xcompile, we expect to pick up these libraries from the sysroot.
+        link_flags.extend([
+            "-l:libstdc++.a",
+        ])
+
+    opt_link_flags = ["-Wl,--gc-sections"] if target_os == "linux" else []
+
+    # Coverage flags:
+    coverage_compile_flags = ["-fprofile-instr-generate", "-fcoverage-mapping"]
+    coverage_link_flags = ["-fprofile-instr-generate"]
+
+    ## NOTE: framework paths is missing here; unix_cc_toolchain_config
+    ## doesn't seem to have a feature for this.
+
+    # C++ built-in include directories:
+    cxx_builtin_include_directories = [
+        toolchain_path_prefix + "include/c++/v1",
+        toolchain_path_prefix + "lib/clang/{}/include".format(llvm_version),
+        toolchain_path_prefix + "lib64/clang/{}/include".format(llvm_version),
+    ]
+
+    sysroot_prefix = ""
+    if sysroot_path:
+        sysroot_prefix = "%sysroot%"
+    if target_os == "linux":
+        cxx_builtin_include_directories.extend([
+            sysroot_prefix + "/include",
+            sysroot_prefix + "/usr/include",
+            sysroot_prefix + "/usr/local/include",
+        ])
+    elif target_os == "darwin":
+        cxx_builtin_include_directories.extend([
+            sysroot_prefix + "/usr/include",
+            sysroot_prefix + "/System/Library/Frameworks",
+        ])
+    else:
+        fail("Unreachable")
+
+    cxx_builtin_include_directories.extend(additional_include_dirs)
+
+    ## NOTE: make variables are missing here; unix_cc_toolchain_config doesn't
+    ## pass these to `create_cc_toolchain_config_info`.
+
+    # Tool paths:
+    # `llvm-strip` was introduced in V7 (https://reviews.llvm.org/D46407):
+    llvm_version = llvm_version.split(".")
+    llvm_major_ver = int(llvm_version[0]) if len(llvm_version) else 0
+    strip_binary = (tools_path_prefix + "bin/llvm-strip") if llvm_major_ver >= 7 else _host_tools.get_and_assert(host_tools_info, "strip")
+
+    # TODO: The command line formed on darwin does not work with llvm-ar.
+    ar_binary = tools_path_prefix + "bin/llvm-ar"
+    if host_os == "darwin":
+        # Bazel uses arg files for longer commands; some old macOS `libtool`
+        # versions do not support this.
+        #
+        # In these cases we want to use `libtool_wrapper.sh` which translates
+        # the arg file back into command line arguments.
+        if not _host_tools.tool_supports(host_tools_info, "libtool", features = [_host_tool_features.SUPPORTS_ARG_FILE]):
+            ar_binary = wrapper_bin_prefix + "bin/host_libtool_wrapper.sh"
+        else:
+            ar_binary = host_tools_info["libtool"]["path"]
+
+    # The tool names come from [here](https://github.com/bazelbuild/bazel/blob/c7e58e6ce0a78fdaff2d716b4864a5ace8917626/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java#L76-L90):
+    tool_paths = {
+        "ar": ar_binary,
+        "cpp": tools_path_prefix + "bin/clang-cpp",
+        "gcc": wrapper_bin_prefix + "bin/cc_wrapper.sh",
+        "gcov": tools_path_prefix + "bin/llvm-profdata",
+        "ld": tools_path_prefix + "bin/ld.lld" if use_lld else _host_tools.get_and_assert(host_tools_info, "ld"),
+        "llvm-cov": tools_path_prefix + "bin/llvm-cov",
+        "nm": tools_path_prefix + "bin/llvm-nm",
+        "objcopy": tools_path_prefix + "bin/llvm-objcopy",
+        "objdump": tools_path_prefix + "bin/llvm-objdump",
+        "strip": strip_binary,
+        "dwp": tools_path_prefix + "bin/llvm-dwp",
+        "llvm-profdata": tools_path_prefix + "bin/llvm-profdata",
+    }
+
+    # Start-end group linker support:
+    # This was added to `lld` in this patch: http://reviews.llvm.org/D18814
+    #
+    # The oldest version of LLVM that we support is 6.0.0 which was released
+    # after the above patch was merged, so we just set this to `True` when
+    # `lld` is being used as the linker.
+    supports_start_end_lib = use_lld
+
+    # Source: https://cs.opensource.google/bazel/bazel/+/master:tools/cpp/unix_cc_toolchain_config.bzl
+    unix_cc_toolchain_config(
+        name = name,
+        cpu = target_cpu,
+        compiler = compiler,
+        toolchain_identifier = toolchain_identifier,
+        host_system_name = host_system_name,
+        target_system_name = target_system_name,
+        target_libc = target_libc,
+        abi_version = abi_version,
+        abi_libc_version = abi_libc_version,
+        cxx_builtin_include_directories = cxx_builtin_include_directories,
+        tool_paths = tool_paths,
+        compile_flags = compile_flags,
+        dbg_compile_flags = dbg_compile_flags,
+        opt_compile_flags = opt_compile_flags,
+        cxx_flags = cxx_flags,
+        link_flags = link_flags,
+        link_libs = link_libs,
+        opt_link_flags = opt_link_flags,
+        unfiltered_compile_flags = unfiltered_compile_flags,
+        coverage_compile_flags = coverage_compile_flags,
+        coverage_link_flags = coverage_link_flags,
+        supports_start_end_lib = supports_start_end_lib,
+        builtin_sysroot = sysroot_path,
+    )
diff --git a/toolchain/cc_wrapper.sh.tpl b/toolchain/cc_wrapper.sh.tpl
new file mode 100644
index 0000000..6be2fbb
--- /dev/null
+++ b/toolchain/cc_wrapper.sh.tpl
@@ -0,0 +1,48 @@
+#!/bin/bash
+#
+# Copyright 2021 The Bazel Authors. All rights reserved.
+#
+# 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
+#
+#    http://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.
+#
+# OS X relpath is not really working. This is a wrapper script around gcc
+# to simulate relpath behavior.
+#
+# This wrapper uses install_name_tool to replace all paths in the binary
+# (bazel-out/.../path/to/original/library.so) by the paths relative to
+# the binary. It parses the command line to behave as rpath is supposed
+# to work.
+#
+# See https://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac
+# on how to set those paths for Mach-O binaries.
+#
+set -eu
+
+# See note in toolchain/internal/configure.bzl where we define
+# `wrapper_bin_prefix` for why this wrapper is needed.
+
+# Call the C++ compiler.
+if [[ -f %{toolchain_path_prefix}bin/clang ]]; then
+  exec %{toolchain_path_prefix}bin/clang "$@"
+elif [[ "${BASH_SOURCE[0]}" == "/"* ]]; then
+  # Some consumers of `CcToolchainConfigInfo` (e.g. `cmake` from rules_foreign_cc)
+  # change CWD and call $CC (this script) with its absolute path.
+  # the execroot (i.e. `cmake` from `rules_foreign_cc`) and call CC . For cases like this,
+  # we'll try to find `clang` relative to this script.
+  # This script is at _execroot_/external/_repo_name_/bin/clang_wrapper.sh
+  execroot_path="${BASH_SOURCE[0]%/*/*/*/*}"
+  clang="${execroot_path}/%{toolchain_path_prefix}bin/clang"
+  exec "${clang}" "${@}"
+else
+  >&2 echo "ERROR: could not find clang; PWD=\"$(pwd)\"; PATH=\"${PATH}\"."
+  exit 5
+fi
diff --git a/toolchain/deps.bzl b/toolchain/deps.bzl
new file mode 100644
index 0000000..bb6f826
--- /dev/null
+++ b/toolchain/deps.bzl
@@ -0,0 +1,25 @@
+# Copyright 2020 The Bazel 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
+#
+#     http://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.
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+def bazel_toolchain_dependencies():
+    # Load rules_cc if the user has not defined them.
+    if not native.existing_rule("rules_cc"):
+        http_archive(
+            name = "rules_cc",
+            sha256 = "b6f34b3261ec02f85dbc5a8bdc9414ce548e1f5f67e000d7069571799cb88b25",
+            strip_prefix = "rules_cc-726dd8157557f1456b3656e26ab21a1646653405",
+            urls = ["https://github.com/bazelbuild/rules_cc/archive/726dd8157557f1456b3656e26ab21a1646653405.tar.gz"],
+        )
diff --git a/toolchain/host_libtool_wrapper.sh.tpl b/toolchain/host_libtool_wrapper.sh.tpl
new file mode 100644
index 0000000..ffef52d
--- /dev/null
+++ b/toolchain/host_libtool_wrapper.sh.tpl
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+# Some older `libtool` versions (~macOS 10.12) don't support arg files.
+#
+# This script flattens arg files into regular command line arguments.
+
+args=()
+for a in "${@}"; do
+  if [[ ${a} =~ @.* ]]; then
+    IFS=$'\n' read -d '' -r -a args_in_file < "${a:1}"
+    for arg in "${args_in_file[@]}"; do
+        args+=("${arg}")
+    done
+  else
+    args+=("${a}")
+  fi
+done
+
+exec "%{libtool_path}" "${args[@]}"
diff --git a/toolchain/internal/BUILD.bazel b/toolchain/internal/BUILD.bazel
new file mode 100644
index 0000000..622eeb9
--- /dev/null
+++ b/toolchain/internal/BUILD.bazel
@@ -0,0 +1,13 @@
+# Copyright 2018 The Bazel 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
+#
+#     http://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.
diff --git a/toolchain/internal/common.bzl b/toolchain/internal/common.bzl
new file mode 100644
index 0000000..a0e73c9
--- /dev/null
+++ b/toolchain/internal/common.bzl
@@ -0,0 +1,186 @@
+# Copyright 2021 The Bazel 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
+#
+#     http://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.
+
+SUPPORTED_TARGETS = [("linux", "x86_64"), ("linux", "aarch64"), ("darwin", "x86_64")]
+
+host_tool_features = struct(
+    SUPPORTS_ARG_FILE = "supports_arg_file",
+)
+
+def python(rctx):
+    # Get path of the python interpreter.
+
+    python3 = rctx.which("python3")
+    python = rctx.which("python")
+    python2 = rctx.which("python2")
+    if python3:
+        return python3
+    elif python:
+        return python
+    elif python2:
+        return python2
+    else:
+        fail("python not found")
+
+def os(rctx):
+    name = rctx.os.name
+    if name == "linux":
+        return "linux"
+    elif name == "mac os x":
+        return "darwin"
+    elif name.startswith("windows"):
+        return "windows"
+    fail("Unsupported OS: " + name)
+
+def os_bzl(os):
+    # Return the OS string as used in bazel platform constraints.
+    return {"darwin": "osx", "linux": "linux"}[os]
+
+def arch(rctx):
+    exec_result = rctx.execute([
+        python(rctx),
+        "-c",
+        "import platform; print(platform.machine())",
+    ])
+    if exec_result.return_code:
+        fail("Failed to detect machine architecture: \n%s\n%s" % (exec_result.stdout, exec_result.stderr))
+    return exec_result.stdout.strip()
+
+# Tries to figure out if a tool supports newline separated arg files (i.e.
+# `@file`).
+def _tool_supports_arg_file(rctx, tool_path):
+    # We assume nothing other than that `tool_path` is an executable.
+    #
+    # First we have to find out what command line flag gets the tool to just
+    # print out some text and exit successfully.
+    #
+    # Most tools support `-v` or `--version` or (for `libtool`) `-V` but some
+    # tools don't have such an option (BSD `ranlib` and `ar`, for example).
+    #
+    # We just try all the options we know of until one works and if none work
+    # we return "None" indicating an indeterminate result.
+    opts = (
+        ["-v", "--version", "-version", "-V"] +
+        ["-h", "--help", "-help", "-H"]
+    )
+
+    no_op_opt = None
+    for opt in opts:
+        if rctx.execute([tool_path, opt], timeout = 2).return_code == 0:
+            no_op_opt = opt
+            break
+
+    if no_op_opt == None:
+        return None
+
+    # Okay! Once we have an opt that we *know* does nothing but make the
+    # executable exit successfully, we'll stick that opt in a file and try
+    # again:
+    tmp_file = "tmp-arg-file"
+    rctx.file(tmp_file, content = "{}\n".format(no_op_opt), executable = False)
+
+    res = rctx.execute([tool_path, "@{}".format(tmp_file)]).return_code == 0
+    rctx.delete(tmp_file)
+
+    return res
+
+def _get_host_tool_info(rctx, tool_path, features_to_test = [], tool_key = None):
+    if tool_key == None:
+        tool_key = tool_path
+
+    if tool_path == None or not rctx.path(tool_path).exists:
+        return {}
+
+    f = host_tool_features
+    features = {}
+    for feature in features_to_test:
+        features[feature] = {
+            f.SUPPORTS_ARG_FILE: _tool_supports_arg_file,
+        }[feature](rctx, tool_path)
+
+    return {
+        tool_key: struct(
+            path = tool_path,
+            features = features,
+        ),
+    }
+
+def _extract_tool_path_and_features(tool_info):
+    # Have to support structs or dicts:
+    tool_path = tool_info.path if type(tool_info) == "struct" else tool_info["path"]
+    tool_features = tool_info.features if type(tool_info) == "struct" else tool_info["features"]
+
+    return (tool_path, tool_features)
+
+def _check_host_tool_supports(host_tool_info, tool_key, features = []):
+    if tool_key in host_tool_info:
+        _, tool_features = _extract_tool_path_and_features(host_tool_info[tool_key])
+
+        for f in features:
+            if not f in tool_features or not tool_features[f]:
+                return False
+
+        return True
+    else:
+        return False
+
+def _get_host_tool_and_assert_supports(host_tool_info, tool_key, features = []):
+    if tool_key in host_tool_info:
+        tool_path, tool_features = _extract_tool_path_and_features(host_tool_info[tool_key])
+
+        missing = [f for f in features if not f in tool_features or not tool_features[f]]
+
+        if missing:
+            fail("Host tool `{key}` (`{path}`) is missing these features: `{missing}`.".format(
+                key = tool_key,
+                path = tool_path,
+                missing = missing,
+            ))
+
+        return tool_path
+    else:
+        return False
+
+host_tools = struct(
+    get_tool_info = _get_host_tool_info,
+    tool_supports = _check_host_tool_supports,
+    get_and_assert = _get_host_tool_and_assert_supports,
+)
+
+def os_arch_pair(os, arch):
+    return "{}-{}".format(os, arch)
+
+_supported_os_arch = [os_arch_pair(os, arch) for (os, arch) in SUPPORTED_TARGETS]
+
+def supported_os_arch_keys():
+    return _supported_os_arch
+
+def check_os_arch_keys(keys):
+    for k in keys:
+        if k and k not in _supported_os_arch:
+            fail("Unsupported {{os}}-{{arch}} key: {key}; valid keys are: {keys}".format(
+                key = k,
+                keys = ", ".join(_supported_os_arch),
+            ))
+
+def canonical_dir_path(path):
+    if not path.endswith("/"):
+        return path + "/"
+    return path
+
+def pkg_path_from_label(label):
+    if label.workspace_root:
+        return label.workspace_root + "/" + label.package
+    else:
+        return label.package
diff --git a/toolchain/internal/configure.bzl b/toolchain/internal/configure.bzl
new file mode 100644
index 0000000..3aba341
--- /dev/null
+++ b/toolchain/internal/configure.bzl
@@ -0,0 +1,376 @@
+# Copyright 2018 The Bazel 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
+#
+#     http://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.
+
+load(
+    "//toolchain/internal:common.bzl",
+    _arch = "arch",
+    _canonical_dir_path = "canonical_dir_path",
+    _check_os_arch_keys = "check_os_arch_keys",
+    _host_tool_features = "host_tool_features",
+    _host_tools = "host_tools",
+    _os = "os",
+    _os_arch_pair = "os_arch_pair",
+    _os_bzl = "os_bzl",
+    _pkg_path_from_label = "pkg_path_from_label",
+    _supported_targets = "SUPPORTED_TARGETS",
+)
+load(
+    "//toolchain/internal:sysroot.bzl",
+    _default_sysroot_path = "default_sysroot_path",
+    _sysroot_path = "sysroot_path",
+)
+
+def _include_dirs_str(rctx, key):
+    dirs = rctx.attr.cxx_builtin_include_directories.get(key)
+    if not dirs:
+        return ""
+    return ("\n" + 12 * " ").join(["\"%s\"," % d for d in dirs])
+
+def llvm_config_impl(rctx):
+    _check_os_arch_keys(rctx.attr.toolchain_roots)
+    _check_os_arch_keys(rctx.attr.sysroot)
+    _check_os_arch_keys(rctx.attr.cxx_builtin_include_directories)
+
+    os = _os(rctx)
+    if os == "windows":
+        rctx.file("BUILD.bazel")
+        rctx.file("toolchains.bzl", """\
+def llvm_register_toolchains():
+    pass
+""")
+        return
+    arch = _arch(rctx)
+
+    key = _os_arch_pair(os, arch)
+    toolchain_root = rctx.attr.toolchain_roots.get(key)
+    if not toolchain_root:
+        toolchain_root = rctx.attr.toolchain_roots.get("")
+    if not toolchain_root:
+        fail("LLVM toolchain root missing for ({}, {})", os, arch)
+
+    # Check if the toolchain root is an absolute path.
+    use_absolute_paths = rctx.attr.absolute_paths
+    if toolchain_root[0] == "/" and (len(toolchain_root) == 1 or toolchain_root[1] != "/"):
+        use_absolute_paths = True
+
+    if use_absolute_paths:
+        llvm_repo_label = Label(toolchain_root + ":BUILD.bazel")  # Exact target does not matter.
+        llvm_repo_path = _canonical_dir_path(str(rctx.path(llvm_repo_label).dirname))
+        config_repo_path = _canonical_dir_path(str(rctx.path("")))
+        toolchain_path_prefix = llvm_repo_path
+        tools_path_prefix = llvm_repo_path
+        wrapper_bin_prefix = config_repo_path
+    else:
+        llvm_repo_path = _pkg_path_from_label(Label(toolchain_root + ":BUILD.bazel"))
+        config_repo_path = "external/%s/" % rctx.name
+
+        # tools can only be defined in a subdirectory of config_repo_path,
+        # because their paths are relative to the package defining
+        # cc_toolchain, and cannot contain '..'.
+        # https://github.com/bazelbuild/bazel/issues/7746.  To work around
+        # this, we symlink the llvm repo under the package so all tools (except
+        # clang) can be called with normalized relative paths. For clang
+        # however, using a path with symlinks interferes with the header file
+        # inclusion validation checks, because clang frontend will infer the
+        # InstalledDir to be the symlinked path, and will look for header files
+        # in the symlinked path, but that seems to fail the inclusion
+        # validation check. So we always use a cc_wrapper (which is called
+        # through a normalized relative path), and then call clang with the not
+        # symlinked path from the wrapper.
+        rctx.symlink("../../" + llvm_repo_path, "llvm")
+        toolchain_path_prefix = llvm_repo_path
+        tools_path_prefix = "llvm/"
+        wrapper_bin_prefix = ""
+
+    default_sysroot_path = _default_sysroot_path(rctx, os)
+
+    workspace_name = rctx.name
+    toolchain_info = struct(
+        os = os,
+        arch = arch,
+        toolchain_root = toolchain_root,
+        toolchain_path_prefix = toolchain_path_prefix,
+        tools_path_prefix = tools_path_prefix,
+        wrapper_bin_prefix = wrapper_bin_prefix,
+        additional_include_dirs_dict = rctx.attr.cxx_builtin_include_directories,
+        sysroot_dict = rctx.attr.sysroot,
+        default_sysroot_path = default_sysroot_path,
+        llvm_version = rctx.attr.llvm_version,
+    )
+    host_tools_info = dict([
+        pair
+        for (key, tool_path, features) in [
+            # This is used for macOS hosts:
+            ("libtool", "/usr/bin/libtool", [_host_tool_features.SUPPORTS_ARG_FILE]),
+            # This is used with old (pre 7) LLVM versions:
+            ("strip", "/usr/bin/strip", []),
+            # This is used when lld doesn't support the target platform (i.e.
+            # Mach-O for macOS):
+            ("ld", "/usr/bin/ld", []),
+        ]
+        for pair in _host_tools.get_tool_info(rctx, tool_path, features, key).items()
+    ])
+    cc_toolchains_str, toolchain_labels_str = _cc_toolchains_str(
+        workspace_name,
+        toolchain_info,
+        use_absolute_paths,
+        host_tools_info,
+    )
+
+    # Convenience macro to register all generated toolchains.
+    rctx.template(
+        "toolchains.bzl",
+        Label("//toolchain:toolchains.bzl.tpl"),
+        {
+            "%{toolchain_labels}": toolchain_labels_str,
+        },
+    )
+
+    # BUILD file with all the generated toolchain definitions.
+    rctx.template(
+        "BUILD.bazel",
+        Label("//toolchain:BUILD.toolchain.tpl"),
+        {
+            "%{cc_toolchains}": cc_toolchains_str,
+            "%{cc_toolchain_config_bzl}": str(rctx.attr._cc_toolchain_config_bzl),
+        },
+    )
+
+    # CC wrapper script; see comments near the definition of `wrapper_bin_prefix`.
+    if os == "darwin":
+        cc_wrapper_tpl = "//toolchain:osx_cc_wrapper.sh.tpl"
+    else:
+        cc_wrapper_tpl = "//toolchain:cc_wrapper.sh.tpl"
+    rctx.template(
+        "bin/cc_wrapper.sh",
+        Label(cc_wrapper_tpl),
+        {
+            "%{toolchain_path_prefix}": toolchain_path_prefix,
+        },
+    )
+
+    # libtool wrapper; used if the host libtool doesn't support arg files:
+    rctx.template(
+        "bin/host_libtool_wrapper.sh",
+        Label("//toolchain:host_libtool_wrapper.sh.tpl"),
+        {
+            "%{libtool_path}": "/usr/bin/libtool",
+        },
+    )
+
+def _cc_toolchains_str(
+        workspace_name,
+        toolchain_info,
+        use_absolute_paths,
+        host_tools_info):
+    # Since all the toolchains rely on downloading the right LLVM toolchain for
+    # the host architecture, we don't need to explicitly specify
+    # `exec_compatible_with` attribute. If the host and execution platform are
+    # not the same, then host auto-detection based LLVM download does not work
+    # and the user has to explicitly specify the distribution of LLVM they
+    # want.
+
+    # Note that for cross-compiling, the toolchain configuration will need
+    # appropriate sysroots. A recommended approach is to configure two
+    # `llvm_toolchain` repos, one without sysroots (for easy single platform
+    # builds) and register this one, and one with sysroots and provide
+    # `--extra_toolchains` flag when cross-compiling.
+
+    cc_toolchains_str = ""
+    toolchain_names = []
+    for (target_os, target_arch) in _supported_targets:
+        suffix = "{}-{}".format(target_arch, target_os)
+        cc_toolchain_str = _cc_toolchain_str(
+            suffix,
+            target_os,
+            target_arch,
+            toolchain_info,
+            use_absolute_paths,
+            host_tools_info,
+        )
+        if cc_toolchain_str:
+            cc_toolchains_str = cc_toolchains_str + cc_toolchain_str
+            toolchain_name = "@{}//:cc-toolchain-{}".format(workspace_name, suffix)
+            toolchain_names.append(toolchain_name)
+
+    sep = ",\n" + " " * 8  # 2 tabs with tabstop=4.
+    toolchain_labels_str = sep.join(["\"{}\"".format(d) for d in toolchain_names])
+    return cc_toolchains_str, toolchain_labels_str
+
+def _cc_toolchain_str(
+        suffix,
+        target_os,
+        target_arch,
+        toolchain_info,
+        use_absolute_paths,
+        host_tools_info):
+    host_os = toolchain_info.os
+    host_arch = toolchain_info.arch
+
+    host_os_bzl = _os_bzl(host_os)
+    target_os_bzl = _os_bzl(target_os)
+
+    sysroot_path, sysroot = _sysroot_path(
+        toolchain_info.sysroot_dict,
+        target_os,
+        target_arch,
+    )
+    if not sysroot_path:
+        if host_os == target_os and host_arch == target_arch:
+            # For darwin -> darwin, we can use the macOS SDK path.
+            sysroot_path = toolchain_info.default_sysroot_path
+        else:
+            # We are trying to cross-compile without a sysroot, let's bail.
+            # TODO: Are there situations where we can continue?
+            return ""
+
+    extra_files_str = ", \":llvm\", \":wrapper-files\""
+
+    additional_include_dirs = toolchain_info.additional_include_dirs_dict.get(_os_arch_pair(target_os, target_arch))
+    additional_include_dirs_str = "[]"
+    if additional_include_dirs:
+        additional_include_dirs_str = "[{}]".format(
+            ", ".join(["\"{}\"".format(d) for d in additional_include_dirs]),
+        )
+
+    sysroot_label_str = "\"%s\"" % str(sysroot) if sysroot else ""
+
+    # `struct` isn't allowed in `BUILD` files so we JSON encode + decode to turn
+    # them into `dict`s.
+    host_tools_info = json.decode(json.encode(host_tools_info))
+
+    template = """
+# CC toolchain for cc-clang-{suffix}.
+
+cc_toolchain_config(
+    name = "local-{suffix}",
+    host_arch = "{host_arch}",
+    host_os = "{host_os}",
+    target_arch = "{target_arch}",
+    target_os = "{target_os}",
+    toolchain_path_prefix = "{toolchain_path_prefix}",
+    tools_path_prefix = "{tools_path_prefix}",
+    wrapper_bin_prefix = "{wrapper_bin_prefix}",
+    sysroot_path = "{sysroot_path}",
+    additional_include_dirs = {additional_include_dirs_str},
+    llvm_version = "{llvm_version}",
+    host_tools_info = {host_tools_info},
+)
+
+toolchain(
+    name = "cc-toolchain-{suffix}",
+    exec_compatible_with = [
+        "@platforms//cpu:{host_arch}",
+        "@platforms//os:{host_os_bzl}",
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:{target_arch}",
+        "@platforms//os:{target_os_bzl}",
+    ],
+    toolchain = ":cc-clang-{suffix}",
+    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+)
+"""
+
+    if use_absolute_paths:
+        template = template + """
+cc_toolchain(
+    name = "cc-clang-{suffix}",
+    all_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    toolchain_config = "local-{suffix}",
+)
+"""
+    else:
+        template = template + """
+filegroup(
+    name = "sysroot-components-{suffix}",
+    srcs = [{sysroot_label_str}],
+)
+
+filegroup(
+    name = "compiler-components-{suffix}",
+    srcs = [
+        "{toolchain_root}:clang",
+        "{toolchain_root}:include",
+        ":sysroot-components-{suffix}",
+    ],
+)
+
+filegroup(
+    name = "linker-components-{suffix}",
+    srcs = [
+        "{toolchain_root}:clang",
+        "{toolchain_root}:ld",
+        "{toolchain_root}:ar",
+        "{toolchain_root}:lib",
+        ":sysroot-components-{suffix}",
+    ],
+)
+
+filegroup(
+    name = "all-components-{suffix}",
+    srcs = [
+        "{toolchain_root}:bin",
+        ":compiler-components-{suffix}",
+        ":linker-components-{suffix}",
+    ],
+)
+
+filegroup(name = "all-files-{suffix}", srcs = [":all-components-{suffix}"{extra_files_str}])
+filegroup(name = "archiver-files-{suffix}", srcs = ["{toolchain_root}:ar"{extra_files_str}])
+filegroup(name = "assembler-files-{suffix}", srcs = ["{toolchain_root}:as"{extra_files_str}])
+filegroup(name = "compiler-files-{suffix}", srcs = [":compiler-components-{suffix}"{extra_files_str}])
+filegroup(name = "dwp-files-{suffix}", srcs = ["{toolchain_root}:dwp"{extra_files_str}])
+filegroup(name = "linker-files-{suffix}", srcs = [":linker-components-{suffix}"{extra_files_str}])
+filegroup(name = "objcopy-files-{suffix}", srcs = ["{toolchain_root}:objcopy"{extra_files_str}])
+filegroup(name = "strip-files-{suffix}", srcs = ["{toolchain_root}:strip"{extra_files_str}])
+
+cc_toolchain(
+    name = "cc-clang-{suffix}",
+    all_files = "all-files-{suffix}",
+    ar_files = "archiver-files-{suffix}",
+    as_files = "assembler-files-{suffix}",
+    compiler_files = "compiler-files-{suffix}",
+    dwp_files = "dwp-files-{suffix}",
+    linker_files = "linker-files-{suffix}",
+    objcopy_files = "objcopy-files-{suffix}",
+    strip_files = "strip-files-{suffix}",
+    toolchain_config = "local-{suffix}",
+)
+"""
+
+    return template.format(
+        suffix = suffix,
+        target_os = target_os,
+        target_arch = target_arch,
+        host_os = host_os,
+        host_arch = host_arch,
+        target_os_bzl = target_os_bzl,
+        host_os_bzl = host_os_bzl,
+        toolchain_root = toolchain_info.toolchain_root,
+        toolchain_path_prefix = toolchain_info.toolchain_path_prefix,
+        tools_path_prefix = toolchain_info.tools_path_prefix,
+        wrapper_bin_prefix = toolchain_info.wrapper_bin_prefix,
+        additional_include_dirs_str = additional_include_dirs_str,
+        sysroot_label_str = sysroot_label_str,
+        sysroot_path = sysroot_path,
+        llvm_version = toolchain_info.llvm_version,
+        extra_files_str = extra_files_str,
+        host_tools_info = host_tools_info,
+    )
diff --git a/toolchain/internal/llvm_distributions.bzl b/toolchain/internal/llvm_distributions.bzl
new file mode 100644
index 0000000..8d3441b
--- /dev/null
+++ b/toolchain/internal/llvm_distributions.bzl
@@ -0,0 +1,260 @@
+# Copyright 2018 The Bazel 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
+#
+#     http://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.
+
+load("@bazel_tools//tools/build_defs/repo:utils.bzl", "read_netrc", "use_netrc")
+load("//toolchain/internal:common.bzl", _python = "python")
+
+# If a new LLVM version is missing from this list, please add the shasum here
+# and send a PR on github. To compute the shasum block, you can use the script
+# utils/llvm_checksums.sh
+_llvm_distributions = {
+    # 6.0.0
+    "clang+llvm-6.0.0-aarch64-linux-gnu.tar.xz": "69382758842f29e1f84a41208ae2fd0fae05b5eb7f5531cdab97f29dda3c2334",
+    "clang+llvm-6.0.0-amd64-unknown-freebsd-10.tar.xz": "fee8352f5dee2e38fa2bb80ab0b5ef9efef578cbc6892e5c724a1187498119b7",
+    "clang+llvm-6.0.0-armv7a-linux-gnueabihf.tar.xz": "4fda22e3d80994f343bfbdcae60f75e63ad44eb0998c59c559d706c11dd87b76",
+    "clang+llvm-6.0.0-i386-unknown-freebsd-10.tar.xz": "13414a66b680760171e04f32071396eb6e5a179ff0b5a067d48c4b23744840f1",
+    "clang+llvm-6.0.0-i686-linux-gnu-Fedora27.tar.xz": "2619e0a2542eec997daed3c7e597d99d5800cc3a07500b359429541a260d0207",
+    "clang+llvm-6.0.0-mips-linux-gnu.tar.xz": "39820007ef6b2e3a4d05ec15feb477ce6e4e6e90180d00326e6ab9982ed8fe82",
+    "clang+llvm-6.0.0-mipsel-linux-gnu.tar.xz": "5ff062f4838ac51a3500383faeb0731440f1c4473bf892258314a49cbaa66e61",
+    "clang+llvm-6.0.0-x86_64-apple-darwin.tar.xz": "0ef8e99e9c9b262a53ab8f2821e2391d041615dd3f3ff36fdf5370916b0f4268",
+    "clang+llvm-6.0.0-x86_64-linux-gnu-Fedora27.tar.xz": "2aada1f1a973d5d4d99a30700c4b81436dea1a2dcba8dd965acf3318d3ea29bb",
+    "clang+llvm-6.0.0-x86_64-linux-gnu-debian8.tar.xz": "ff55cd0bdd0b67e22d1feee2e4c84dedc3bb053401330b64c7f6ac18e88a71f1",
+    "clang+llvm-6.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz": "114e78b2f6db61aaee314c572e07b0d635f653adc5d31bd1cd0bf31a3db4a6e5",
+    "clang+llvm-6.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "cc99fda45b4c740f35d0a367985a2bf55491065a501e2dd5d1ad3f97dcac89da",
+    "clang+llvm-6.0.0-x86_64-linux-sles11.3.tar.xz": "1d4d30ebe4a7e5579644235b46513a1855d3ece865f7cc5ccd0ac5113c461ee7",
+    "clang+llvm-6.0.0-x86_64-linux-sles12.2.tar.xz": "c144e17aab8dce8e8823a7a891067e27fd0686a49d8a3785cb64b0e51f08e2ee",
+
+    # 6.0.1
+    "clang+llvm-6.0.1-amd64-unknown-freebsd10.tar.xz": "6d1f67c9e7c3481106d5c9bfcb8a75e3876eb17a446a14c59c13cafd000c21d2",
+    "clang+llvm-6.0.1-i386-unknown-freebsd10.tar.xz": "c6f65f2c42fa02e3b7e508664ded9b7a91ebafefae368dfa84b3d68811bcb924",
+    "clang+llvm-6.0.1-x86_64-linux-gnu-ubuntu-14.04.tar.xz": "fa5416553ca94a8c071a27134c094a5fb736fe1bd0ecc5ef2d9bc02754e1bef0",
+    "clang+llvm-6.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "7ea204ecd78c39154d72dfc0d4a79f7cce1b2264da2551bb2eef10e266d54d91",
+    "clang+llvm-6.0.1-x86_64-linux-sles11.3.tar.xz": "d128e2a7ea8b42418ec58a249e886ec2c736cbbbb08b9e11f64eb281b62bc574",
+    "clang+llvm-6.0.1-x86_64-linux-sles12.3.tar.xz": "79c74f4764d13671285412d55da95df42b4b87064785cde3363f806dbb54232d",
+
+    # 7.0.0
+    "clang+llvm-7.0.0-amd64-unknown-freebsd-10.tar.xz": "95ceb933ccf76e3ddaa536f41ab82c442bbac07cdea6f9fbf6e3b13cc1711255",
+    "clang+llvm-7.0.0-i386-unknown-freebsd-10.tar.xz": "35460d34a8b3d856e0d7c0b2b20d31f0d1ec05908c830a81f586721e8f8fb04f",
+    "clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz": "b3ad93c3d69dfd528df9c5bb1a434367babb8f3baea47fbb99bf49f1b03c94ca",
+    "clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz": "5c90e61b06d37270bc26edb305d7e498e2c7be22d99e0afd9f2274ef5458575a",
+    "clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "69b85c833cd28ea04ce34002464f10a6ad9656dd2bba0f7133536a9927c660d2",
+    "clang+llvm-7.0.0-x86_64-linux-sles11.3.tar.xz": "1a0a94a5cef357b885d02cf46b66109b6233f0af8f02be3da08e2daf646b5cf8",
+    "clang+llvm-7.0.0-x86_64-linux-sles12.3.tar.xz": "1c303f1a7b90f0f1988387dfab16f1eadbe2b2152d86a323502068379941dd17",
+
+    # 8.0.0
+    "clang+llvm-8.0.0-aarch64-linux-gnu.tar.xz": "998e9ae6e89bd3f029ed031ad9355c8b43441302c0e17603cf1de8ee9939e5c9",
+    "clang+llvm-8.0.0-amd64-unknown-freebsd11.tar.xz": "af15d14bd25e469e35ed7c43cb7e035bc1b2aa7b55d26ad597a43e72768750a8",
+    "clang+llvm-8.0.0-armv7a-linux-gnueabihf.tar.xz": "ddcdc9df5c33b77740e4c27486905c44ecc3c4ec178094febeab60124deb0cc2",
+    "clang+llvm-8.0.0-i386-unknown-freebsd11.tar.xz": "1ba88663ccda4e9fad93f8f35dde7ce04854abc0bcbb1d12a90cdc863e4a77b8",
+    "clang+llvm-8.0.0-x86_64-apple-darwin.tar.xz": "94ebeb70f17b6384e052c47fef24a6d70d3d949ab27b6c83d4ab7b298278ad6f",
+    "clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz": "9ef854b71949f825362a119bf2597f744836cb571131ae6b721cd102ffea8cd0",
+    "clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "87b88d620284d1f0573923e6f7cc89edccf11d19ebaec1cfb83b4f09ac5db09c",
+    "clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz": "0f5c314f375ebd5c35b8c1d5e5b161d9efaeff0523bac287f8b4e5b751272f51",
+    "clang+llvm-8.0.0-x86_64-linux-sles11.3.tar.xz": "7e2846ff60c181d1f27d97c23c25a2295f5730b6d88612ddd53b4cbb8177c4b9",
+
+    # 8.0.1
+    "clang+llvm-8.0.1-aarch64-linux-gnu.tar.xz": "3ca16b5f9e490d6c60712476c51db9d864e7d7f22904c91ad30ba8faee1ede64",
+    "clang+llvm-8.0.1-amd64-unknown-freebsd11.tar.xz": "4ae625169fa0ae56cf534cddc6f8eda76123f89adac0de439d0e47885fccc813",
+    "clang+llvm-8.0.1-armv7a-linux-gnueabihf.tar.xz": "c87b57496f8ec0f0fd74faa1c43b0ac12c156aae54d9be45169fd8f2b33b2181",
+    "clang+llvm-8.0.1-i386-unknown-freebsd11.tar.xz": "f0ab06cce95f9339af3e27e728913414a7b775a5bdb6c90e2a4f67f8cf2a917e",
+    "clang+llvm-8.0.1-powerpc64le-linux-rhel-7.4.tar.xz": "c26676326892119b015286efcd6f485b11c1055717454f6884c4ac5896ad5771",
+    "clang+llvm-8.0.1-powerpc64le-linux-ubuntu-16.04.tar.xz": "7a8a422b360ad649f24e077eeee7098dd1496a82bee81792898f78ced2fe4a17",
+    "clang+llvm-8.0.1-x86_64-linux-gnu-ubuntu-14.04.tar.xz": "0eb70c888c5a67f61e62ae502f4c935e3116e79e5cb3371a3be260f345fe1f16",
+    "clang+llvm-8.0.1-x86_64-linux-sles11.3.tar.xz": "ec5d7fd082137ce5b72c7b4dde9a83c07a7e298773351ab6a0693a8200d0fa0c",
+
+    # 9.0.0
+    "clang+llvm-9.0.0-x86_64-pc-linux-gnu.tar.xz": "616c5f75418c88a72613b6d0a93178028f81357777226869ea6b34c23d08a12d",
+    "clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "5c1473c2611e1eac4ed1aeea5544eac5e9d266f40c5623bbaeb1c6555815a27d",
+    "clang+llvm-9.0.0-amd64-pc-solaris2.11.tar.xz": "86235763496b8174bca8fd1fcec2c99a3a29f8784814acef5c66634f86f81b16",
+    "clang+llvm-9.0.0-powerpc64le-linux-ubuntu-16.04.tar.xz": "a8e7dc00e9eac47ea769eb1f5145e1e28f0610289f07f3275021f0556c169ddf",
+    "clang+llvm-9.0.0-x86_64-linux-sles11.3.tar.xz": "c80b5b10df191465df8cee8c273d9c46715e6f27f80fef118ad4ebb7d9f3a7d3",
+    "clang+llvm-9.0.0-amd64-unknown-freebsd11.tar.xz": "2a1f123a9d992c9719ef7677e127182ca707a5984a929f1c3f34fbb95ffbf6f3",
+    "clang+llvm-9.0.0-powerpc64le-linux-rhel-7.4.tar.xz": "28052539e8e8ad204ee06910a143d992c67fef98662f83fa6f242f65ff29b386",
+    "clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz": "bea706c8f6992497d08488f44e77b8f0f87f5b275295b974aa8b194efba18cb8",
+    "clang+llvm-9.0.0-aarch64-linux-gnu.tar.xz": "f8f3e6bdd640079a140a7ada4eb6f5f05aeae125cf54b94d44f733b0e8691dc2",
+    "clang+llvm-9.0.0-sparcv9-sun-solaris2.11.tar.xz": "7711e4cff908cad47ccab1d2e95bf3c8eb915585999c4e59bb42b10c3c502cfe",
+    "clang+llvm-9.0.0-armv7a-linux-gnueabihf.tar.xz": "ff6046bf98dbc85d7cb0c3c70456bc002b99a809bfc115657db2683ba61752ec",
+    "clang+llvm-9.0.0-i386-unknown-freebsd11.tar.xz": "2d8d0b712946d6bc76317c4093ce77634ef6d502c343e1f3f6b841401db8fa56",
+    "clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz": "a23b082b30c128c9831dbdd96edad26b43f56624d0ad0ea9edec506f5385038d",
+    "clang+llvm-9.0.0-x86_64-darwin-apple.tar.xz": "b46e3fe3829d4eb30ad72993bf28c76b1e1f7e38509fbd44192a2ef7c0126fc7",
+
+    # 10.0.0
+    "clang+llvm-10.0.0-amd64-pc-solaris2.11.tar.xz": "aaf6865542bd772e30be3abf620340a050ed5e4297f8be347e959e5483d9f159",
+    "clang+llvm-10.0.0-powerpc64le-linux-ubuntu-16.04.tar.xz": "2d6298720d6aae7fcada4e909f0949d63e94fd0370d20b8882cdd91ceae7511c",
+    "clang+llvm-10.0.0-x86_64-linux-sles11.3.tar.xz": "a7a3c2a7aff813bb10932636a6f1612e308256a5e6b5a5655068d5c5b7f80e86",
+    "clang+llvm-10.0.0-amd64-unknown-freebsd11.tar.xz": "56d58da545743d5f2947234d413632fd2b840e38f2bed7369f6e65531af36a52",
+    "clang+llvm-10.0.0-powerpc64le-linux-rhel-7.4.tar.xz": "958b8a774eae0bb25515d7fb2f13f5ead1450f768ffdcff18b29739613b3c457",
+    "clang+llvm-10.0.0-aarch64-linux-gnu.tar.xz": "c2072390dc6c8b4cc67737f487ef384148253a6a97b38030e012c4d7214b7295",
+    "clang+llvm-10.0.0-sparcv9-sun-solaris2.11.tar.xz": "725c9205550cabb6d8e0d8b1029176113615809dcc880b347c1577aecdf2af4c",
+    "clang+llvm-10.0.0-armv7a-linux-gnueabihf.tar.xz": "ad136e0d8ce9ac1a341a54513dfd313a7a64c49afa7a69d51cdc2118f7fdc350",
+    "clang+llvm-10.0.0-i386-unknown-freebsd11.tar.xz": "310ed47e957c226b0de17130711505366c225edbed65299ac2c3d59f9a59a41a",
+    "clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz": "b25f592a0c00686f03e3b7db68ca6dc87418f681f4ead4df4745a01d9be63843",
+    "clang+llvm-10.0.0-x86_64-apple-darwin.tar.xz": "633a833396bf2276094c126b072d52b59aca6249e7ce8eae14c728016edb5e61",
+
+    # 10.0.1
+    "clang+llvm-10.0.1-aarch64-linux-gnu.tar.xz": "90dc69a4758ca15cd0ffa45d07fbf5bf4309d47d2c7745a9f0735ecffde9c31f",
+    "clang+llvm-10.0.1-amd64-unknown-freebsd11.tar.xz": "290897c328f75df041d1abda6e25a50c2e6a0a3d939b5069661bb966bf7ac843",
+    "clang+llvm-10.0.1-armv7a-linux-gnueabihf.tar.xz": "adf90157520cd5e0931b9f186bed0f0463feda56370de4eba51766946f57b02b",
+    "clang+llvm-10.0.1-i386-unknown-freebsd11.tar.xz": "f404976ad92cf846b7915cd43cd251e090a5e7524809ab96f5a65216988b2b26",
+    "clang+llvm-10.0.1-powerpc64le-linux-rhel-7.4.tar.xz": "27359cae558905bf190834db11bbeaea433777a360744e9f79bfe69226a19117",
+    "clang+llvm-10.0.1-powerpc64le-linux-ubuntu-16.04.tar.xz": "c19edf5c1f5270ae9124a3873e689a3309a9ad075373a75c0791abf4bf72602e",
+    "clang+llvm-10.0.1-x86_64-apple-darwin.tar.xz": "1154a24597ab77801980dfd5ae4a13c117d6b482bab015baa410aeba443ffd92",
+    "clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "48b83ef827ac2c213d5b64f5ad7ed082c8bcb712b46644e0dc5045c6f462c231",
+    "clang+llvm-10.0.1-x86_64-linux-sles12.4.tar.xz": "59f35fc7967b740315edf31a54b228ae5da8a54f499e37d424d67b7107217ae4",
+
+    # 11.0.0
+    "clang+llvm-11.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "abfe77fa4c2ceda16455fac9dba58962af9173c5aa85d5bb8ca4f5165ef87a19",
+    "clang+llvm-11.0.0-x86_64-linux-sles12.4.tar.xz": "ce3e2e9788e0136f3082eb3199c6e2dd171f4e7c98310f83fc284c5ba734d27a",
+    "clang+llvm-11.0.0-sparcv9-sun-solaris2.11.tar.xz": "3f2bbbbd9aac9809bcc561d73b0db39ecd64fa099fac601f929da5e95a63bdc5",
+    "clang+llvm-11.0.0-x86_64-linux-gnu-ubuntu-20.04.tar.xz": "829f5fb0ebda1d8716464394f97d5475d465ddc7bea2879c0601316b611ff6db",
+    "clang+llvm-11.0.0-amd64-pc-solaris2.11.tar.xz": "031699337d703fe42843a8326f94079fd67e46b60f25be5bdf47664e158e0b43",
+    "clang+llvm-11.0.0-x86_64-apple-darwin.tar.xz": "b93886ab0025cbbdbb08b46e5e403a462b0ce034811c929e96ed66c2b07fe63a",
+
+    # 11.0.1
+    "clang+llvm-11.0.1-aarch64-linux-gnu.tar.xz": "39b3d3e3b534e327d90c77045058e5fc924b1a81d349eac2be6fb80f4a0e40d4",
+    "clang+llvm-11.0.1-amd64-unknown-freebsd11.tar.xz": "cd0a6da1825bc7440c5a8dfa22add4ee91953c45aa0e5597ba1a5caf347f807d",
+    "clang+llvm-11.0.1-amd64-unknown-freebsd12.tar.xz": "2daa205f87d2b81a281f3883c2102cd69ac017193b19ea30f914b57f904c7c4b",
+    "clang+llvm-11.0.1-armv7a-linux-gnueabihf.tar.xz": "5c6b3a1104ac3999c11e18b42c7feca47e0bb894d55b938aba32b1c362402a52",
+    "clang+llvm-11.0.1-i386-unknown-freebsd11.tar.xz": "e32ad587e800145a7868449b1416e25d05a6ca08c071ecc8173cf9e1b0b7dcdd",
+    "clang+llvm-11.0.1-i386-unknown-freebsd12.tar.xz": "46e88ce3a5efef198cade0cf29ee152f3361ca4488fd7701cc79485c06aa93b8",
+    "clang+llvm-11.0.1-powerpc64le-linux-rhel-7.4.tar.xz": "d270ded2cbcb76588bbf71dad2e3657961896bfadf7ff4da57d07870da537873",
+    "clang+llvm-11.0.1-powerpc64le-linux-ubuntu-18.04.tar.xz": "a60a35f6c9f280268df8afe76f4a5349426f8b8eefd40eb885eae80b6e3647d0",
+    "clang+llvm-11.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "67f18660231d7dd09dc93502f712613247b7b4395e6f48c11226629b250b53c5",
+    "clang+llvm-11.0.1-x86_64-linux-gnu-ubuntu-20.10.tar.xz": "b60f68581182ace5f7d4a72e5cce61c01adc88050acb72b2070ad298c25071bc",
+    "clang+llvm-11.0.1-x86_64-linux-sles12.4.tar.xz": "77cd59cf6f932cf2b3c9a68789d1bd3f7ba9f471a28f6ba25e25deb1a0806e0d",
+
+    # 11.1.0
+    "clang+llvm-11.1.0-aarch64-linux-gnu.tar.xz": "18df38247af3fba0e0e2991fb00d7e3cf3560b4d3509233a14af699ef0039e1c",
+    "clang+llvm-11.1.0-amd64-unknown-freebsd11.tar.xz": "645e24018aa2694d8ccb44139f44a0d3af97fa8eab785faecb7a228ebe76ac7e",
+    "clang+llvm-11.1.0-amd64-unknown-freebsd12.tar.xz": "430284b75248ab2dd3ebb8718d8bbb19cc8b9b62f4707ae47a61827b3ba59836",
+    "clang+llvm-11.1.0-armv7a-linux-gnueabihf.tar.xz": "18a3c3aedf1181aa18da3f5d0a2c67366c6d5fb398ac00e461298d9584be5c68",
+    "clang+llvm-11.1.0-i386-unknown-freebsd11.tar.xz": "ddc451c1094d0c8912160912d7c20d28087782758e0a8d145f301a18ddcea558",
+    "clang+llvm-11.1.0-i386-unknown-freebsd12.tar.xz": "3c23d3b97f869382b33878d8a5210056c60d5e749acfeea0354682bb013f5a20",
+    "clang+llvm-11.1.0-powerpc64le-linux-rhel-7.4.tar.xz": "8ff13bb70f1eb8efe61b1899e4d05d6f15c18a14a9ffa883f54f243b060fa778",
+    "clang+llvm-11.1.0-powerpc64le-linux-ubuntu-18.04.tar.xz": "2741183e4ea5fccc86ec2d9ce226edcf00da90b07731b04540edb5025cc695c1",
+    "clang+llvm-11.1.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "c691a558967fb7709fb81e0ed80d1f775f4502810236aa968b4406526b43bee1",
+    "clang+llvm-11.1.0-x86_64-linux-gnu-ubuntu-20.10.tar.xz": "29b07422da4bcea271a88f302e5f84bd34380af137df18e33251b42dd20c26d7",
+
+    # 12.0.0
+    "clang+llvm-12.0.0-armv7a-linux-gnueabihf.tar.xz": "697d432c2572e48fc04118fc7cec63c9477ef2e8a7cca2c0b32e52f9705ab1cc",
+    "clang+llvm-12.0.0-i386-unknown-freebsd11.tar.xz": "8298a026f74165bf6088c1c942c22bd7532b12cd2b916f7673bdaf522abe41b0",
+    "clang+llvm-12.0.0-x86_64-apple-darwin.tar.xz": "7bc2259bf75c003f644882460fc8e844ddb23b27236fe43a2787870a4cd8ab50",
+    "clang+llvm-12.0.0-amd64-unknown-freebsd11.tar.xz": "8ff2ae0863d4cbe88ace6cbcce64a1a6c9a8f1237f635125a5d580b2639bba61",
+    "clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "9694f4df031c614dbe59b8431f94c68631971ad44173eecc1ea1a9e8ee27b2a3",
+    "clang+llvm-12.0.0-aarch64-linux-gnu.tar.xz": "d05f0b04fb248ce1e7a61fcd2087e6be8bc4b06b2cc348792f383abf414dec48",
+    "clang+llvm-12.0.0-amd64-unknown-freebsd12.tar.xz": "0a90d2cf8a3d71d7d4a6bee3e085405ebc37a854311bce82d6845d93b19fcc87",
+    "clang+llvm-12.0.0-x86_64-linux-sles12.4.tar.xz": "00c25261e303080c2e8d55413a73c60913cdb39cfd47587d6817a86fe52565e9",
+    "clang+llvm-12.0.0-i386-unknown-freebsd12.tar.xz": "1e61921735fd11754df193826306f0352c99ca6013e22f40a7fc77f0b20162be",
+    "clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-20.04.tar.xz": "a9ff205eb0b73ca7c86afc6432eed1c2d49133bd0d49e47b15be59bbf0dd292e",
+
+    # 12.0.1
+    "clang+llvm-12.0.1-amd64-unknown-freebsd11.tar.xz": "94dfe48d9e483283edbee968056d487a850b30de25258fa48f049cca3ede5db4",
+    "clang+llvm-12.0.1-amd64-unknown-freebsd12.tar.xz": "38857da36489880b0504ae7142b74abe41cf18711a6bb25ca96792d8190e8b0e",
+    "clang+llvm-12.0.1-i386-unknown-freebsd11.tar.xz": "346e14e5a9189838704f096e65579c8e1915f95dcc291aa7f20626ccf9767e04",
+    "clang+llvm-12.0.1-i386-unknown-freebsd12.tar.xz": "1f3b5e99e82165bf3442120ee3cb2c95ca96129cf45c85a52ec8973f8904529d",
+    "clang+llvm-12.0.1-armv7a-linux-gnueabihf.tar.xz": "1ec685b5026f9cc5e7316a5ff2dffd8ff54ad9941e642df19062cc1359842c86",
+    "clang+llvm-12.0.1-aarch64-linux-gnu.tar.xz": "3d4ad804b7c85007686548cbc917ab067bf17eaedeab43d9eb83d3a683d8e9d4",
+    "clang+llvm-12.0.1-powerpc64le-linux-rhel-7.9.tar.xz": "9849fa17fb7eb666744f1e2ce8dcb5d28753c4c482cc6f5e3d2b5ad2108dc2de",
+    "clang+llvm-12.0.1-powerpc64le-linux-ubuntu-18.04.tar.xz": "271b9605b74d904d3cc05dd6a61e927fd5a46d5f6b7541cdc67186eb02b22e4c",
+    "clang+llvm-12.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "6b3cc55d3ef413be79785c4dc02828ab3bd6b887872b143e3091692fc6acefe7",
+
+    # 13.0.0
+    "clang+llvm-13.0.0-amd64-unknown-freebsd12.tar.xz": "e579747a36ff78aa0a5533fe43bc1ed1f8ed449c9bfec43c358d953ffbbdcf76",
+    "clang+llvm-13.0.0-amd64-unknown-freebsd13.tar.xz": "c4f15e156afaa530eb47ba13c46800275102af535ed48e395aed4c1decc1eaa1",
+    "clang+llvm-13.0.0-i386-unknown-freebsd12.tar.xz": "4d14b19c082438a5ceed61e538e5a0298018b1773e8ba2e990f3fbe33492f48f",
+    "clang+llvm-13.0.0-i386-unknown-freebsd13.tar.xz": "f8e105c6ac2fd517ae5ed8ef9b9bab4b015fe89a06c90c3dd5d5c7933dca2276",
+    "clang+llvm-13.0.0-powerpc64le-linux-rhel-7.9.tar.xz": "cfade83f6da572a8ab0e4796d1f657967b342e98202c26e76c857879fb2fa2d2",
+    "clang+llvm-13.0.0-powerpc64le-linux-ubuntu-18.04.tar.xz": "5d79e9e2919866a91431589355f6d07f35d439458ff12cb8f36093fb314a7028",
+    "clang+llvm-13.0.0-x86_64-apple-darwin.tar.xz": "d051234eca1db1f5e4bc08c64937c879c7098900f7a0370f3ceb7544816a8b09",
+    "clang+llvm-13.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz": "76d0bf002ede7a893f69d9ad2c4e101d15a8f4186fbfe24e74856c8449acd7c1",
+    "clang+llvm-13.0.0-x86_64-linux-gnu-ubuntu-20.04.tar.xz": "2c2fb857af97f41a5032e9ecadf7f78d3eff389a5cd3c9ec620d24f134ceb3c8",
+}
+
+# Note: Unlike the user-specified llvm_mirror attribute, the URL prefixes in
+# this map are not immediately appended with "/". This is because LLVM prebuilt
+# URLs changed when they switched to hosting the files on GitHub as of 10.0.0.
+_llvm_distributions_base_url = {
+    "6.0.0": "https://releases.llvm.org/",
+    "6.0.1": "https://releases.llvm.org/",
+    "7.0.0": "https://releases.llvm.org/",
+    "8.0.0": "https://releases.llvm.org/",
+    "8.0.1": "https://releases.llvm.org/",
+    "9.0.0": "https://releases.llvm.org/",
+    "10.0.0": "https://github.com/llvm/llvm-project/releases/download/llvmorg-",
+    "10.0.1": "https://github.com/llvm/llvm-project/releases/download/llvmorg-",
+    "11.0.0": "https://github.com/llvm/llvm-project/releases/download/llvmorg-",
+    "11.0.1": "https://github.com/llvm/llvm-project/releases/download/llvmorg-",
+    "11.1.0": "https://github.com/llvm/llvm-project/releases/download/llvmorg-",
+    "12.0.0": "https://github.com/llvm/llvm-project/releases/download/llvmorg-",
+    "12.0.1": "https://github.com/llvm/llvm-project/releases/download/llvmorg-",
+    "13.0.0": "https://github.com/llvm/llvm-project/releases/download/llvmorg-",
+}
+
+def _get_auth(ctx, urls):
+    """
+    Given the list of URLs obtain the correct auth dict.
+
+    Based on:
+    https://github.com/bazelbuild/bazel/blob/793964e8e4268629d82fabbd08bf1a7718afa301/tools/build_defs/repo/http.bzl#L42
+    """
+    netrcpath = None
+    if ctx.attr.netrc:
+        netrcpath = ctx.attr.netrc
+    elif not ctx.os.name.startswith("windows"):
+        if "HOME" in ctx.os.environ:
+            netrcpath = "%s/.netrc" % (ctx.os.environ["HOME"])
+    elif "USERPROFILE" in ctx.os.environ:
+        netrcpath = "%s/.netrc" % (ctx.os.environ["USERPROFILE"])
+
+    if netrcpath and ctx.path(netrcpath).exists:
+        netrc = read_netrc(ctx, netrcpath)
+        return use_netrc(netrc, urls, ctx.attr.auth_patterns)
+
+    return {}
+
+def download_llvm_preconfigured(rctx):
+    llvm_version = rctx.attr.llvm_version
+
+    if rctx.attr.distribution == "auto":
+        exec_result = rctx.execute([
+            _python(rctx),
+            rctx.path(rctx.attr._llvm_release_name),
+            llvm_version,
+        ])
+        if exec_result.return_code:
+            fail("Failed to detect host OS version: \n%s\n%s" % (exec_result.stdout, exec_result.stderr))
+        if exec_result.stderr:
+            print(exec_result.stderr)
+        basename = exec_result.stdout.strip()
+    else:
+        basename = rctx.attr.distribution
+
+    if basename not in _llvm_distributions:
+        fail("Unknown LLVM release: %s\nPlease ensure file name is correct." % basename)
+
+    urls = []
+    url_suffix = "{0}/{1}".format(llvm_version, basename).replace("+", "%2B")
+    if rctx.attr.llvm_mirror:
+        urls.append("{0}/{1}".format(rctx.attr.llvm_mirror, url_suffix))
+    if rctx.attr.alternative_llvm_sources:
+        for pattern in rctx.attr.alternative_llvm_sources:
+            urls.append(pattern.format(llvm_version = llvm_version, basename = basename))
+    urls.append("{0}{1}".format(_llvm_distributions_base_url[llvm_version], url_suffix))
+
+    rctx.download_and_extract(
+        urls,
+        sha256 = _llvm_distributions[basename],
+        stripPrefix = basename[:(len(basename) - len(".tar.xz"))],
+        auth = _get_auth(rctx, urls),
+    )
diff --git a/toolchain/internal/repo.bzl b/toolchain/internal/repo.bzl
new file mode 100644
index 0000000..ab6efe7
--- /dev/null
+++ b/toolchain/internal/repo.bzl
@@ -0,0 +1,41 @@
+# Copyright 2021 The Bazel 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
+#
+#     http://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.
+
+load(
+    "//toolchain/internal:common.bzl",
+    _os = "os",
+)
+load(
+    "//toolchain/internal:llvm_distributions.bzl",
+    _download_llvm_preconfigured = "download_llvm_preconfigured",
+)
+
+def llvm_repo_impl(rctx):
+    os = _os(rctx)
+    if os == "windows":
+        rctx.file("BUILD", executable = False)
+        return
+
+    rctx.file(
+        "BUILD.bazel",
+        content = rctx.read(Label("//toolchain:BUILD.llvm_repo")),
+        executable = False,
+    )
+
+    _download_llvm_preconfigured(rctx)
+
+    # We try to avoid patches to the downloaded repo so that it is easier for
+    # users to bring their own LLVM distribution through `http_archive`. If we
+    # do want to make changes, then we should do it through a patch file, and
+    # document it for users of toolchain_roots attribute.
diff --git a/toolchain/internal/sysroot.bzl b/toolchain/internal/sysroot.bzl
new file mode 100644
index 0000000..9646d08
--- /dev/null
+++ b/toolchain/internal/sysroot.bzl
@@ -0,0 +1,51 @@
+# Copyright 2018 The Bazel 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
+#
+#     http://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.
+
+load(
+    "//toolchain/internal:common.bzl",
+    _os_arch_pair = "os_arch_pair",
+    _pkg_path_from_label = "pkg_path_from_label",
+)
+
+def _darwin_sdk_path(rctx):
+    exec_result = rctx.execute(["/usr/bin/xcrun", "--show-sdk-path", "--sdk", "macosx"])
+    if exec_result.return_code:
+        fail("Failed to detect OSX SDK path: \n%s\n%s" % (exec_result.stdout, exec_result.stderr))
+    if exec_result.stderr:
+        print(exec_result.stderr)
+    return exec_result.stdout.strip()
+
+# Default sysroot path can be used when the user has not provided an explicit
+# sysroot for the target, and when host platform is the same as target
+# platform.
+def default_sysroot_path(rctx, os):
+    if os == "darwin":
+        return _darwin_sdk_path(rctx)
+    else:
+        return ""
+
+# Return the sysroot path and the label to the files, if sysroot is not a system path.
+def sysroot_path(sysroot_dict, os, arch):
+    sysroot = sysroot_dict.get(_os_arch_pair(os, arch))
+    if not sysroot:
+        return (None, None)
+
+    # If the sysroot is an absolute path, use it as-is. Check for things that
+    # start with "/" and not "//" to identify absolute paths, but also support
+    # passing the sysroot as "/" to indicate the root directory.
+    if sysroot[0] == "/" and (len(sysroot) == 1 or sysroot[1] != "/"):
+        return (sysroot, None)
+
+    sysroot_path = _pkg_path_from_label(Label(sysroot))
+    return (sysroot_path, sysroot)
diff --git a/toolchain/osx_cc_wrapper.sh.tpl b/toolchain/osx_cc_wrapper.sh.tpl
new file mode 100755
index 0000000..484c55e
--- /dev/null
+++ b/toolchain/osx_cc_wrapper.sh.tpl
@@ -0,0 +1,149 @@
+#!/bin/bash
+#
+# Copyright 2015 The Bazel Authors. All rights reserved.
+#
+# 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
+#
+#    http://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.
+#
+# OS X relpath is not really working. This is a wrapper script around gcc
+# to simulate relpath behavior.
+#
+# This wrapper uses install_name_tool to replace all paths in the binary
+# (bazel-out/.../path/to/original/library.so) by the paths relative to
+# the binary. It parses the command line to behave as rpath is supposed
+# to work.
+#
+# See https://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac
+# on how to set those paths for Mach-O binaries.
+#
+set -eu
+
+INSTALL_NAME_TOOL="/usr/bin/install_name_tool"
+
+LIBS=
+LIB_DIRS=
+RPATHS=
+OUTPUT=
+
+function parse_option() {
+    local -r opt="$1"
+    if [[ "${OUTPUT}" = "1" ]]; then
+        OUTPUT=$opt
+    elif [[ "$opt" =~ ^-l(.*)$ ]]; then
+        LIBS="${BASH_REMATCH[1]} $LIBS"
+    elif [[ "$opt" =~ ^-L(.*)$ ]]; then
+        LIB_DIRS="${BASH_REMATCH[1]} $LIB_DIRS"
+    elif [[ "$opt" =~ ^-Wl,-rpath,\@loader_path/(.*)$ ]]; then
+        RPATHS="${BASH_REMATCH[1]} ${RPATHS}"
+    elif [[ "$opt" = "-o" ]]; then
+        # output is coming
+        OUTPUT=1
+    fi
+}
+
+# let parse the option list
+for i in "$@"; do
+    if [[ "$i" = @* ]]; then
+        while IFS= read -r opt
+        do
+            parse_option "$opt"
+        done < "${i:1}" || exit 1
+    else
+        parse_option "$i"
+    fi
+done
+
+# On macOS, we use ld as the linker for single-platform builds (i.e., when not
+# cross-compiling). Some applications may remove /usr/bin from PATH before
+# calling this script, which would make /usr/bin/ld unreachable.  For example,
+# rules_rust does not set PATH (unless the user explicitly sets PATH in env
+# through attributes) [1] when calling rustc, and rustc does not replace an
+# unset PATH with a reasonable default either ([2], [3]), which results in CC
+# being called with PATH={sysroot}/{rust_lib}/bin. Note that rules_cc [4] and
+# rules_go [5] do ensure that /usr/bin is in PATH.
+# [1]: https://github.com/bazelbuild/rules_rust/blob/e589105b4e8181dd1d0d8ccaa0cf3267efb06e86/cargo/cargo_build_script.bzl#L66-L68
+# [2]: https://github.com/rust-lang/rust/blob/1c03f0d0ba4fee54b7aa458f4d3ad989d8bf7b34/compiler/rustc_session/src/session.rs#L804-L813
+# [3]: https://github.com/rust-lang/rust/blob/1c03f0d0ba4fee54b7aa458f4d3ad989d8bf7b34/compiler/rustc_codegen_ssa/src/back/link.rs#L640-L645
+# [4]: https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java;l=529;drc=72caead7b428fd50164079956ec368fc54a9567c
+# [5]: https://github.com/bazelbuild/rules_go/blob/63dfd99403076331fef0775d52a8039d502d4115/go/private/context.bzl#L434
+# Let's restore /usr/bin to PATH in such cases. Note that /usr/bin is not a
+# writeable directory on macOS even with sudo privileges, so it should be safe
+# to add it to PATH even when the application wants to use a very strict PATH.
+if [[ ":${PATH}:" != *":/usr/bin:"* ]]; then
+  PATH="${PATH}:/usr/bin"
+fi
+
+# Call the C++ compiler.
+if [[ -f %{toolchain_path_prefix}bin/clang ]]; then
+  %{toolchain_path_prefix}bin/clang "$@"
+elif [[ "${BASH_SOURCE[0]}" == "/"* ]]; then
+  # Some consumers of `CcToolchainConfigInfo` (e.g. `cmake` from rules_foreign_cc)
+  # change CWD and call $CC (this script) with its absolute path.
+  # the execroot (i.e. `cmake` from `rules_foreign_cc`) and call CC . For cases like this,
+  # we'll try to find `clang` relative to this script.
+  # This script is at _execroot_/external/_repo_name_/bin/cc_wrapper.sh
+  execroot_path="${BASH_SOURCE[0]%/*/*/*/*}"
+  clang="${execroot_path}/%{toolchain_path_prefix}bin/clang"
+  "${clang}" "${@}"
+else
+  >&2 echo "ERROR: could not find clang; PWD=\"$(pwd)\"; PATH=\"${PATH}\"."
+  exit 5
+fi
+
+function get_library_path() {
+    for libdir in ${LIB_DIRS}; do
+        if [ -f ${libdir}/lib$1.so ]; then
+            echo "${libdir}/lib$1.so"
+        elif [ -f ${libdir}/lib$1.dylib ]; then
+            echo "${libdir}/lib$1.dylib"
+        fi
+    done
+}
+
+# A convenient method to return the actual path even for non symlinks
+# and multi-level symlinks.
+function get_realpath() {
+    local previous="$1"
+    local next=$(readlink "${previous}")
+    while [ -n "${next}" ]; do
+        previous="${next}"
+        next=$(readlink "${previous}")
+    done
+    echo "${previous}"
+}
+
+# Get the path of a lib inside a tool
+function get_otool_path() {
+    # the lib path is the path of the original lib relative to the workspace
+    get_realpath $1 | sed 's|^.*/bazel-out/|bazel-out/|'
+}
+
+# Do replacements in the output
+for rpath in ${RPATHS}; do
+    for lib in ${LIBS}; do
+        unset libname
+        if [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.so" ]; then
+            libname="lib${lib}.so"
+        elif [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.dylib" ]; then
+            libname="lib${lib}.dylib"
+        fi
+        # ${libname-} --> return $libname if defined, or undefined otherwise. This is to make
+        # this set -e friendly
+        if [[ -n "${libname-}" ]]; then
+            libpath=$(get_library_path ${lib})
+            if [ -n "${libpath}" ]; then
+                ${INSTALL_NAME_TOOL} -change $(get_otool_path "${libpath}") \
+                    "@loader_path/${rpath}/${libname}" "${OUTPUT}"
+            fi
+        fi
+    done
+done
diff --git a/toolchain/rules.bzl b/toolchain/rules.bzl
new file mode 100644
index 0000000..92d2d33
--- /dev/null
+++ b/toolchain/rules.bzl
@@ -0,0 +1,152 @@
+# Copyright 2018 The Bazel 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
+#
+#     http://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.
+
+load(
+    "//toolchain/internal:common.bzl",
+    _supported_os_arch_keys = "supported_os_arch_keys",
+)
+load(
+    "//toolchain/internal:configure.bzl",
+    _llvm_config_impl = "llvm_config_impl",
+)
+load(
+    "//toolchain/internal:repo.bzl",
+    _llvm_repo_impl = "llvm_repo_impl",
+)
+
+_common_attrs = {
+    "llvm_version": attr.string(
+        mandatory = True,
+        doc = "One of the supported versions of LLVM, e.g. 12.0.0",
+    ),
+}
+
+_llvm_repo_attrs = dict(_common_attrs)
+_llvm_repo_attrs.update({
+    "distribution": attr.string(
+        default = "auto",
+        doc = ("LLVM pre-built binary distribution filename, must be one " +
+               "listed on http://releases.llvm.org/download.html for the version " +
+               "specified in the llvm_version attribute. A special value of " +
+               "'auto' tries to detect the version based on host OS."),
+    ),
+    "llvm_mirror": attr.string(
+        doc = "Base URL for an LLVM release mirror." +
+              "\n\n" +
+              "This mirror must follow the same structure as the official LLVM release " +
+              "sources (`releases.llvm.org` for versions <= 9, `llvm/llvm-project` GitHub " +
+              "releases for newer versions)." +
+              "\n\n" +
+              "If provided, this mirror will be given precedence over the official LLVM release " +
+              "sources (see: " +
+              "https://github.com/grailbio/bazel-toolchain/toolchain/internal/llvm_distributions.bzl).",
+    ),
+    "alternative_llvm_sources": attr.string_list(
+        doc = "Patterns for alternative LLVM release sources. Unlike URLs specified for `llvm_mirror` " +
+              "these do not have to follow the same structure as the official LLVM release sources." +
+              "\n\n" +
+              "Patterns may include `{llvm_version}` (which will be substituted for the full LLVM " +
+              "version, i.e. 13.0.0) and `{basename}` (which will be replaced with the filename " +
+              "used by the official LLVM release sources for a particular distribution; i.e. " +
+              "`llvm-13.0.0-x86_64-linux-gnu-ubuntu-20.04.tar.xz`)." +
+              "\n\n" +
+              "As with `llvm_mirror`, these sources will take precedence over the official LLVM " +
+              "release sources.",
+    ),
+    "netrc": attr.string(
+        mandatory = False,
+        doc = "Path to the netrc file for authenticated LLVM URL downloads.",
+    ),
+    "auth_patterns": attr.string_dict(
+        mandatory = False,
+        doc = "An optional dict mapping host names to custom authorization patterns.",
+    ),
+    "_llvm_release_name": attr.label(
+        default = "//toolchain/tools:llvm_release_name.py",
+        allow_single_file = True,
+        doc = "Python module to output LLVM release name for the current OS.",
+    ),
+})
+
+_llvm_config_attrs = dict(_common_attrs)
+_llvm_config_attrs.update({
+    "toolchain_roots": attr.string_dict(
+        mandatory = True,
+        # TODO: Ideally, we should be taking a filegroup label here instead of a package path, but
+        # we ultimately need to subset the files to be more selective in what we include in the
+        # sandbox for which operations, and it is not straightforward to subset a filegroup.
+        doc = ("System or package path, for each host OS and arch pair you want to support " +
+               "({}), ".format(", ".join(_supported_os_arch_keys())) +
+               "to be used as the LLVM toolchain distributions. An empty key can be used to " +
+               "specify a fallback default for all hosts, e.g. with the llvm_toolchain_repo rule. " +
+               "If the value begins with exactly one forward slash '/', then the value is " +
+               "assumed to be a system path and the toolchain is configured to use absolute " +
+               "paths. Else, the value will be assumed to be a bazel package containing the " +
+               "filegroup targets as in BUILD.llvm_repo."),
+    ),
+    "sysroot": attr.string_dict(
+        mandatory = False,
+        doc = ("System path or fileset, for each target OS and arch pair you want to support " +
+               "({}), ".format(", ".join(_supported_os_arch_keys())) +
+               "used to indicate the set of files that form the sysroot for the compiler. " +
+               "If the value begins with exactly one forward slash '/', then the value is " +
+               "assumed to be a system path. Else, the value will be assumed to be a label " +
+               "containing the files and the sysroot path will be taken as the path to the " +
+               "package of this label."),
+    ),
+    "cxx_builtin_include_directories": attr.string_list_dict(
+        mandatory = False,
+        doc = ("Additional builtin include directories to be added to the default system " +
+               "directories, for each target OS and arch pair you want to support " +
+               "({}); ".format(", ".join(_supported_os_arch_keys())) +
+               "see documentation for bazel's create_cc_toolchain_config_info."),
+    ),
+    "absolute_paths": attr.bool(
+        default = False,
+        doc = "Use absolute paths in the toolchain. Avoids sandbox overhead.",
+    ),
+    "_cc_toolchain_config_bzl": attr.label(
+        default = "//toolchain:cc_toolchain_config.bzl",
+    ),
+})
+
+llvm = repository_rule(
+    attrs = _llvm_repo_attrs,
+    local = False,
+    implementation = _llvm_repo_impl,
+)
+
+toolchain = repository_rule(
+    attrs = _llvm_config_attrs,
+    local = True,
+    configure = True,
+    implementation = _llvm_config_impl,
+)
+
+def llvm_toolchain(name, **kwargs):
+    if not kwargs.get("toolchain_roots"):
+        llvm_args = {
+            k: v
+            for k, v in kwargs.items()
+            if (k not in _llvm_config_attrs.keys()) or (k in _common_attrs.keys())
+        }
+        llvm(name = name + "_llvm", **llvm_args)
+        kwargs.update(toolchain_roots = {"": "@%s_llvm//" % name})
+
+    toolchain_args = {
+        k: v
+        for k, v in kwargs.items()
+        if (k not in _llvm_repo_attrs.keys()) or (k in _common_attrs.keys())
+    }
+    toolchain(name = name, **toolchain_args)
diff --git a/toolchain/toolchains.bzl.tpl b/toolchain/toolchains.bzl.tpl
new file mode 100644
index 0000000..2b1961f
--- /dev/null
+++ b/toolchain/toolchains.bzl.tpl
@@ -0,0 +1,18 @@
+# Copyright 2018 The Bazel 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
+#
+#     http://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.
+
+def llvm_register_toolchains():
+    native.register_toolchains(
+        %{toolchain_labels}
+    )
diff --git a/toolchain/tools/BUILD.bazel b/toolchain/tools/BUILD.bazel
new file mode 100644
index 0000000..7f673fe
--- /dev/null
+++ b/toolchain/tools/BUILD.bazel
@@ -0,0 +1,15 @@
+# Copyright 2018 The Bazel 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
+#
+#     http://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.
+
+exports_files(["llvm_release_name.py"])
diff --git a/toolchain/tools/llvm_release_name.py b/toolchain/tools/llvm_release_name.py
new file mode 100755
index 0000000..47d71d6
--- /dev/null
+++ b/toolchain/tools/llvm_release_name.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python3
+# Copyright 2018 The Bazel 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
+#
+#     http://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.
+"""LLVM pre-built distribution file names."""
+
+import platform
+import sys
+
+_known_distros = ["freebsd", "suse", "ubuntu", "arch", "manjaro", "debian", "fedora", "centos", "amzn", "raspbian"]
+
+def _major_llvm_version(llvm_version):
+    return int(llvm_version.split(".")[0])
+
+def _minor_llvm_version(llvm_version):
+    return int(llvm_version.split(".")[1])
+
+def _darwin(llvm_version, arch):
+    major_llvm_version = _major_llvm_version(llvm_version)
+    suffix = "darwin-apple" if major_llvm_version == 9 else "apple-darwin"
+    return "clang+llvm-{llvm_version}-{arch}-{suffix}.tar.xz".format(
+        llvm_version=llvm_version, arch=arch, suffix=suffix)
+
+def _windows(llvm_version, arch):
+    if arch.endswith('64'):
+        win_arch = "win64"
+    else:
+        win_arch = "win32"
+
+    return "LLVM-{llvm_version}-{win_arch}.exe".format(
+        llvm_version=llvm_version,
+        win_arch=win_arch)
+
+def _ubuntu_osname(arch, version, major_llvm_version, llvm_version):
+    if arch == "powerpc64le":
+        if major_llvm_version > 11:
+            return "linux-gnu-ubuntu-18.04"
+        else:
+            return "linux-gnu-ubuntu-16.04"
+
+    os_name = "linux-gnu-ubuntu-16.04"
+
+    if version.startswith("20.10") and (llvm_version in ["11.0.1", "11.1.0"]):
+        os_name = "linux-gnu-ubuntu-20.10"
+    elif version.startswith("20"):
+        if major_llvm_version < 11 or llvm_version in ["11.0.1", "11.1.0"]:
+            # There is no binary packages specifically for 20.04, but those for 18.04 works on
+            # 20.04
+            os_name = "linux-gnu-ubuntu-18.04"
+        elif major_llvm_version > 11:
+            # release 11.0.0 started providing packaging for ubuntu 20.04.
+            os_name = "linux-gnu-ubuntu-20.04"
+    elif version.startswith("18"):
+        if llvm_version in ["8.0.0", "9.0.0", "10.0.0"]:
+            os_name = "linux-gnu-ubuntu-18.04"
+        else:
+            os_name = "linux-gnu-ubuntu-16.04"
+
+    return os_name
+
+def _linux(llvm_version, arch):
+    release_file_path = "/etc/os-release"
+    with open(release_file_path) as release_file:
+        lines = release_file.readlines()
+        info = dict()
+        for line in lines:
+            line = line.strip()
+            if not line:
+                continue
+            [key, val] = line.split('=', 1)
+            info[key] = val
+    if "ID" not in info:
+        sys.exit("Could not find ID in /etc/os-release.")
+    distname = info["ID"].strip('\"')
+
+    if distname not in _known_distros:
+        for distro in info["ID_LIKE"].strip('\"').split(' '):
+            if distro in _known_distros:
+                distname = distro
+                break
+
+    version = None
+    if "VERSION_ID" in info:
+        version = info["VERSION_ID"].strip('"')
+
+    major_llvm_version = _major_llvm_version(llvm_version)
+
+    # NOTE: Many of these systems are untested because I do not have access to them.
+    # If you find this mapping wrong, please send a Pull Request on Github.
+    if arch in ["aarch64", "armv7a", "mips", "mipsel"]:
+        os_name = "linux-gnu"
+    elif distname == "freebsd":
+        os_name = "unknown-freebsd-%s" % version
+    elif distname == "suse":
+        os_name = _resolve_version_for_suse(major_llvm_version, _minor_llvm_version(llvm_version))
+    elif distname == "ubuntu":
+        os_name = _ubuntu_osname(arch, version, major_llvm_version, llvm_version)
+    elif ((distname in ["linuxmint", "pop"]) and (version.startswith("20") or version.startswith("19"))):
+        if major_llvm_version < 11 or llvm_version in ["11.0.1", "11.1.0"]:
+            # There is no binary packages specifically for 20.04, but those for 18.04 works on
+            # 20.04
+            os_name = "linux-gnu-ubuntu-18.04"
+        else:
+            # release 11.0.0 started providing packaging for ubuntu 20.04.
+            os_name = "linux-gnu-ubuntu-20.04"
+    elif distname in ["manjaro"] or (distname == "linuxmint" and version.startswith("18")):
+        os_name = "linux-gnu-ubuntu-16.04"
+    elif distname == "debian":
+        int_version = None
+        try:
+            int_version = int(version)
+        except ValueError:
+            pass
+        if int_version is None or int_version >= 10:
+            if major_llvm_version < 11 or llvm_version in ["11.0.1", "11.1.0"]:
+                os_name = "linux-gnu-ubuntu-18.04"
+            else:
+                os_name = "linux-gnu-ubuntu-20.04"
+        elif int_version == 9 and major_llvm_version >= 7:
+            os_name = "linux-gnu-ubuntu-16.04"
+        elif int_version == 8 and major_llvm_version < 7:
+            os_name = "linux-gnu-debian8"
+    elif ((distname == "fedora" and int(version) >= 27) or
+          (distname == "centos" and int(version) >= 7)) and major_llvm_version < 7:
+        os_name = "linux-gnu-Fedora27"
+    elif distname == "centos" and major_llvm_version >= 7:
+        os_name = "linux-sles11.3"
+    elif distname == "fedora" and major_llvm_version >= 7:
+        if major_llvm_version < 11 or llvm_version in ["11.0.1", "11.1.0"]:
+            os_name = "linux-gnu-ubuntu-18.04"
+        else:
+            os_name = "linux-gnu-ubuntu-20.04"
+    elif distname == "arch" and major_llvm_version >= 11:
+        os_name = "linux-gnu-ubuntu-20.04"
+    elif distname == "arch" and major_llvm_version >= 10:
+        os_name = "linux-gnu-ubuntu-18.04"
+    elif distname == "arch" and major_llvm_version >= 7:
+        os_name = "linux-gnu-ubuntu-16.04"
+    elif distname == "amzn":
+        # Based on the ID_LIKE field, sles seems like the closest available
+        # distro for which LLVM releases are widely available.
+        if major_llvm_version >= 11:
+            os_name = "linux-sles12.4"
+        else:
+            os_name = "linux-sles11.3"
+    elif distname == "raspbian":
+        arch = "armv7a"
+        os_name = "linux-gnueabihf"
+    else:
+        sys.exit("Unsupported linux distribution and version: %s, %s" % (distname, version))
+
+    return "clang+llvm-{llvm_version}-{arch}-{os_name}.tar.xz".format(
+        llvm_version=llvm_version,
+        arch=arch,
+        os_name=os_name)
+
+def _resolve_version_for_suse(major_llvm_version, minor_llvm_version):
+        if major_llvm_version < 10:
+            os_name = "linux-sles11.3"
+        elif major_llvm_version == 10 and minor_llvm_version == 0:
+            os_name = "linux-sles11.3"
+        else:
+            os_name = "linux-sles12.4"
+        return os_name
+
+def main():
+    """Prints the pre-built distribution file name."""
+
+    if len(sys.argv) != 2:
+        sys.exit("Usage: %s llvm_version" % sys.argv[0])
+
+    llvm_version = sys.argv[1]
+
+    system = platform.system()
+    arch = platform.machine()
+
+    if system == "Darwin":
+        print(_darwin(llvm_version, arch))
+        sys.exit()
+
+    if system == "Windows":
+        print(_windows(llvm_version, arch))
+        sys.exit()
+
+    if system == "Linux":
+        print(_linux(llvm_version, arch))
+        sys.exit()
+
+    sys.exit("Unsupported system: %s" % system)
+
+if __name__ == '__main__':
+    main()