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/.bazelrc b/.bazelrc
new file mode 100644
index 0000000..fbd75a7
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1 @@
+build --incompatible_enable_cc_toolchain_resolution
diff --git a/.github/workflows/migration.yml b/.github/workflows/migration.yml
new file mode 100644
index 0000000..4d1baf6
--- /dev/null
+++ b/.github/workflows/migration.yml
@@ -0,0 +1,18 @@
+name: Migration
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: test
+      env:
+        BAZELISK_GITHUB_TOKEN: ${{ secrets.BAZELISK_GITHUB_TOKEN }}
+        TEST_MIGRATION: true
+      run: tests/scripts/run_tests.sh
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..c187b79
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,39 @@
+name: Tests
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+
+jobs:
+  test:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [macos-latest, ubuntu-latest]
+        script: [run_tests.sh, run_external_tests.sh]
+    steps:
+    - uses: actions/checkout@v2
+    - name: test
+      run: tests/scripts/${{ matrix.script }}
+  container_test:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        # This list is missing suse_tumbleweed because their latest image is
+        # not working, and they don't have versioned images.
+        # TODO: Re-enable suse_tumbleweed when their docker image starts working.
+        script: [archlinux, debian, fedora, suse_leap, ubuntu_16_04, ubuntu_18_04, ubuntu_20_04, linux_sysroot]
+    steps:
+    - uses: actions/checkout@v2
+    - name: test
+      run: tests/scripts/${{ matrix.script }}_test.sh
+  xcompile_test:
+    runs-on: macos-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: test
+      run: tests/scripts/run_xcompile_tests.sh
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a6ef824
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/bazel-*
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   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/README.md b/README.md
new file mode 100644
index 0000000..c0d1835
--- /dev/null
+++ b/README.md
@@ -0,0 +1,207 @@
+LLVM toolchain for Bazel [![Tests](https://github.com/grailbio/bazel-toolchain/actions/workflows/tests.yml/badge.svg)](https://github.com/grailbio/bazel-toolchain/actions/workflows/tests.yml) [![Migration](https://github.com/grailbio/bazel-toolchain/actions/workflows/migration.yml/badge.svg)](https://github.com/grailbio/bazel-toolchain/actions/workflows/migration.yml)
+=================
+
+-------
+
+The project is in a relatively stable state and in use for all code development
+at GRAIL and other organizations. Having said that, I am unable to give time to
+it at any regular cadence.
+
+I rely on the community for maintenance and new feature implementations. If you
+are interested in being part of this project, please let me know and I can give
+you write access, so you can merge your changes directly.
+
+If you feel like you have a better maintained fork or an alternative/derived
+implementation, please let me know and I can redirect people there.
+
+– @siddharthab
+
+-------
+
+## Quickstart
+
+Minimum bazel version: **4.0.0**
+
+To use this toolchain, include this section in your WORKSPACE:
+```starlark
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+BAZEL_TOOLCHAIN_TAG = "0.6.3"
+BAZEL_TOOLCHAIN_SHA = "da607faed78c4cb5a5637ef74a36fdd2286f85ca5192222c4664efec2d529bb8"
+
+http_archive(
+    name = "com_grail_bazel_toolchain",
+    sha256 = BAZEL_TOOLCHAIN_SHA,
+    strip_prefix = "bazel-toolchain-{tag}".format(tag = BAZEL_TOOLCHAIN_TAG),
+    canonical_id = BAZEL_TOOLCHAIN_TAG,
+    url = "https://github.com/grailbio/bazel-toolchain/archive/{tag}.tar.gz".format(tag = BAZEL_TOOLCHAIN_TAG),
+)
+
+load("@com_grail_bazel_toolchain//toolchain:deps.bzl", "bazel_toolchain_dependencies")
+
+bazel_toolchain_dependencies()
+
+load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain")
+
+llvm_toolchain(
+    name = "llvm_toolchain",
+    llvm_version = "13.0.0",
+)
+
+load("@llvm_toolchain//:toolchains.bzl", "llvm_register_toolchains")
+
+llvm_register_toolchains()
+```
+
+And add the following section to your .bazelrc file (not needed after
+this [issue](https://github.com/bazelbuild/bazel/issues/7260) is closed):
+```
+build --incompatible_enable_cc_toolchain_resolution
+```
+
+## Basic Usage
+
+The toolchain can automatically detect your OS and arch type, and use the right
+pre-built binary distribution from llvm.org. The detection is currently
+based on host OS and is not perfect, so some distributions, docker based
+sandboxed builds, and remote execution builds will need toolchains configured
+manually through the `distribution` attribute. We expect the detection logic to
+grow through community contributions. We welcome PRs! :smile:
+
+See in-code documentation in [rules.bzl](toolchain/rules.bzl) for available
+attributes to `llvm_toolchain`.
+
+## Advanced Usage
+
+#### Customizations
+
+We currently offer limited customizability through attributes of the
+[llvm_toolchain_\* rules](toolchain/rules.bzl). You can send us a PR to add
+more configuration attributes.
+
+A majority of the complexity of this project is to make it generic for multiple
+use cases. For one-off experiments with new architectures, cross-compilations,
+new compiler features, etc., my advice would be to look at the toolchain
+configurations generated by this repo, and copy-paste/edit to make your own in
+any package in your own workspace.
+
+```
+bazel query --output=build @llvm_toolchain//:all | grep -v -e '^#' -e '^  generator'
+```
+
+Besides defining your toolchain in your package BUILD file, and until this
+[issue](https://github.com/bazelbuild/bazel/issues/7746) is resolved, you would
+also need a way for bazel to access the tools in LLVM distribution as relative
+paths from your package without using `..` up-references. For this, you can
+create a symlink that uses up-references to point to the LLVM distribution
+directory, and also create a wrapper script for clang such that the actual
+clang invocation is not through the symlinked path. See the files in the
+`@llvm_toolchain//:` package as a reference.
+
+```
+# See generated files for reference.
+ls -lR "$(bazel info output_base)/external/llvm_toolchain"
+
+# Create symlink to LLVM distribution.
+cd _your_package_directory_
+ln -s ../....../external/llvm_toolchain_llvm llvm
+
+# Create CC wrapper script.
+mkdir bin
+cp "$(bazel info output_base)/external/llvm_toolchain/bin/cc_wrapper.sh" bin/cc_wrapper.sh
+vim bin/cc_wrapper.sh # Review to ensure relative paths, etc. are good.
+```
+
+See [bazel
+tutorial](https://docs.bazel.build/versions/main/tutorial/cc-toolchain-config.html)
+for how CC toolchains work in general.
+
+#### Selecting Toolchains
+
+If toolchains are registered (see Quickstart section above), you do not need to
+do anything special for bazel to find the toolchain. You may want to check once
+with the `--toolchain_resolution_debug` flag to see which toolchains were
+selected by bazel for your target platform.
+
+For specifying unregistered toolchains on the command line, please use the
+`--extra_toolchains` flag.  For example,
+`--extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux`.
+
+We no longer support the `--crosstool_top=@llvm_toolchain//:toolchain` flag,
+and instead rely on the `--incompatible_enable_cc_toolchain_resolution` flag.
+
+#### Bring Your Own LLVM
+
+The LLVM toolchain archive is downloaded and extracted as a separate repository
+with the suffix `_llvm`. Alternatively, you can also specify your own
+repositories for each host os-arch pair through the `toolchain_roots`
+attribute. Each of these repositories is typically configured through
+`local_repository` or `http_archive` (with `build_file` attribute as
+`@com_grail_bazel_toolchain//toolchain:BUILD.llvm_repo`).
+
+#### Sysroots
+
+A sysroot can be specified through the `sysroot` attribute. This can be either
+a path on the user's system, or a bazel `filegroup` like label. One way to
+create a sysroot is to use `docker export` to get a single archive of the
+entire filesystem for the image you want. Another way is to use the build
+scripts provided by the [Chromium
+project](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/linux_sysroot.md).
+
+#### Cross-compilation
+
+The toolchain supports cross-compilation if you bring your own sysroot. When
+cross-compiling, we link against the libstdc++ from the sysroot
+(single-platform build behavior is to link against libc++ bundled with LLVM).
+The following pairs have been tested to work for some hello-world binaries:
+- {linux, x86_64} -> {linux, aarch64}
+- {linux, aarch64} -> {linux, x86_64}
+- {darwin, x86_64} -> {linux, x86_64}
+- {darwin, x86_64} -> {linux, aarch64}
+
+A recommended approach would be to define two toolchains, one without sysroot
+for single-platform builds, and one with sysroot for cross-compilation builds.
+Then, when cross-compiling, explicitly specify the toolchain with the sysroot
+and the target platform. For example, see the [WORKSPACE](WORKSPACE) file and
+the [test script](tests/scripts/run_xcompile_tests.sh) for cross-compilation.
+```
+bazel build \
+  --platforms=@com_grail_bazel_toolchain//platforms:linux-x86_64 \
+  --extra_toolchains=@llvm_toolchain_with_sysroot//:cc-toolchain-x86_64-linux \
+  //...
+```
+
+#### Sandbox
+
+Sandboxing the toolchain introduces a significant overhead (100ms per action,
+as of mid 2018). To overcome this, one can use
+`--experimental_sandbox_base=/dev/shm`.  However, not all environments might
+have enough shared memory available to load all the files in memory. If this is
+a concern, you may set the attribute for using absolute paths, which will
+substitute templated paths to the toolchain as absolute paths. When running
+bazel actions, these paths will be available from inside the sandbox as part of
+the / read-only mount. Note that this will make your builds non-hermetic.
+
+#### Compatibility
+
+The toolchain is tested to work with `rules_go`, `rules_rust`, and
+`rules_foreign_cc`.
+
+#### Accessing tools
+
+The LLVM distribution also provides several tools like `clang-format`. You can
+depend on these tools directly in the bin directory of the distribution. When
+using the auto-configured download (not using `toolchain_roots`), the
+distribution is available in the repo with the suffix `_llvm` appended to the
+name you used for the `llvm_toolchain` rule. For example,
+`@llvm_toolchain_llvm//:bin/clang-format` is a valid and visible target in the
+quickstart example above.
+
+
+## Prior Art
+
+Other examples of toolchain configuration:
+
+https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain
+
+https://github.com/vsco/bazel-toolchains
diff --git a/WORKSPACE b/WORKSPACE
new file mode 100644
index 0000000..89dfc78
--- /dev/null
+++ b/WORKSPACE
@@ -0,0 +1,243 @@
+# 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.
+
+workspace(
+    name = "com_grail_bazel_toolchain",
+)
+
+load("@com_grail_bazel_toolchain//toolchain:deps.bzl", "bazel_toolchain_dependencies")
+
+bazel_toolchain_dependencies()
+
+load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain")
+
+llvm_toolchain(
+    name = "llvm_toolchain",
+    llvm_version = "12.0.0",
+)
+
+load("@llvm_toolchain//:toolchains.bzl", "llvm_register_toolchains")
+
+llvm_register_toolchains()
+
+## Toolchain example with a sysroot.
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+# This sysroot is used by github.com/vsco/bazel-toolchains.
+http_archive(
+    name = "org_chromium_sysroot_linux_x64",
+    build_file_content = """
+filegroup(
+  name = "sysroot",
+  srcs = glob(["*/**"]),
+  visibility = ["//visibility:public"],
+)
+""",
+    sha256 = "84656a6df544ecef62169cfe3ab6e41bb4346a62d3ba2a045dc5a0a2ecea94a3",
+    urls = ["https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain/2202c161310ffde63729f29d27fe7bb24a0bc540/debian_stretch_amd64_sysroot.tar.xz"],
+)
+
+llvm_toolchain(
+    name = "llvm_toolchain_with_sysroot",
+    llvm_version = "12.0.0",
+    sysroot = {
+        "linux-x86_64": "@org_chromium_sysroot_linux_x64//:sysroot",
+    },
+    # We can share the downloaded LLVM distribution with the first configuration.
+    toolchain_roots = {
+        "": "@llvm_toolchain_llvm//",
+    },
+)
+
+# Well known repos; present here only for testing.
+
+http_archive(
+    name = "com_google_googletest",
+    sha256 = "9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb",
+    strip_prefix = "googletest-release-1.10.0",
+    urls = ["https://github.com/google/googletest/archive/release-1.10.0.tar.gz"],
+)
+
+http_archive(
+    name = "com_github_google_benchmark",
+    sha256 = "3c6a165b6ecc948967a1ead710d4a181d7b0fbcaa183ef7ea84604994966221a",
+    strip_prefix = "benchmark-1.5.0",
+    urls = ["https://github.com/google/benchmark/archive/v1.5.0.tar.gz"],
+)
+
+http_archive(
+    name = "com_google_absl",
+    sha256 = "59b862f50e710277f8ede96f083a5bb8d7c9595376146838b9580be90374ee1f",
+    strip_prefix = "abseil-cpp-20210324.2",
+    urls = ["https://github.com/abseil/abseil-cpp/archive/20210324.2.tar.gz"],
+)
+
+http_archive(
+    name = "openssl",
+    build_file = "//tests/openssl:openssl.bazel",
+    sha256 = "f6fb3079ad15076154eda9413fed42877d668e7069d9b87396d0804fdb3f4c90",
+    strip_prefix = "openssl-1.1.1c",
+    urls = ["https://www.openssl.org/source/openssl-1.1.1c.tar.gz"],
+)
+
+http_archive(
+    name = "io_bazel_rules_go",
+    sha256 = "8e968b5fcea1d2d64071872b12737bbb5514524ee5f0a4f54f5920266c261acb",
+    urls = [
+        "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.28.0/rules_go-v0.28.0.zip",
+        "https://github.com/bazelbuild/rules_go/releases/download/v0.28.0/rules_go-v0.28.0.zip",
+    ],
+)
+
+load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
+
+go_rules_dependencies()
+
+go_register_toolchains(version = "1.17")
+
+# For testing rules_foreign_cc.
+# See https://bazelbuild.github.io/rules_foreign_cc/0.6.0/cmake.html
+
+http_archive(
+    name = "rules_foreign_cc",
+    sha256 = "69023642d5781c68911beda769f91fcbc8ca48711db935a75da7f6536b65047f",
+    strip_prefix = "rules_foreign_cc-0.6.0",
+    url = "https://github.com/bazelbuild/rules_foreign_cc/archive/0.6.0.tar.gz",
+)
+
+load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies")
+
+rules_foreign_cc_dependencies()
+
+_ALL_CONTENT = """\
+filegroup(
+    name = "all_srcs",
+    srcs = glob(["**"]),
+    visibility = ["//visibility:public"],
+)
+"""
+
+http_archive(
+    name = "pcre",
+    build_file_content = _ALL_CONTENT,
+    sha256 = "0b8e7465dc5e98c757cc3650a20a7843ee4c3edf50aaf60bb33fd879690d2c73",
+    strip_prefix = "pcre-8.43",
+    urls = [
+        "https://mirror.bazel.build/ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz",
+        "https://ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz",
+    ],
+)
+
+http_archive(
+    name = "rules_rust",
+    sha256 = "531bdd470728b61ce41cf7604dc4f9a115983e455d46ac1d0c1632f613ab9fc3",
+    strip_prefix = "rules_rust-d8238877c0e552639d3e057aadd6bfcf37592408",
+    urls = [
+        # `main` branch as of 2021-08-23
+        "https://github.com/bazelbuild/rules_rust/archive/d8238877c0e552639d3e057aadd6bfcf37592408.tar.gz",
+    ],
+)
+
+load("@rules_rust//rust:repositories.bzl", "rust_repositories")
+
+rust_repositories(
+    edition = "2018",
+    version = "1.55.0",
+)
+
+# We're using `git2` as our Rust test because it links against C code
+# (`libgit2-sys`) using `cc`, has tests, and is non-trivial but not _massive_.
+#
+# Ordinarily we'd just run the `rules_rust` tests but those break when run
+# from another workspace (some of the skylib unittests expect paths within the
+# main workspace and fail when paths like `external/rules_rust/...` are
+# produced) and we want to test usage of the cc_toolchain via the `cc` crate
+# anyways (as of this writing nothing in `@rules_rust//tests` seems to test
+# this).
+GIT2_RS_VER = "0.13.22"
+
+GIT2_RS_SHA = "9c1cbbfc9a1996c6af82c2b4caf828d2c653af4fcdbb0e5674cc966eee5a4197"
+
+http_archive(
+    name = "git2",
+    build_file_content = """
+package(default_visibility = ["//visibility:public"])
+
+load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
+load("@crates//:defs.bzl", "crates_from", "dev_crates_from", "crate")
+
+DEV_CRATES = dev_crates_from("@git2//:Cargo.toml")
+DEV_CRATES.remove(crate("paste")) # This is a proc_macro crate!
+
+rust_library(
+    name = "git2",
+    srcs = glob(["src/**/*.rs"]),
+    deps = crates_from("@git2//:Cargo.toml"),
+)
+
+rust_test(
+    name = "git2-tests",
+    crate = ":git2",
+    deps = DEV_CRATES,
+    proc_macro_deps = [crate("paste")],
+)
+
+[
+    rust_test(
+        name = t[len("tests/"):][:-len(".rs")],
+        srcs = [t],
+        deps = [":git2"] + DEV_CRATES,
+        proc_macro_deps = [crate("paste")],
+    )
+    for t in glob(["tests/*.rs"])
+]
+""",
+    canonical_id = GIT2_RS_VER,
+    patch_args = ["-p1"],
+    # We need to remove some `[target]` entries in `git2`'s `Cargo.toml` to
+    # make `crate-universe` happy.
+    #
+    # See: https://github.com/bazelbuild/rules_rust/issues/783
+    patches = ["//tests/rust:git2-rs-cargo-toml.patch"],
+    sha256 = GIT2_RS_SHA,
+    strip_prefix = "git2-{ver}".format(ver = GIT2_RS_VER),
+    type = "tar.gz",
+    url = "https://crates.io/api/v1/crates/git2/{ver}/download".format(ver = GIT2_RS_VER),
+)
+
+# Snippets for `crate_universe`:
+RULES_RUST_CRATE_UNIVERSE_URL_TEMPLATE = "https://github.com/bazelbuild/rules_rust/releases/download/crate_universe-13/crate_universe_resolver-{host_triple}{extension}"
+
+RULES_RUST_CRATE_UNIVERSE_SHA256_CHECKSUMS = {
+    "aarch64-apple-darwin": "c6017cd8a4fee0f1796a8db184e9d64445dd340b7f48a65130d7ee61b97051b4",
+    "aarch64-unknown-linux-gnu": "d0a310b03b8147e234e44f6a93e8478c260a7c330e5b35515336e7dd67150f35",
+    "x86_64-apple-darwin": "762f1c77b3cf1de8e84d7471442af1314157efd90720c7e1f2fff68556830ee2",
+    "x86_64-pc-windows-gnu": "c44bd97373d690587e74448b13267077d133f04e89bedfc9d521ae8ba55dddb9",
+    "x86_64-unknown-linux-gnu": "aebf51af6a3dd33fdac463b35b0c3f4c47ab93e052099199673289e2025e5824",
+}
+
+load("@rules_rust//crate_universe:defs.bzl", "crate_universe")
+
+crate_universe(
+    name = "crates",
+    cargo_toml_files = [
+        "@git2//:Cargo.toml",
+    ],
+    resolver_download_url_template = RULES_RUST_CRATE_UNIVERSE_URL_TEMPLATE,
+    resolver_sha256s = RULES_RUST_CRATE_UNIVERSE_SHA256_CHECKSUMS,
+)
+
+load("@crates//:defs.bzl", "pinned_rust_install")
+
+pinned_rust_install()
diff --git a/platforms/BUILD.bazel b/platforms/BUILD.bazel
new file mode 100644
index 0000000..16c1983
--- /dev/null
+++ b/platforms/BUILD.bazel
@@ -0,0 +1,39 @@
+# 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"])
+
+platform(
+    name = "linux-x86_64",
+    constraint_values = [
+        "@platforms//os:linux",
+        "@platforms//cpu:x86_64",
+    ],
+)
+
+platform(
+    name = "linux-aarch64",
+    constraint_values = [
+        "@platforms//os:linux",
+        "@platforms//cpu:aarch64",
+    ],
+)
+
+platform(
+    name = "darwin-x86_64",
+    constraint_values = [
+        "@platforms//os:osx",
+        "@platforms//cpu:x86_64",
+    ],
+)
diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel
new file mode 100644
index 0000000..e8d703f
--- /dev/null
+++ b/tests/BUILD.bazel
@@ -0,0 +1,110 @@
+# 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_skylib//rules:build_test.bzl", "build_test")
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
+load(":transitions.bzl", "dwp_file")
+
+cc_library(
+    name = "stdlib",
+    srcs = ["stdlib.cc"],
+    hdrs = ["stdlib.h"],
+)
+
+# We want to emulate the behavior of cc_binary but be able to run the target as
+# a test, so we use a cc_test target with linkstatic.
+cc_test(
+    name = "stdlib_test",
+    srcs = ["stdlib_test.cc"],
+    linkstatic = True,
+    deps = [":stdlib"],
+)
+
+# We want to test a `.stripped` target to make sure `llvm-strip` can be called.
+#
+# For this we need `cc_binary`; `cc_test` does not create `.stripped` targets.
+cc_binary(
+    name = "stdlib_bin",
+    srcs = ["stdlib_test.cc"],
+    deps = [":stdlib"],
+)
+
+build_test(
+    name = "stripped_binary_test",
+    targets = [
+        ":stdlib_bin.stripped",
+    ],
+)
+
+# We want to test that `llvm-dwp` (used when assembling a `.dwp` file from
+# `.dwo` files) can be called.
+#
+# `--fission=yes` enables this for all compilation modes but we also need to
+# enable the `per_object_debug_info` feature manually because
+# `unix_cc_toolchain_config.bzl`'s` `cc_toolchain_config` does not (see #109).
+#
+# Additionally, newer versions of clang (12+) require a non-zero `-g` setting to
+# actually produce the `.dwo` files in addition to the `-gsplit-dwarf` flag. The
+# feature in `unix_cc_toolchain_config.bzl` should be updated to reflect this
+# and pass in an appropriate `-g` flag.
+#
+# bazelbuild/rules_cc#115 is a patch that does this
+# (https://github.com/bazelbuild/rules_cc/pull/115).
+#
+# bazelbuild/bazel#14028 tracks this
+# (https://github.com/bazelbuild/bazel/issues/14038).
+#
+# #109 in this repo and this comment
+# (https://github.com/grailbio/bazel-toolchain/pull/108#issuecomment-928839768)
+# have some additional details.
+#
+# For now, we'll specify `-c dbg` when building `.dwo` and `.dwp` files.
+#
+# This (setting the fission flag, enabling the `per_object_debug_info` feature,
+# and setting the compilation mode to `dbg`) is what `dwp_file` does using a
+# transition.
+#
+# Unfortunately `per_object_debug_info` breaks on macOS which is why this target
+# is marked as only being compatible with Linux (see #109).
+dwp_file(
+    name = "stdlib.dwp",
+    src = ":stdlib_bin",
+    # NOTE: we should eventually we able to drop this; see #109.
+    override_compilation_mode = "dbg",
+    target_compatible_with = [
+        "@platforms//os:linux",
+    ],
+)
+
+build_test(
+    name = "dwp_test",
+    targets = [
+        ":stdlib.dwp",
+    ],
+)
+
+cc_test(
+    name = "pthread_link_test",
+    srcs = ["pthread_link_test.cc"],
+    linkstatic = False,
+)
+
+sh_test(
+    name = "file_dependency_test",
+    srcs = ["file_dependency_test.sh"],
+    data = [
+        "@llvm_toolchain_llvm//:bin/clang-format",
+        "@llvm_toolchain_llvm//:lib/libc++.a",
+    ],
+)
diff --git a/tests/file_dependency_test.sh b/tests/file_dependency_test.sh
new file mode 100755
index 0000000..60e5cec
--- /dev/null
+++ b/tests/file_dependency_test.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+fail() {
+  >&2 echo "$@"
+  exit 1
+}
+
+[[ -a "external/llvm_toolchain_llvm/bin/clang-format" ]] || fail "bin/clang-format not found"
+
+[[ -a "external/llvm_toolchain_llvm/lib/libc++.a" ]] || fail "lib/libc++.a not found"
+
+echo "SUCCESS!"
diff --git a/tests/foreign/BUILD.bazel b/tests/foreign/BUILD.bazel
new file mode 100644
index 0000000..99cfae4
--- /dev/null
+++ b/tests/foreign/BUILD.bazel
@@ -0,0 +1,28 @@
+# 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("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake")
+
+# See https://bazelbuild.github.io/rules_foreign_cc/0.6.0/cmake.html
+cmake(
+    name = "pcre",
+    cache_entries = {
+        "CMAKE_C_FLAGS": "-fPIC",
+    },
+    lib_source = "@pcre//:all_srcs",
+    out_static_libs = ["libpcre.a"],
+)
+
+# A smaller test would be something like
+# https://github.com/bazelbuild/rules_foreign_cc/blob/0.6.0/examples/cmake_hello_world_lib/binary/BUILD.bazel
diff --git a/tests/openssl/BUILD.bazel b/tests/openssl/BUILD.bazel
new file mode 100644
index 0000000..36f2a23
--- /dev/null
+++ b/tests/openssl/BUILD.bazel
@@ -0,0 +1,4 @@
+exports_files(
+    srcs = glob(["**/*.h"]),
+    visibility = ["@openssl//:__pkg__"],
+)
diff --git a/tests/openssl/crypto/include/internal/bn_conf.h b/tests/openssl/crypto/include/internal/bn_conf.h
new file mode 100644
index 0000000..cb853e0
--- /dev/null
+++ b/tests/openssl/crypto/include/internal/bn_conf.h
@@ -0,0 +1,28 @@
+/* WARNING: do not edit! */
+/* Generated by Makefile from crypto/include/internal/bn_conf.h.in */
+/*
+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef HEADER_BN_CONF_H
+#define HEADER_BN_CONF_H
+
+/*
+ * The contents of this file are not used in the UEFI build, as
+ * both 32-bit and 64-bit builds are supported from a single run
+ * of the Configure script.
+ */
+
+/* Should we define BN_DIV2W here? */
+
+/* Only one for the following should be defined */
+#define SIXTY_FOUR_BIT_LONG
+#undef SIXTY_FOUR_BIT
+#undef THIRTY_TWO_BIT
+
+#endif
diff --git a/tests/openssl/crypto/include/internal/dso_conf.h b/tests/openssl/crypto/include/internal/dso_conf.h
new file mode 100644
index 0000000..71ff370
--- /dev/null
+++ b/tests/openssl/crypto/include/internal/dso_conf.h
@@ -0,0 +1,17 @@
+/* WARNING: do not edit! */
+/* Generated by Makefile from crypto/include/internal/dso_conf.h.in */
+/*
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef HEADER_DSO_CONF_H
+#define HEADER_DSO_CONF_H
+#define DSO_DLFCN
+#define HAVE_DLFCN_H
+#define DSO_EXTENSION ".dylib"
+#endif
diff --git a/tests/openssl/include/openssl/opensslconf.h b/tests/openssl/include/openssl/opensslconf.h
new file mode 100644
index 0000000..2c28a2b
--- /dev/null
+++ b/tests/openssl/include/openssl/opensslconf.h
@@ -0,0 +1,191 @@
+/*
+ * WARNING: do not edit!
+ * Generated by Makefile from include/openssl/opensslconf.h.in
+ *
+ * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslv.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef OPENSSL_ALGORITHM_DEFINES
+#error OPENSSL_ALGORITHM_DEFINES no longer supported
+#endif
+
+/*
+ * OpenSSL was configured with the following options:
+ */
+
+#ifndef OPENSSL_NO_MD2
+#define OPENSSL_NO_MD2
+#endif
+#ifndef OPENSSL_NO_RC5
+#define OPENSSL_NO_RC5
+#endif
+#ifndef OPENSSL_THREADS
+#define OPENSSL_THREADS
+#endif
+#ifndef OPENSSL_RAND_SEED_OS
+#define OPENSSL_RAND_SEED_OS
+#endif
+#ifndef OPENSSL_NO_ASAN
+#define OPENSSL_NO_ASAN
+#endif
+#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+#define OPENSSL_NO_CRYPTO_MDEBUG
+#endif
+#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
+#define OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
+#endif
+#ifndef OPENSSL_NO_DEVCRYPTOENG
+#define OPENSSL_NO_DEVCRYPTOENG
+#endif
+#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+#define OPENSSL_NO_EC_NISTP_64_GCC_128
+#endif
+#ifndef OPENSSL_NO_EGD
+#define OPENSSL_NO_EGD
+#endif
+#ifndef OPENSSL_NO_EXTERNAL_TESTS
+#define OPENSSL_NO_EXTERNAL_TESTS
+#endif
+#ifndef OPENSSL_NO_FUZZ_AFL
+#define OPENSSL_NO_FUZZ_AFL
+#endif
+#ifndef OPENSSL_NO_FUZZ_LIBFUZZER
+#define OPENSSL_NO_FUZZ_LIBFUZZER
+#endif
+#ifndef OPENSSL_NO_HEARTBEATS
+#define OPENSSL_NO_HEARTBEATS
+#endif
+#ifndef OPENSSL_NO_MSAN
+#define OPENSSL_NO_MSAN
+#endif
+#ifndef OPENSSL_NO_SCTP
+#define OPENSSL_NO_SCTP
+#endif
+#ifndef OPENSSL_NO_SSL_TRACE
+#define OPENSSL_NO_SSL_TRACE
+#endif
+#ifndef OPENSSL_NO_SSL3
+#define OPENSSL_NO_SSL3
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+#define OPENSSL_NO_SSL3_METHOD
+#endif
+#ifndef OPENSSL_NO_UBSAN
+#define OPENSSL_NO_UBSAN
+#endif
+#ifndef OPENSSL_NO_UNIT_TEST
+#define OPENSSL_NO_UNIT_TEST
+#endif
+#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS
+#define OPENSSL_NO_WEAK_SSL_CIPHERS
+#endif
+#ifndef OPENSSL_NO_STATIC_ENGINE
+#define OPENSSL_NO_STATIC_ENGINE
+#endif
+
+/*
+ * Sometimes OPENSSSL_NO_xxx ends up with an empty file and some compilers
+ * don't like that.  This will hopefully silence them.
+ */
+#define NON_EMPTY_TRANSLATION_UNIT static void *dummy = &dummy;
+
+/*
+ * Applications should use -DOPENSSL_API_COMPAT=<version> to suppress the
+ * declarations of functions deprecated in or before <version>. Otherwise, they
+ * still won't see them if the library has been built to disable deprecated
+ * functions.
+ */
+#ifndef DECLARE_DEPRECATED
+#define DECLARE_DEPRECATED(f) f;
+#ifdef __GNUC__
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)
+#undef DECLARE_DEPRECATED
+#define DECLARE_DEPRECATED(f) f __attribute__((deprecated));
+#endif
+#endif
+#endif
+
+#ifndef OPENSSL_FILE
+#ifdef OPENSSL_NO_FILENAMES
+#define OPENSSL_FILE ""
+#define OPENSSL_LINE 0
+#else
+#define OPENSSL_FILE __FILE__
+#define OPENSSL_LINE __LINE__
+#endif
+#endif
+
+#ifndef OPENSSL_MIN_API
+#define OPENSSL_MIN_API 0
+#endif
+
+#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < OPENSSL_MIN_API
+#undef OPENSSL_API_COMPAT
+#define OPENSSL_API_COMPAT OPENSSL_MIN_API
+#endif
+
+/*
+ * Do not deprecate things to be deprecated in version 1.2.0 before the
+ * OpenSSL version number matches.
+ */
+#if OPENSSL_VERSION_NUMBER < 0x10200000L
+#define DEPRECATEDIN_1_2_0(f) f;
+#elif OPENSSL_API_COMPAT < 0x10200000L
+#define DEPRECATEDIN_1_2_0(f) DECLARE_DEPRECATED(f)
+#else
+#define DEPRECATEDIN_1_2_0(f)
+#endif
+
+#if OPENSSL_API_COMPAT < 0x10100000L
+#define DEPRECATEDIN_1_1_0(f) DECLARE_DEPRECATED(f)
+#else
+#define DEPRECATEDIN_1_1_0(f)
+#endif
+
+#if OPENSSL_API_COMPAT < 0x10000000L
+#define DEPRECATEDIN_1_0_0(f) DECLARE_DEPRECATED(f)
+#else
+#define DEPRECATEDIN_1_0_0(f)
+#endif
+
+#if OPENSSL_API_COMPAT < 0x00908000L
+#define DEPRECATEDIN_0_9_8(f) DECLARE_DEPRECATED(f)
+#else
+#define DEPRECATEDIN_0_9_8(f)
+#endif
+
+/* Generate 80386 code? */
+#undef I386_ONLY
+
+#undef OPENSSL_UNISTD
+#define OPENSSL_UNISTD <unistd.h>
+
+#undef OPENSSL_EXPORT_VAR_AS_FUNCTION
+
+/*
+ * The following are cipher-specific, but are part of the public API.
+ */
+#if !defined(OPENSSL_SYS_UEFI)
+#undef BN_LLONG
+/* Only one for the following should be defined */
+#define SIXTY_FOUR_BIT_LONG
+#undef SIXTY_FOUR_BIT
+#undef THIRTY_TWO_BIT
+#endif
+
+#define RC4_INT unsigned int
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tests/openssl/openssl.bazel b/tests/openssl/openssl.bazel
new file mode 100644
index 0000000..c8bbf21
--- /dev/null
+++ b/tests/openssl/openssl.bazel
@@ -0,0 +1,916 @@
+# 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"])
+
+COPTS = [
+    "-DL_ENDIAN",
+    "-DOPENSSL_PIC",
+    "-DOPENSSL_CPUID_OBJ",
+    "-DOPENSSL_IA32_SSE2",
+    "-DOPENSSL_BN_ASM_MONT",
+    "-DOPENSSL_BN_ASM_MONT5",
+    "-DOPENSSL_BN_ASM_GF2m",
+    "-DSHA1_ASM",
+    "-DSHA256_ASM",
+    "-DSHA512_ASM",
+    "-DKECCAK1600_ASM",
+    "-DRC4_ASM",
+    "-DMD5_ASM",
+    "-DAES_ASM",
+    "-DVPAES_ASM",
+    "-DBSAES_ASM",
+    "-DGHASH_ASM",
+    "-DECP_NISTZ256_ASM",
+    "-DX25519_ASM",
+    "-DPOLY1305_ASM",
+    "-DOPENSSLDIR=\\\"/usr/local/ssl\\\"",
+    "-DENGINESDIR=\\\"/usr/local/lib/engines-1.1\\\"",
+    "-D_REENTRANT",
+    "-DNDEBUG",
+    "-Wno-unused-command-line-argument",
+]
+
+CONF_FILES = [
+    "crypto/include/internal/bn_conf.h",
+    "crypto/include/internal/dso_conf.h",
+    "include/openssl/opensslconf.h",
+]
+
+genrule(
+    name = "configure",
+    srcs = [("@com_grail_bazel_toolchain//tests/openssl:" + f) for f in CONF_FILES],
+    outs = CONF_FILES,
+    cmd = "\n".join([
+        "cp $(location @com_grail_bazel_toolchain//tests/openssl:{0}) $(location {0})".format(f)
+        for f in CONF_FILES
+    ]),
+    visibility = ["//visibility:private"],
+)
+
+HDRS = glob(["include/**/*.h"]) + ["include/openssl/opensslconf.h"]
+
+genrule(
+    name = "gen-buildinf_h",
+    srcs = ["util/mkbuildinf.pl"],
+    outs = ["crypto/buildinf.h"],
+    cmd = "perl $(location util/mkbuildinf.pl) 'dummy' 'dummy' > $(location crypto/buildinf.h)",
+)
+
+genrule(
+    name = "gen-asm",
+    srcs = [
+        "crypto/aes/asm/aes-x86_64.pl",
+        "crypto/aes/asm/aesni-mb-x86_64.pl",
+        "crypto/aes/asm/aesni-sha1-x86_64.pl",
+        "crypto/aes/asm/aesni-sha256-x86_64.pl",
+        "crypto/aes/asm/aesni-x86_64.pl",
+        "crypto/aes/asm/bsaes-x86_64.pl",
+        "crypto/aes/asm/vpaes-x86_64.pl",
+        "crypto/bn/asm/rsaz-avx2.pl",
+        "crypto/bn/asm/rsaz-x86_64.pl",
+        "crypto/bn/asm/x86_64-gf2m.pl",
+        "crypto/bn/asm/x86_64-mont.pl",
+        "crypto/bn/asm/x86_64-mont5.pl",
+        "crypto/camellia/asm/cmll-x86_64.pl",
+        "crypto/chacha/asm/chacha-x86_64.pl",
+        "crypto/ec/ecp_nistz256_table.c",
+        "crypto/ec/asm/ecp_nistz256-x86_64.pl",
+        "crypto/ec/asm/x25519-x86_64.pl",
+        "crypto/md5/asm/md5-x86_64.pl",
+        "crypto/modes/asm/aesni-gcm-x86_64.pl",
+        "crypto/modes/asm/ghash-x86_64.pl",
+        "crypto/perlasm/x86_64-xlate.pl",
+        "crypto/poly1305/asm/poly1305-x86_64.pl",
+        "crypto/rc4/asm/rc4-md5-x86_64.pl",
+        "crypto/rc4/asm/rc4-x86_64.pl",
+        "crypto/sha/asm/keccak1600-x86_64.pl",
+        "crypto/sha/asm/sha1-mb-x86_64.pl",
+        "crypto/sha/asm/sha1-x86_64.pl",
+        "crypto/sha/asm/sha256-mb-x86_64.pl",
+        "crypto/sha/asm/sha512-x86_64.pl",
+        "crypto/whrlpool/asm/wp-x86_64.pl",
+        "crypto/x86_64cpuid.pl",
+        "engines/asm/e_padlock-x86_64.pl",
+    ],
+    outs = [
+        "crypto/aes/aes-x86_64.s",
+        "crypto/aes/aesni-mb-x86_64.s",
+        "crypto/aes/aesni-sha1-x86_64.s",
+        "crypto/aes/aesni-sha256-x86_64.s",
+        "crypto/aes/aesni-x86_64.s",
+        "crypto/aes/bsaes-x86_64.s",
+        "crypto/aes/vpaes-x86_64.s",
+        "crypto/bn/rsaz-avx2.s",
+        "crypto/bn/rsaz-x86_64.s",
+        "crypto/bn/x86_64-gf2m.s",
+        "crypto/bn/x86_64-mont.s",
+        "crypto/bn/x86_64-mont5.s",
+        "crypto/camellia/cmll-x86_64.s",
+        "crypto/chacha/chacha-x86_64.s",
+        "crypto/ec/ecp_nistz256-x86_64.s",
+        "crypto/ec/x25519-x86_64.s",
+        "crypto/md5/md5-x86_64.s",
+        "crypto/modes/aesni-gcm-x86_64.s",
+        "crypto/modes/ghash-x86_64.s",
+        "crypto/poly1305/poly1305-x86_64.s",
+        "crypto/rc4/rc4-md5-x86_64.s",
+        "crypto/rc4/rc4-x86_64.s",
+        "crypto/sha/keccak1600-x86_64.s",
+        "crypto/sha/sha1-mb-x86_64.s",
+        "crypto/sha/sha1-x86_64.s",
+        "crypto/sha/sha256-mb-x86_64.s",
+        "crypto/sha/sha256-x86_64.s",
+        "crypto/sha/sha512-x86_64.s",
+        "crypto/whrlpool/wp-x86_64.s",
+        "crypto/x86_64cpuid.s",
+        "engines/e_padlock-x86_64.s",
+    ],
+    cmd = "\n".join([
+        "FLAVOR='elf'",
+        "if [[ $$(uname -s) == 'Darwin' ]]; then FLAVOR='macosx'; fi",
+        "perl $(location crypto/aes/asm/aes-x86_64.pl) $$FLAVOR $(location crypto/aes/aes-x86_64.s)",
+        "perl $(location crypto/aes/asm/aesni-mb-x86_64.pl) $$FLAVOR $(location crypto/aes/aesni-mb-x86_64.s)",
+        "perl $(location crypto/aes/asm/aesni-sha1-x86_64.pl) $$FLAVOR $(location crypto/aes/aesni-sha1-x86_64.s)",
+        "perl $(location crypto/aes/asm/aesni-sha256-x86_64.pl) $$FLAVOR $(location crypto/aes/aesni-sha256-x86_64.s)",
+        "perl $(location crypto/aes/asm/aesni-x86_64.pl) $$FLAVOR $(location crypto/aes/aesni-x86_64.s)",
+        "perl $(location crypto/aes/asm/bsaes-x86_64.pl) $$FLAVOR $(location crypto/aes/bsaes-x86_64.s)",
+        "perl $(location crypto/aes/asm/vpaes-x86_64.pl) $$FLAVOR $(location crypto/aes/vpaes-x86_64.s)",
+        "perl $(location crypto/bn/asm/rsaz-avx2.pl) $$FLAVOR $(location crypto/bn/rsaz-avx2.s)",
+        "perl $(location crypto/bn/asm/rsaz-x86_64.pl) $$FLAVOR $(location crypto/bn/rsaz-x86_64.s)",
+        "perl $(location crypto/bn/asm/x86_64-gf2m.pl) $$FLAVOR $(location crypto/bn/x86_64-gf2m.s)",
+        "perl $(location crypto/bn/asm/x86_64-mont.pl) $$FLAVOR $(location crypto/bn/x86_64-mont.s)",
+        "perl $(location crypto/bn/asm/x86_64-mont5.pl) $$FLAVOR $(location crypto/bn/x86_64-mont5.s)",
+        "perl $(location crypto/camellia/asm/cmll-x86_64.pl) $$FLAVOR $(location crypto/camellia/cmll-x86_64.s)",
+        "perl $(location crypto/chacha/asm/chacha-x86_64.pl) $$FLAVOR $(location crypto/chacha/chacha-x86_64.s)",
+        "perl $(location crypto/ec/asm/ecp_nistz256-x86_64.pl) $$FLAVOR $(location crypto/ec/ecp_nistz256-x86_64.s)",
+        "perl $(location crypto/ec/asm/x25519-x86_64.pl) $$FLAVOR $(location crypto/ec/x25519-x86_64.s)",
+        "perl $(location crypto/md5/asm/md5-x86_64.pl) $$FLAVOR $(location crypto/md5/md5-x86_64.s)",
+        "perl $(location crypto/modes/asm/aesni-gcm-x86_64.pl) $$FLAVOR $(location crypto/modes/aesni-gcm-x86_64.s)",
+        "perl $(location crypto/modes/asm/ghash-x86_64.pl) $$FLAVOR $(location crypto/modes/ghash-x86_64.s)",
+        "perl $(location crypto/poly1305/asm/poly1305-x86_64.pl) $$FLAVOR $(location crypto/poly1305/poly1305-x86_64.s)",
+        "perl $(location crypto/rc4/asm/rc4-md5-x86_64.pl) $$FLAVOR $(location crypto/rc4/rc4-md5-x86_64.s)",
+        "perl $(location crypto/rc4/asm/rc4-x86_64.pl) $$FLAVOR $(location crypto/rc4/rc4-x86_64.s)",
+        "perl $(location crypto/sha/asm/keccak1600-x86_64.pl) $$FLAVOR $(location crypto/sha/keccak1600-x86_64.s)",
+        "perl $(location crypto/sha/asm/sha1-mb-x86_64.pl) $$FLAVOR $(location crypto/sha/sha1-mb-x86_64.s)",
+        "perl $(location crypto/sha/asm/sha1-x86_64.pl) $$FLAVOR $(location crypto/sha/sha1-x86_64.s)",
+        "perl $(location crypto/sha/asm/sha256-mb-x86_64.pl) $$FLAVOR $(location crypto/sha/sha256-mb-x86_64.s)",
+        "perl $(location crypto/sha/asm/sha512-x86_64.pl) $$FLAVOR $(location crypto/sha/sha256-x86_64.s)",
+        "perl $(location crypto/sha/asm/sha512-x86_64.pl) $$FLAVOR $(location crypto/sha/sha512-x86_64.s)",
+        "perl $(location crypto/whrlpool/asm/wp-x86_64.pl) $$FLAVOR $(location crypto/whrlpool/wp-x86_64.s)",
+        "perl $(location crypto/x86_64cpuid.pl) $$FLAVOR $(location crypto/x86_64cpuid.s)",
+        "perl $(location engines/asm/e_padlock-x86_64.pl) $$FLAVOR $(location engines/e_padlock-x86_64.s)",
+    ]),
+)
+
+cc_library(
+    name = "libcrypto",
+    srcs = [
+        "crypto/aes/aes-x86_64.s",
+        "crypto/aes/aes_cfb.c",
+        "crypto/aes/aes_ecb.c",
+        "crypto/aes/aes_ige.c",
+        "crypto/aes/aes_misc.c",
+        "crypto/aes/aes_ofb.c",
+        "crypto/aes/aes_wrap.c",
+        "crypto/aes/aesni-mb-x86_64.s",
+        "crypto/aes/aesni-sha1-x86_64.s",
+        "crypto/aes/aesni-sha256-x86_64.s",
+        "crypto/aes/aesni-x86_64.s",
+        "crypto/aes/bsaes-x86_64.s",
+        "crypto/aes/vpaes-x86_64.s",
+        "crypto/aria/aria.c",
+        "crypto/asn1/a_bitstr.c",
+        "crypto/asn1/a_d2i_fp.c",
+        "crypto/asn1/a_digest.c",
+        "crypto/asn1/a_dup.c",
+        "crypto/asn1/a_gentm.c",
+        "crypto/asn1/a_i2d_fp.c",
+        "crypto/asn1/a_int.c",
+        "crypto/asn1/a_mbstr.c",
+        "crypto/asn1/a_object.c",
+        "crypto/asn1/a_octet.c",
+        "crypto/asn1/a_print.c",
+        "crypto/asn1/a_sign.c",
+        "crypto/asn1/a_strex.c",
+        "crypto/asn1/a_strnid.c",
+        "crypto/asn1/a_time.c",
+        "crypto/asn1/a_type.c",
+        "crypto/asn1/a_utctm.c",
+        "crypto/asn1/a_utf8.c",
+        "crypto/asn1/a_verify.c",
+        "crypto/asn1/ameth_lib.c",
+        "crypto/asn1/asn1_err.c",
+        "crypto/asn1/asn1_gen.c",
+        "crypto/asn1/asn1_item_list.c",
+        "crypto/asn1/asn1_lib.c",
+        "crypto/asn1/asn1_par.c",
+        "crypto/asn1/asn_mime.c",
+        "crypto/asn1/asn_moid.c",
+        "crypto/asn1/asn_mstbl.c",
+        "crypto/asn1/asn_pack.c",
+        "crypto/asn1/bio_asn1.c",
+        "crypto/asn1/bio_ndef.c",
+        "crypto/asn1/d2i_pr.c",
+        "crypto/asn1/d2i_pu.c",
+        "crypto/asn1/evp_asn1.c",
+        "crypto/asn1/f_int.c",
+        "crypto/asn1/f_string.c",
+        "crypto/asn1/i2d_pr.c",
+        "crypto/asn1/i2d_pu.c",
+        "crypto/asn1/n_pkey.c",
+        "crypto/asn1/nsseq.c",
+        "crypto/asn1/p5_pbe.c",
+        "crypto/asn1/p5_pbev2.c",
+        "crypto/asn1/p5_scrypt.c",
+        "crypto/asn1/p8_pkey.c",
+        "crypto/asn1/t_bitst.c",
+        "crypto/asn1/t_pkey.c",
+        "crypto/asn1/t_spki.c",
+        "crypto/asn1/tasn_dec.c",
+        "crypto/asn1/tasn_enc.c",
+        "crypto/asn1/tasn_fre.c",
+        "crypto/asn1/tasn_new.c",
+        "crypto/asn1/tasn_prn.c",
+        "crypto/asn1/tasn_scn.c",
+        "crypto/asn1/tasn_typ.c",
+        "crypto/asn1/tasn_utl.c",
+        "crypto/asn1/x_algor.c",
+        "crypto/asn1/x_bignum.c",
+        "crypto/asn1/x_info.c",
+        "crypto/asn1/x_int64.c",
+        "crypto/asn1/x_long.c",
+        "crypto/asn1/x_pkey.c",
+        "crypto/asn1/x_sig.c",
+        "crypto/asn1/x_spki.c",
+        "crypto/asn1/x_val.c",
+        "crypto/async/arch/async_null.c",
+        "crypto/async/arch/async_posix.c",
+        "crypto/async/arch/async_win.c",
+        "crypto/async/async.c",
+        "crypto/async/async_err.c",
+        "crypto/async/async_wait.c",
+        "crypto/bf/bf_cfb64.c",
+        "crypto/bf/bf_ecb.c",
+        "crypto/bf/bf_enc.c",
+        "crypto/bf/bf_ofb64.c",
+        "crypto/bf/bf_skey.c",
+        "crypto/bio/b_addr.c",
+        "crypto/bio/b_dump.c",
+        "crypto/bio/b_print.c",
+        "crypto/bio/b_sock.c",
+        "crypto/bio/b_sock2.c",
+        "crypto/bio/bf_buff.c",
+        "crypto/bio/bf_lbuf.c",
+        "crypto/bio/bf_nbio.c",
+        "crypto/bio/bf_null.c",
+        "crypto/bio/bio_cb.c",
+        "crypto/bio/bio_err.c",
+        "crypto/bio/bio_lib.c",
+        "crypto/bio/bio_meth.c",
+        "crypto/bio/bss_acpt.c",
+        "crypto/bio/bss_bio.c",
+        "crypto/bio/bss_conn.c",
+        "crypto/bio/bss_dgram.c",
+        "crypto/bio/bss_fd.c",
+        "crypto/bio/bss_file.c",
+        "crypto/bio/bss_log.c",
+        "crypto/bio/bss_mem.c",
+        "crypto/bio/bss_null.c",
+        "crypto/bio/bss_sock.c",
+        "crypto/blake2/blake2b.c",
+        "crypto/blake2/blake2s.c",
+        "crypto/blake2/m_blake2b.c",
+        "crypto/blake2/m_blake2s.c",
+        "crypto/bn/asm/x86_64-gcc.c",
+        "crypto/bn/bn_add.c",
+        "crypto/bn/bn_blind.c",
+        "crypto/bn/bn_const.c",
+        "crypto/bn/bn_ctx.c",
+        "crypto/bn/bn_depr.c",
+        "crypto/bn/bn_dh.c",
+        "crypto/bn/bn_div.c",
+        "crypto/bn/bn_err.c",
+        "crypto/bn/bn_exp.c",
+        "crypto/bn/bn_exp2.c",
+        "crypto/bn/bn_gcd.c",
+        "crypto/bn/bn_gf2m.c",
+        "crypto/bn/bn_intern.c",
+        "crypto/bn/bn_kron.c",
+        "crypto/bn/bn_lib.c",
+        "crypto/bn/bn_mod.c",
+        "crypto/bn/bn_mont.c",
+        "crypto/bn/bn_mpi.c",
+        "crypto/bn/bn_mul.c",
+        "crypto/bn/bn_nist.c",
+        "crypto/bn/bn_prime.c",
+        "crypto/bn/bn_print.c",
+        "crypto/bn/bn_rand.c",
+        "crypto/bn/bn_recp.c",
+        "crypto/bn/bn_shift.c",
+        "crypto/bn/bn_sqr.c",
+        "crypto/bn/bn_sqrt.c",
+        "crypto/bn/bn_srp.c",
+        "crypto/bn/bn_word.c",
+        "crypto/bn/bn_x931p.c",
+        "crypto/bn/rsaz-avx2.s",
+        "crypto/bn/rsaz-x86_64.s",
+        "crypto/bn/rsaz_exp.c",
+        "crypto/bn/x86_64-gf2m.s",
+        "crypto/bn/x86_64-mont.s",
+        "crypto/bn/x86_64-mont5.s",
+        "crypto/buffer/buf_err.c",
+        "crypto/buffer/buffer.c",
+        "crypto/camellia/cmll-x86_64.s",
+        "crypto/camellia/cmll_cfb.c",
+        "crypto/camellia/cmll_ctr.c",
+        "crypto/camellia/cmll_ecb.c",
+        "crypto/camellia/cmll_misc.c",
+        "crypto/camellia/cmll_ofb.c",
+        "crypto/cast/c_cfb64.c",
+        "crypto/cast/c_ecb.c",
+        "crypto/cast/c_enc.c",
+        "crypto/cast/c_ofb64.c",
+        "crypto/cast/c_skey.c",
+        "crypto/chacha/chacha-x86_64.s",
+        "crypto/cmac/cm_ameth.c",
+        "crypto/cmac/cm_pmeth.c",
+        "crypto/cmac/cmac.c",
+        "crypto/cms/cms_asn1.c",
+        "crypto/cms/cms_att.c",
+        "crypto/cms/cms_cd.c",
+        "crypto/cms/cms_dd.c",
+        "crypto/cms/cms_enc.c",
+        "crypto/cms/cms_env.c",
+        "crypto/cms/cms_err.c",
+        "crypto/cms/cms_ess.c",
+        "crypto/cms/cms_io.c",
+        "crypto/cms/cms_kari.c",
+        "crypto/cms/cms_lib.c",
+        "crypto/cms/cms_pwri.c",
+        "crypto/cms/cms_sd.c",
+        "crypto/cms/cms_smime.c",
+        "crypto/comp/c_zlib.c",
+        "crypto/comp/comp_err.c",
+        "crypto/comp/comp_lib.c",
+        "crypto/conf/conf_api.c",
+        "crypto/conf/conf_def.c",
+        "crypto/conf/conf_err.c",
+        "crypto/conf/conf_lib.c",
+        "crypto/conf/conf_mall.c",
+        "crypto/conf/conf_mod.c",
+        "crypto/conf/conf_sap.c",
+        "crypto/conf/conf_ssl.c",
+        "crypto/cpt_err.c",
+        "crypto/cryptlib.c",
+        "crypto/ct/ct_b64.c",
+        "crypto/ct/ct_err.c",
+        "crypto/ct/ct_log.c",
+        "crypto/ct/ct_oct.c",
+        "crypto/ct/ct_policy.c",
+        "crypto/ct/ct_prn.c",
+        "crypto/ct/ct_sct.c",
+        "crypto/ct/ct_sct_ctx.c",
+        "crypto/ct/ct_vfy.c",
+        "crypto/ct/ct_x509v3.c",
+        "crypto/ctype.c",
+        "crypto/cversion.c",
+        "crypto/des/cbc_cksm.c",
+        "crypto/des/cbc_enc.c",
+        "crypto/des/cfb64ede.c",
+        "crypto/des/cfb64enc.c",
+        "crypto/des/cfb_enc.c",
+        "crypto/des/des_enc.c",
+        "crypto/des/ecb3_enc.c",
+        "crypto/des/ecb_enc.c",
+        "crypto/des/fcrypt.c",
+        "crypto/des/fcrypt_b.c",
+        "crypto/des/ofb64ede.c",
+        "crypto/des/ofb64enc.c",
+        "crypto/des/ofb_enc.c",
+        "crypto/des/pcbc_enc.c",
+        "crypto/des/qud_cksm.c",
+        "crypto/des/rand_key.c",
+        "crypto/des/set_key.c",
+        "crypto/des/str2key.c",
+        "crypto/des/xcbc_enc.c",
+        "crypto/dh/dh_ameth.c",
+        "crypto/dh/dh_asn1.c",
+        "crypto/dh/dh_check.c",
+        "crypto/dh/dh_depr.c",
+        "crypto/dh/dh_err.c",
+        "crypto/dh/dh_gen.c",
+        "crypto/dh/dh_kdf.c",
+        "crypto/dh/dh_key.c",
+        "crypto/dh/dh_lib.c",
+        "crypto/dh/dh_meth.c",
+        "crypto/dh/dh_pmeth.c",
+        "crypto/dh/dh_prn.c",
+        "crypto/dh/dh_rfc5114.c",
+        "crypto/dh/dh_rfc7919.c",
+        "crypto/dsa/dsa_ameth.c",
+        "crypto/dsa/dsa_asn1.c",
+        "crypto/dsa/dsa_depr.c",
+        "crypto/dsa/dsa_err.c",
+        "crypto/dsa/dsa_gen.c",
+        "crypto/dsa/dsa_key.c",
+        "crypto/dsa/dsa_lib.c",
+        "crypto/dsa/dsa_meth.c",
+        "crypto/dsa/dsa_ossl.c",
+        "crypto/dsa/dsa_pmeth.c",
+        "crypto/dsa/dsa_prn.c",
+        "crypto/dsa/dsa_sign.c",
+        "crypto/dsa/dsa_vrf.c",
+        "crypto/dso/dso_dl.c",
+        "crypto/dso/dso_dlfcn.c",
+        "crypto/dso/dso_err.c",
+        "crypto/dso/dso_lib.c",
+        "crypto/dso/dso_openssl.c",
+        "crypto/dso/dso_vms.c",
+        "crypto/dso/dso_win32.c",
+        "crypto/ebcdic.c",
+        "crypto/ec/curve25519.c",
+        "crypto/ec/curve448/arch_32/f_impl.c",
+        "crypto/ec/curve448/curve448.c",
+        "crypto/ec/curve448/curve448_tables.c",
+        "crypto/ec/curve448/eddsa.c",
+        "crypto/ec/curve448/f_generic.c",
+        "crypto/ec/curve448/scalar.c",
+        "crypto/ec/ec2_oct.c",
+        "crypto/ec/ec2_smpl.c",
+        "crypto/ec/ec_ameth.c",
+        "crypto/ec/ec_asn1.c",
+        "crypto/ec/ec_check.c",
+        "crypto/ec/ec_curve.c",
+        "crypto/ec/ec_cvt.c",
+        "crypto/ec/ec_err.c",
+        "crypto/ec/ec_key.c",
+        "crypto/ec/ec_kmeth.c",
+        "crypto/ec/ec_lib.c",
+        "crypto/ec/ec_mult.c",
+        "crypto/ec/ec_oct.c",
+        "crypto/ec/ec_pmeth.c",
+        "crypto/ec/ec_print.c",
+        "crypto/ec/ecdh_kdf.c",
+        "crypto/ec/ecdh_ossl.c",
+        "crypto/ec/ecdsa_ossl.c",
+        "crypto/ec/ecdsa_sign.c",
+        "crypto/ec/ecdsa_vrf.c",
+        "crypto/ec/eck_prn.c",
+        "crypto/ec/ecp_mont.c",
+        "crypto/ec/ecp_nist.c",
+        "crypto/ec/ecp_nistp224.c",
+        "crypto/ec/ecp_nistp256.c",
+        "crypto/ec/ecp_nistp521.c",
+        "crypto/ec/ecp_nistputil.c",
+        "crypto/ec/ecp_nistz256-x86_64.s",
+        "crypto/ec/ecp_nistz256.c",
+        "crypto/ec/ecp_oct.c",
+        "crypto/ec/ecp_smpl.c",
+        "crypto/ec/ecx_meth.c",
+        "crypto/ec/x25519-x86_64.s",
+        "crypto/engine/eng_all.c",
+        "crypto/engine/eng_cnf.c",
+        "crypto/engine/eng_ctrl.c",
+        "crypto/engine/eng_dyn.c",
+        "crypto/engine/eng_err.c",
+        "crypto/engine/eng_fat.c",
+        "crypto/engine/eng_init.c",
+        "crypto/engine/eng_lib.c",
+        "crypto/engine/eng_list.c",
+        "crypto/engine/eng_openssl.c",
+        "crypto/engine/eng_pkey.c",
+        "crypto/engine/eng_rdrand.c",
+        "crypto/engine/eng_table.c",
+        "crypto/engine/tb_asnmth.c",
+        "crypto/engine/tb_cipher.c",
+        "crypto/engine/tb_dh.c",
+        "crypto/engine/tb_digest.c",
+        "crypto/engine/tb_dsa.c",
+        "crypto/engine/tb_eckey.c",
+        "crypto/engine/tb_pkmeth.c",
+        "crypto/engine/tb_rand.c",
+        "crypto/engine/tb_rsa.c",
+        "crypto/err/err.c",
+        "crypto/err/err_all.c",
+        "crypto/err/err_prn.c",
+        "crypto/evp/bio_b64.c",
+        "crypto/evp/bio_enc.c",
+        "crypto/evp/bio_md.c",
+        "crypto/evp/bio_ok.c",
+        "crypto/evp/c_allc.c",
+        "crypto/evp/c_alld.c",
+        "crypto/evp/cmeth_lib.c",
+        "crypto/evp/digest.c",
+        "crypto/evp/e_aes.c",
+        "crypto/evp/e_aes_cbc_hmac_sha1.c",
+        "crypto/evp/e_aes_cbc_hmac_sha256.c",
+        "crypto/evp/e_aria.c",
+        "crypto/evp/e_bf.c",
+        "crypto/evp/e_camellia.c",
+        "crypto/evp/e_cast.c",
+        "crypto/evp/e_chacha20_poly1305.c",
+        "crypto/evp/e_des.c",
+        "crypto/evp/e_des3.c",
+        "crypto/evp/e_idea.c",
+        "crypto/evp/e_null.c",
+        "crypto/evp/e_old.c",
+        "crypto/evp/e_rc2.c",
+        "crypto/evp/e_rc4.c",
+        "crypto/evp/e_rc4_hmac_md5.c",
+        "crypto/evp/e_rc5.c",
+        "crypto/evp/e_seed.c",
+        "crypto/evp/e_sm4.c",
+        "crypto/evp/e_xcbc_d.c",
+        "crypto/evp/encode.c",
+        "crypto/evp/evp_cnf.c",
+        "crypto/evp/evp_enc.c",
+        "crypto/evp/evp_err.c",
+        "crypto/evp/evp_key.c",
+        "crypto/evp/evp_lib.c",
+        "crypto/evp/evp_pbe.c",
+        "crypto/evp/evp_pkey.c",
+        "crypto/evp/m_md2.c",
+        "crypto/evp/m_md4.c",
+        "crypto/evp/m_md5.c",
+        "crypto/evp/m_md5_sha1.c",
+        "crypto/evp/m_mdc2.c",
+        "crypto/evp/m_null.c",
+        "crypto/evp/m_ripemd.c",
+        "crypto/evp/m_sha1.c",
+        "crypto/evp/m_sha3.c",
+        "crypto/evp/m_sigver.c",
+        "crypto/evp/m_wp.c",
+        "crypto/evp/names.c",
+        "crypto/evp/p5_crpt.c",
+        "crypto/evp/p5_crpt2.c",
+        "crypto/evp/p_dec.c",
+        "crypto/evp/p_enc.c",
+        "crypto/evp/p_lib.c",
+        "crypto/evp/p_open.c",
+        "crypto/evp/p_seal.c",
+        "crypto/evp/p_sign.c",
+        "crypto/evp/p_verify.c",
+        "crypto/evp/pbe_scrypt.c",
+        "crypto/evp/pmeth_fn.c",
+        "crypto/evp/pmeth_gn.c",
+        "crypto/evp/pmeth_lib.c",
+        "crypto/ex_data.c",
+        "crypto/getenv.c",
+        "crypto/hmac/hm_ameth.c",
+        "crypto/hmac/hm_pmeth.c",
+        "crypto/hmac/hmac.c",
+        "crypto/idea/i_cbc.c",
+        "crypto/idea/i_cfb64.c",
+        "crypto/idea/i_ecb.c",
+        "crypto/idea/i_ofb64.c",
+        "crypto/idea/i_skey.c",
+        "crypto/init.c",
+        "crypto/kdf/hkdf.c",
+        "crypto/kdf/kdf_err.c",
+        "crypto/kdf/scrypt.c",
+        "crypto/kdf/tls1_prf.c",
+        "crypto/lhash/lh_stats.c",
+        "crypto/lhash/lhash.c",
+        "crypto/md4/md4_dgst.c",
+        "crypto/md4/md4_one.c",
+        "crypto/md5/md5-x86_64.s",
+        "crypto/md5/md5_dgst.c",
+        "crypto/md5/md5_one.c",
+        "crypto/mdc2/mdc2_one.c",
+        "crypto/mdc2/mdc2dgst.c",
+        "crypto/mem.c",
+        "crypto/mem_dbg.c",
+        "crypto/mem_sec.c",
+        "crypto/modes/aesni-gcm-x86_64.s",
+        "crypto/modes/cbc128.c",
+        "crypto/modes/ccm128.c",
+        "crypto/modes/cfb128.c",
+        "crypto/modes/ctr128.c",
+        "crypto/modes/cts128.c",
+        "crypto/modes/gcm128.c",
+        "crypto/modes/ghash-x86_64.s",
+        "crypto/modes/ocb128.c",
+        "crypto/modes/ofb128.c",
+        "crypto/modes/wrap128.c",
+        "crypto/modes/xts128.c",
+        "crypto/o_dir.c",
+        "crypto/o_fips.c",
+        "crypto/o_fopen.c",
+        "crypto/o_init.c",
+        "crypto/o_str.c",
+        "crypto/o_time.c",
+        "crypto/objects/o_names.c",
+        "crypto/objects/obj_dat.c",
+        "crypto/objects/obj_err.c",
+        "crypto/objects/obj_lib.c",
+        "crypto/objects/obj_xref.c",
+        "crypto/ocsp/ocsp_asn.c",
+        "crypto/ocsp/ocsp_cl.c",
+        "crypto/ocsp/ocsp_err.c",
+        "crypto/ocsp/ocsp_ext.c",
+        "crypto/ocsp/ocsp_ht.c",
+        "crypto/ocsp/ocsp_lib.c",
+        "crypto/ocsp/ocsp_prn.c",
+        "crypto/ocsp/ocsp_srv.c",
+        "crypto/ocsp/ocsp_vfy.c",
+        "crypto/ocsp/v3_ocsp.c",
+        "crypto/pem/pem_all.c",
+        "crypto/pem/pem_err.c",
+        "crypto/pem/pem_info.c",
+        "crypto/pem/pem_lib.c",
+        "crypto/pem/pem_oth.c",
+        "crypto/pem/pem_pk8.c",
+        "crypto/pem/pem_pkey.c",
+        "crypto/pem/pem_sign.c",
+        "crypto/pem/pem_x509.c",
+        "crypto/pem/pem_xaux.c",
+        "crypto/pem/pvkfmt.c",
+        "crypto/pkcs12/p12_add.c",
+        "crypto/pkcs12/p12_asn.c",
+        "crypto/pkcs12/p12_attr.c",
+        "crypto/pkcs12/p12_crpt.c",
+        "crypto/pkcs12/p12_crt.c",
+        "crypto/pkcs12/p12_decr.c",
+        "crypto/pkcs12/p12_init.c",
+        "crypto/pkcs12/p12_key.c",
+        "crypto/pkcs12/p12_kiss.c",
+        "crypto/pkcs12/p12_mutl.c",
+        "crypto/pkcs12/p12_npas.c",
+        "crypto/pkcs12/p12_p8d.c",
+        "crypto/pkcs12/p12_p8e.c",
+        "crypto/pkcs12/p12_sbag.c",
+        "crypto/pkcs12/p12_utl.c",
+        "crypto/pkcs12/pk12err.c",
+        "crypto/pkcs7/bio_pk7.c",
+        "crypto/pkcs7/pk7_asn1.c",
+        "crypto/pkcs7/pk7_attr.c",
+        "crypto/pkcs7/pk7_doit.c",
+        "crypto/pkcs7/pk7_lib.c",
+        "crypto/pkcs7/pk7_mime.c",
+        "crypto/pkcs7/pk7_smime.c",
+        "crypto/pkcs7/pkcs7err.c",
+        "crypto/poly1305/poly1305-x86_64.s",
+        "crypto/poly1305/poly1305.c",
+        "crypto/poly1305/poly1305_ameth.c",
+        "crypto/poly1305/poly1305_pmeth.c",
+        "crypto/rand/drbg_ctr.c",
+        "crypto/rand/drbg_lib.c",
+        "crypto/rand/rand_egd.c",
+        "crypto/rand/rand_err.c",
+        "crypto/rand/rand_lib.c",
+        "crypto/rand/rand_unix.c",
+        "crypto/rand/rand_vms.c",
+        "crypto/rand/rand_win.c",
+        "crypto/rand/randfile.c",
+        "crypto/rc2/rc2_cbc.c",
+        "crypto/rc2/rc2_ecb.c",
+        "crypto/rc2/rc2_skey.c",
+        "crypto/rc2/rc2cfb64.c",
+        "crypto/rc2/rc2ofb64.c",
+        "crypto/rc4/rc4-md5-x86_64.s",
+        "crypto/rc4/rc4-x86_64.s",
+        "crypto/ripemd/rmd_dgst.c",
+        "crypto/ripemd/rmd_one.c",
+        "crypto/rsa/rsa_ameth.c",
+        "crypto/rsa/rsa_asn1.c",
+        "crypto/rsa/rsa_chk.c",
+        "crypto/rsa/rsa_crpt.c",
+        "crypto/rsa/rsa_depr.c",
+        "crypto/rsa/rsa_err.c",
+        "crypto/rsa/rsa_gen.c",
+        "crypto/rsa/rsa_lib.c",
+        "crypto/rsa/rsa_meth.c",
+        "crypto/rsa/rsa_mp.c",
+        "crypto/rsa/rsa_none.c",
+        "crypto/rsa/rsa_oaep.c",
+        "crypto/rsa/rsa_ossl.c",
+        "crypto/rsa/rsa_pk1.c",
+        "crypto/rsa/rsa_pmeth.c",
+        "crypto/rsa/rsa_prn.c",
+        "crypto/rsa/rsa_pss.c",
+        "crypto/rsa/rsa_saos.c",
+        "crypto/rsa/rsa_sign.c",
+        "crypto/rsa/rsa_ssl.c",
+        "crypto/rsa/rsa_x931.c",
+        "crypto/rsa/rsa_x931g.c",
+        "crypto/seed/seed.c",
+        "crypto/seed/seed_cbc.c",
+        "crypto/seed/seed_cfb.c",
+        "crypto/seed/seed_ecb.c",
+        "crypto/seed/seed_ofb.c",
+        "crypto/sha/keccak1600-x86_64.s",
+        "crypto/sha/sha1-mb-x86_64.s",
+        "crypto/sha/sha1-x86_64.s",
+        "crypto/sha/sha1_one.c",
+        "crypto/sha/sha1dgst.c",
+        "crypto/sha/sha256-mb-x86_64.s",
+        "crypto/sha/sha256-x86_64.s",
+        "crypto/sha/sha256.c",
+        "crypto/sha/sha512-x86_64.s",
+        "crypto/sha/sha512.c",
+        "crypto/siphash/siphash.c",
+        "crypto/siphash/siphash_ameth.c",
+        "crypto/siphash/siphash_pmeth.c",
+        "crypto/sm2/sm2_crypt.c",
+        "crypto/sm2/sm2_err.c",
+        "crypto/sm2/sm2_pmeth.c",
+        "crypto/sm2/sm2_sign.c",
+        "crypto/sm3/m_sm3.c",
+        "crypto/sm3/sm3.c",
+        "crypto/sm4/sm4.c",
+        "crypto/srp/srp_lib.c",
+        "crypto/srp/srp_vfy.c",
+        "crypto/stack/stack.c",
+        "crypto/store/loader_file.c",
+        "crypto/store/store_err.c",
+        "crypto/store/store_init.c",
+        "crypto/store/store_lib.c",
+        "crypto/store/store_register.c",
+        "crypto/store/store_strings.c",
+        "crypto/threads_none.c",
+        "crypto/threads_pthread.c",
+        "crypto/threads_win.c",
+        "crypto/ts/ts_asn1.c",
+        "crypto/ts/ts_conf.c",
+        "crypto/ts/ts_err.c",
+        "crypto/ts/ts_lib.c",
+        "crypto/ts/ts_req_print.c",
+        "crypto/ts/ts_req_utils.c",
+        "crypto/ts/ts_rsp_print.c",
+        "crypto/ts/ts_rsp_sign.c",
+        "crypto/ts/ts_rsp_utils.c",
+        "crypto/ts/ts_rsp_verify.c",
+        "crypto/ts/ts_verify_ctx.c",
+        "crypto/txt_db/txt_db.c",
+        "crypto/ui/ui_err.c",
+        "crypto/ui/ui_lib.c",
+        "crypto/ui/ui_null.c",
+        "crypto/ui/ui_openssl.c",
+        "crypto/ui/ui_util.c",
+        "crypto/uid.c",
+        "crypto/whrlpool/wp-x86_64.s",
+        "crypto/whrlpool/wp_dgst.c",
+        "crypto/x509/by_dir.c",
+        "crypto/x509/by_file.c",
+        "crypto/x509/t_crl.c",
+        "crypto/x509/t_req.c",
+        "crypto/x509/t_x509.c",
+        "crypto/x509/x509_att.c",
+        "crypto/x509/x509_cmp.c",
+        "crypto/x509/x509_d2.c",
+        "crypto/x509/x509_def.c",
+        "crypto/x509/x509_err.c",
+        "crypto/x509/x509_ext.c",
+        "crypto/x509/x509_lu.c",
+        "crypto/x509/x509_meth.c",
+        "crypto/x509/x509_obj.c",
+        "crypto/x509/x509_r2x.c",
+        "crypto/x509/x509_req.c",
+        "crypto/x509/x509_set.c",
+        "crypto/x509/x509_trs.c",
+        "crypto/x509/x509_txt.c",
+        "crypto/x509/x509_v3.c",
+        "crypto/x509/x509_vfy.c",
+        "crypto/x509/x509_vpm.c",
+        "crypto/x509/x509cset.c",
+        "crypto/x509/x509name.c",
+        "crypto/x509/x509rset.c",
+        "crypto/x509/x509spki.c",
+        "crypto/x509/x509type.c",
+        "crypto/x509/x_all.c",
+        "crypto/x509/x_attrib.c",
+        "crypto/x509/x_crl.c",
+        "crypto/x509/x_exten.c",
+        "crypto/x509/x_name.c",
+        "crypto/x509/x_pubkey.c",
+        "crypto/x509/x_req.c",
+        "crypto/x509/x_x509.c",
+        "crypto/x509/x_x509a.c",
+        "crypto/x509v3/pcy_cache.c",
+        "crypto/x509v3/pcy_data.c",
+        "crypto/x509v3/pcy_lib.c",
+        "crypto/x509v3/pcy_map.c",
+        "crypto/x509v3/pcy_node.c",
+        "crypto/x509v3/pcy_tree.c",
+        "crypto/x509v3/v3_addr.c",
+        "crypto/x509v3/v3_admis.c",
+        "crypto/x509v3/v3_akey.c",
+        "crypto/x509v3/v3_akeya.c",
+        "crypto/x509v3/v3_alt.c",
+        "crypto/x509v3/v3_asid.c",
+        "crypto/x509v3/v3_bcons.c",
+        "crypto/x509v3/v3_bitst.c",
+        "crypto/x509v3/v3_conf.c",
+        "crypto/x509v3/v3_cpols.c",
+        "crypto/x509v3/v3_crld.c",
+        "crypto/x509v3/v3_enum.c",
+        "crypto/x509v3/v3_extku.c",
+        "crypto/x509v3/v3_genn.c",
+        "crypto/x509v3/v3_ia5.c",
+        "crypto/x509v3/v3_info.c",
+        "crypto/x509v3/v3_int.c",
+        "crypto/x509v3/v3_lib.c",
+        "crypto/x509v3/v3_ncons.c",
+        "crypto/x509v3/v3_pci.c",
+        "crypto/x509v3/v3_pcia.c",
+        "crypto/x509v3/v3_pcons.c",
+        "crypto/x509v3/v3_pku.c",
+        "crypto/x509v3/v3_pmaps.c",
+        "crypto/x509v3/v3_prn.c",
+        "crypto/x509v3/v3_purp.c",
+        "crypto/x509v3/v3_skey.c",
+        "crypto/x509v3/v3_sxnet.c",
+        "crypto/x509v3/v3_tlsf.c",
+        "crypto/x509v3/v3_utl.c",
+        "crypto/x509v3/v3err.c",
+        "crypto/x86_64cpuid.s",
+    ] + CONF_FILES + ["crypto/buildinf.h"] + glob([
+        "*.h",
+        "crypto/**/*.h",
+        "crypto/include/*.h",
+        "include/internal/*.h",
+    ]),
+    hdrs = HDRS + [
+        # These are not independent compile units, but are included in other .c files.
+        "crypto/LPdir_unix.c",
+        "crypto/des/ncbc_enc.c",
+    ],
+    copts = COPTS + [
+        "-isystem external/openssl",
+        "-iquote external/openssl/crypto",
+        "-iquote external/openssl/crypto/include",
+        "-iquote external/openssl/crypto/modes",
+        "-iquote external/openssl/crypto/ec/curve448",
+        "-iquote external/openssl/crypto/ec/curve448/arch_32",
+        "-iquote $(GENDIR)/external/openssl/crypto",
+        "-iquote $(GENDIR)/external/openssl/crypto/include",
+    ],
+    includes = ["include"],
+)
+
+cc_library(
+    name = "libssl",
+    srcs = [
+        "ssl/bio_ssl.c",
+        "ssl/d1_lib.c",
+        "ssl/d1_msg.c",
+        "ssl/d1_srtp.c",
+        "ssl/methods.c",
+        "ssl/packet.c",
+        "ssl/pqueue.c",
+        "ssl/record/dtls1_bitmap.c",
+        "ssl/record/rec_layer_d1.c",
+        "ssl/record/rec_layer_s3.c",
+        "ssl/record/ssl3_buffer.c",
+        "ssl/record/ssl3_record.c",
+        "ssl/record/ssl3_record_tls13.c",
+        "ssl/s3_cbc.c",
+        "ssl/s3_enc.c",
+        "ssl/s3_lib.c",
+        "ssl/s3_msg.c",
+        "ssl/ssl_asn1.c",
+        "ssl/ssl_cert.c",
+        "ssl/ssl_ciph.c",
+        "ssl/ssl_conf.c",
+        "ssl/ssl_err.c",
+        "ssl/ssl_init.c",
+        "ssl/ssl_lib.c",
+        "ssl/ssl_mcnf.c",
+        "ssl/ssl_rsa.c",
+        "ssl/ssl_sess.c",
+        "ssl/ssl_stat.c",
+        "ssl/ssl_txt.c",
+        "ssl/ssl_utst.c",
+        "ssl/statem/extensions.c",
+        "ssl/statem/extensions_clnt.c",
+        "ssl/statem/extensions_cust.c",
+        "ssl/statem/extensions_srvr.c",
+        "ssl/statem/statem.c",
+        "ssl/statem/statem_clnt.c",
+        "ssl/statem/statem_dtls.c",
+        "ssl/statem/statem_lib.c",
+        "ssl/statem/statem_srvr.c",
+        "ssl/t1_enc.c",
+        "ssl/t1_lib.c",
+        "ssl/t1_trce.c",
+        "ssl/tls13_enc.c",
+        "ssl/tls_srp.c",
+    ] + glob([
+        "ssl/**/*.h",
+    ]),
+    hdrs = HDRS,
+    copts = COPTS,
+    deps = [":libcrypto"],
+)
diff --git a/tests/pthread_link_test.cc b/tests/pthread_link_test.cc
new file mode 100644
index 0000000..363ec2f
--- /dev/null
+++ b/tests/pthread_link_test.cc
@@ -0,0 +1,38 @@
+// 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.
+
+#if defined(__linux__) && defined(_GNU_SOURCE)
+#include <dlfcn.h>
+#include <assert.h>
+
+// Checks that pthread symbols are loadable.
+//
+// This test verifies that dynamically linked libraries which
+// rely on pthread symbols can still access them.
+// Incorrect order of linking dependencies may remove unused
+// symbols and break shared libraries that are linked later.
+int main() {
+   // Find symbol
+   void* symbol = dlsym(RTLD_NEXT, "pthread_getspecific");
+   // Check that there is no error
+   assert(dlerror() == nullptr && symbol != nullptr);
+
+}
+
+#else//defined(__linux__) && defined(_GNU_SOURCE)
+
+int main() {
+}
+
+#endif//defined(__linux__) && defined(_GNU_SOURCE)
diff --git a/tests/rust/BUILD.bazel b/tests/rust/BUILD.bazel
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/rust/BUILD.bazel
diff --git a/tests/rust/git2-rs-cargo-toml.patch b/tests/rust/git2-rs-cargo-toml.patch
new file mode 100644
index 0000000..a0d588b
--- /dev/null
+++ b/tests/rust/git2-rs-cargo-toml.patch
@@ -0,0 +1,15 @@
+diff --git a/Cargo.toml b/Cargo.toml
+index 5837a47..d6ba77f 100644
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -60,10 +60,3 @@ unstable = []
+ vendored-libgit2 = ["libgit2-sys/vendored"]
+ vendored-openssl = ["openssl-sys/vendored", "libgit2-sys/vendored-openssl"]
+ zlib-ng-compat = ["libgit2-sys/zlib-ng-compat"]
+-[target."cfg(all(unix, not(target_os = \"macos\")))".dependencies.openssl-probe]
+-version = "0.1"
+-optional = true
+-
+-[target."cfg(all(unix, not(target_os = \"macos\")))".dependencies.openssl-sys]
+-version = "0.9.0"
+-optional = true
diff --git a/tests/scripts/archlinux_test.sh b/tests/scripts/archlinux_test.sh
new file mode 100755
index 0000000..e2a735b
--- /dev/null
+++ b/tests/scripts/archlinux_test.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# 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.
+
+set -euo pipefail
+
+images=(
+"archlinux:base-devel"
+)
+
+git_root=$(git rev-parse --show-toplevel)
+readonly git_root
+
+for image in "${images[@]}"; do
+  docker pull "${image}"
+  docker run --rm --entrypoint=/bin/bash --volume="${git_root}:/src:ro" "${image}" -c """
+set -exuo pipefail
+
+# Install dependencies
+pacman -Syu --noconfirm --quiet python
+
+# Run tests
+cd /src
+tests/scripts/run_tests.sh
+"""
+done
diff --git a/tests/scripts/bazel.sh b/tests/scripts/bazel.sh
new file mode 100644
index 0000000..87d7cf1
--- /dev/null
+++ b/tests/scripts/bazel.sh
@@ -0,0 +1,30 @@
+os="$(uname -s | tr "[:upper:]" "[:lower:]")"
+readonly os
+
+arch="$(uname -m)"
+if [[ "${arch}" == "x86_64" ]]; then
+  arch="amd64"
+elif [[ "${arch}" == "aarch64" ]]; then
+  arch="arm64"
+else
+  >&2 echo "Unknown architecture: ${arch}"
+fi
+readonly arch
+
+# Use bazelisk to catch migration problems.
+readonly bazelisk_version="v1.10.1"
+readonly url="https://github.com/bazelbuild/bazelisk/releases/download/${bazelisk_version}/bazelisk-${os}-${arch}"
+bazel="${TMPDIR:-/tmp}/bazelisk"
+readonly bazel
+
+readonly common_test_args=(
+  --incompatible_enable_cc_toolchain_resolution
+  --symlink_prefix=/
+  --color=yes
+  --show_progress_rate_limit=30
+  --keep_going
+  --test_output=errors
+)
+
+curl -L -sSf -o "${bazel}" "${url}"
+chmod a+x "${bazel}"
diff --git a/tests/scripts/centos_test.sh b/tests/scripts/centos_test.sh
new file mode 100755
index 0000000..1df0167
--- /dev/null
+++ b/tests/scripts/centos_test.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# 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.
+
+echo "This test is disabled because our supported versions of LLVM do not work with CentOS."
+exit 1
+
+set -euo pipefail
+
+images=(
+"centos:7"
+)
+
+git_root=$(git rev-parse --show-toplevel)
+readonly git_root
+
+for image in "${images[@]}"; do
+  docker pull "${image}"
+  docker run --rm --entrypoint=/bin/bash --volume="${git_root}:/src:ro" "${image}" -c """
+set -exuo pipefail
+
+# Install dependencies
+yum install -y -q gcc
+
+# Run tests
+cd /src
+tests/scripts/run_tests.sh
+"""
+done
diff --git a/tests/scripts/debian_test.sh b/tests/scripts/debian_test.sh
new file mode 100755
index 0000000..9f280c9
--- /dev/null
+++ b/tests/scripts/debian_test.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# 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.
+
+set -euo pipefail
+
+images=(
+"debian:latest"
+)
+
+git_root=$(git rev-parse --show-toplevel)
+readonly git_root
+
+for image in "${images[@]}"; do
+  docker pull "${image}"
+  docker run --rm --entrypoint=/bin/bash --volume="${git_root}:/src:ro" "${image}" -c """
+set -exuo pipefail
+
+# Common setup
+export DEBIAN_FRONTEND=noninteractive
+apt-get -qq update
+apt-get -qq -y install apt-utils curl pkg-config zip g++ zlib1g-dev unzip python gnupg2 libtinfo5 >/dev/null
+# The above command gives some verbose output that can not be silenced easily.
+# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=288778
+
+# Run tests
+cd /src
+tests/scripts/run_tests.sh
+"""
+done
diff --git a/tests/scripts/fedora_test.sh b/tests/scripts/fedora_test.sh
new file mode 100755
index 0000000..39897cc
--- /dev/null
+++ b/tests/scripts/fedora_test.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# 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.
+
+set -euo pipefail
+
+images=(
+"fedora:latest"
+)
+
+git_root=$(git rev-parse --show-toplevel)
+readonly git_root
+
+for image in "${images[@]}"; do
+  docker pull "${image}"
+  docker run --rm --entrypoint=/bin/bash --volume="${git_root}:/src:ro" "${image}" -c """
+set -exuo pipefail
+
+# Install dependencies
+dnf install -qy dnf-plugins-core
+dnf install -qy python gcc ncurses-compat-libs
+
+# Run tests
+cd /src
+tests/scripts/run_tests.sh
+"""
+done
diff --git a/tests/scripts/linux_sysroot_test.sh b/tests/scripts/linux_sysroot_test.sh
new file mode 100755
index 0000000..2b030cb
--- /dev/null
+++ b/tests/scripts/linux_sysroot_test.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# 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.
+
+set -euo pipefail
+
+images=(
+"ubuntu:20.04"
+)
+
+git_root=$(git rev-parse --show-toplevel)
+readonly git_root
+
+for image in "${images[@]}"; do
+  docker pull "${image}"
+  docker run --rm --entrypoint=/bin/bash --volume="${git_root}:/src:ro" "${image}" -c """
+set -exuo pipefail
+
+# Common setup
+export DEBIAN_FRONTEND=noninteractive
+apt-get -qq update
+apt-get -qq -y install apt-utils curl pkg-config zip g++ zlib1g-dev unzip python >/dev/null
+# The above command gives some verbose output that can not be silenced easily.
+# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=288778
+
+# Run tests
+cd /src
+tests/scripts/run_tests.sh -t '@llvm_toolchain_with_sysroot//:cc-toolchain-x86_64-linux'
+"""
+done
diff --git a/tests/scripts/run_external_tests.sh b/tests/scripts/run_external_tests.sh
new file mode 100755
index 0000000..e36ff78
--- /dev/null
+++ b/tests/scripts/run_external_tests.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# 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.
+
+set -euo pipefail
+
+source "$(dirname "${BASH_SOURCE[0]}")/bazel.sh"
+"${bazel}" version
+
+# Generate some files needed for the tests.
+"${bazel}" fetch @io_bazel_rules_go//tests/core/cgo:all
+"$("${bazel}" info output_base)/external/io_bazel_rules_go/tests/core/cgo/generate_imported_dylib.sh"
+
+# We exclude the following targets:
+# - cc_libs_test from rules_go because it assumes that stdlibc++ has been dynamically linked, but we
+#   link it statically on linux.
+# - opts_test from rules_go because its include path assumes that the main repo is rules_go (see
+#   https://github.com/bazelbuild/rules_go/issues/2955).
+"${bazel}" --bazelrc=/dev/null test "${common_test_args[@]}" \
+  //tests/foreign:pcre \
+  @git2//:all \
+  @openssl//:libssl \
+  $("${bazel}" query 'attr(timeout, short, tests(@com_google_absl//absl/...))') \
+  $("${bazel}" query 'tests(@io_bazel_rules_go//tests/core/cgo:all) except set(@io_bazel_rules_go//tests/core/cgo:cc_libs_test @io_bazel_rules_go//tests/core/cgo:opts_test)')
diff --git a/tests/scripts/run_tests.sh b/tests/scripts/run_tests.sh
new file mode 100755
index 0000000..b411a08
--- /dev/null
+++ b/tests/scripts/run_tests.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# 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.
+
+set -euo pipefail
+
+toolchain_name=""
+
+while getopts "t:h" opt; do
+  case "$opt" in
+    "t") toolchain_name="$OPTARG";;
+    "h") echo "Usage:"
+       echo "-t - Toolchain name to use for testing; default is llvm_toolchain"
+       exit 2
+       ;;
+    "?") echo "invalid option: -$OPTARG"; exit 1;;
+  esac
+done
+
+source "$(dirname "${BASH_SOURCE[0]}")/bazel.sh"
+"${bazel}" version
+
+set -x
+test_args=(
+  --extra_toolchains="${toolchain_name}"
+  --copt=-v
+  --linkopt=-Wl,-t
+)
+if [[ "${TEST_MIGRATION:-}" ]]; then
+  # We can not use bazelisk to test migration because bazelisk does not allow
+  # us to selectively ignore a migration flag.
+  test_args+=("--all_incompatible_changes")
+  # This flag is not quite ready -- https://github.com/bazelbuild/bazel/issues/7347
+  test_args+=("--incompatible_disallow_struct_provider_syntax=false")
+  # the rules_rust repo included in the WORKSPACE is currently incompatible with
+  # '--incompatible_no_rule_outputs_param=true', setting this to false for now.
+  test_args+=("--incompatible_no_rule_outputs_param=false")
+fi
+"${bazel}"  --bazelrc=/dev/null test "${common_test_args[@]}" "${test_args[@]}" //tests:all
diff --git a/tests/scripts/run_xcompile_tests.sh b/tests/scripts/run_xcompile_tests.sh
new file mode 100755
index 0000000..b0a7cfb
--- /dev/null
+++ b/tests/scripts/run_xcompile_tests.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# 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.
+
+set -euo pipefail
+
+source "$(dirname "${BASH_SOURCE[0]}")/bazel.sh"
+"${bazel}" version
+
+binpath="$("${bazel}" info bazel-bin)/tests/stdlib_test"
+
+check_with_image() {
+  if "${CI:-false}"; then
+    # macOS GitHub Action Runners do not have docker installed on them.
+    return
+  fi
+  local image="$1"
+  docker run --rm --mount "type=bind,source=${binpath},target=/stdlib_test" "${image}" /stdlib_test
+}
+
+echo ""
+echo "Testing static linked user libraries and dynamic linked system libraries"
+build_args=(
+  --incompatible_enable_cc_toolchain_resolution
+  --platforms=//platforms:linux-x86_64
+  --extra_toolchains=@llvm_toolchain_with_sysroot//:cc-toolchain-x86_64-linux
+  --symlink_prefix=/
+  --color=yes
+  --show_progress_rate_limit=30
+)
+"${bazel}" --bazelrc=/dev/null build "${build_args[@]}" //tests:stdlib_test
+file "${binpath}" | tee /dev/stderr | grep -q ELF
+check_with_image "frolvlad/alpine-glibc" # Need glibc image for system libraries.
+
+echo ""
+echo "Testing static linked user and system libraries"
+build_args+=(
+  --features=fully_static_link
+)
+"${bazel}" --bazelrc=/dev/null build "${build_args[@]}" //tests:stdlib_test
+file "${binpath}" | tee /dev/stderr | grep -q ELF
+check_with_image "alpine"
diff --git a/tests/scripts/suse_leap_test.sh b/tests/scripts/suse_leap_test.sh
new file mode 100755
index 0000000..d4f54a7
--- /dev/null
+++ b/tests/scripts/suse_leap_test.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# 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.
+
+set -euox pipefail
+
+images=(
+"opensuse/leap:latest"
+)
+
+git_root=$(git rev-parse --show-toplevel)
+readonly git_root
+
+echo "git root: $git_root"
+
+for image in "${images[@]}"; do
+  docker pull "${image}"
+  docker run --rm --entrypoint=/bin/bash --volume="${git_root}:/src" "${image}" -c """
+set -exuo pipefail
+
+# Common setup
+zypper -n update
+zypper -n install curl python tar gzip gcc libncurses5 binutils-gold
+
+# Run tests
+cd /src
+tests/scripts/run_tests.sh
+"""
+done
diff --git a/tests/scripts/suse_tumbleweed_test.sh b/tests/scripts/suse_tumbleweed_test.sh
new file mode 100755
index 0000000..785a83c
--- /dev/null
+++ b/tests/scripts/suse_tumbleweed_test.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# 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.
+
+set -euox pipefail
+
+images=(
+"opensuse/tumbleweed:latest"
+)
+
+git_root=$(git rev-parse --show-toplevel)
+readonly git_root
+
+echo "git root: $git_root"
+
+for image in "${images[@]}"; do
+  docker pull "${image}"
+  docker run --rm --entrypoint=/bin/bash --volume="${git_root}:/src" "${image}" -c """
+set -exuo pipefail
+
+# Common setup
+zypper -n update
+zypper -n install pkgconf-pkg-config curl python tar gzip findutils gcc libncurses5 binutils-gold
+
+# Run tests
+cd /src
+tests/scripts/run_tests.sh
+"""
+done
diff --git a/tests/scripts/ubuntu_16_04_test.sh b/tests/scripts/ubuntu_16_04_test.sh
new file mode 100755
index 0000000..419900c
--- /dev/null
+++ b/tests/scripts/ubuntu_16_04_test.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# 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.
+
+set -euo pipefail
+
+images=(
+"ubuntu:16.04"
+)
+
+git_root=$(git rev-parse --show-toplevel)
+readonly git_root
+
+for image in "${images[@]}"; do
+  docker pull "${image}"
+  docker run --rm --entrypoint=/bin/bash --volume="${git_root}:/src:ro" "${image}" -c """
+set -exuo pipefail
+
+# Common setup
+export DEBIAN_FRONTEND=noninteractive
+apt-get -qq update
+apt-get -qq -y install apt-utils curl pkg-config zip g++ zlib1g-dev unzip python >/dev/null
+# The above command gives some verbose output that can not be silenced easily.
+# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=288778
+
+# Run tests
+cd /src
+tests/scripts/run_tests.sh
+"""
+done
diff --git a/tests/scripts/ubuntu_18_04_test.sh b/tests/scripts/ubuntu_18_04_test.sh
new file mode 100755
index 0000000..12da28e
--- /dev/null
+++ b/tests/scripts/ubuntu_18_04_test.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# 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.
+
+set -euo pipefail
+
+images=(
+"ubuntu:18.04"
+)
+
+git_root=$(git rev-parse --show-toplevel)
+readonly git_root
+
+for image in "${images[@]}"; do
+  docker pull "${image}"
+  docker run --rm --entrypoint=/bin/bash --volume="${git_root}:/src:ro" "${image}" -c """
+set -exuo pipefail
+
+# Common setup
+export DEBIAN_FRONTEND=noninteractive
+apt-get -qq update
+apt-get -qq -y install apt-utils curl pkg-config zip g++ zlib1g-dev unzip python >/dev/null
+# The above command gives some verbose output that can not be silenced easily.
+# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=288778
+
+# Run tests
+cd /src
+tests/scripts/run_tests.sh
+"""
+done
diff --git a/tests/scripts/ubuntu_20_04_test.sh b/tests/scripts/ubuntu_20_04_test.sh
new file mode 100755
index 0000000..059f01c
--- /dev/null
+++ b/tests/scripts/ubuntu_20_04_test.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# 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.
+
+set -euo pipefail
+
+images=(
+"ubuntu:20.04"
+)
+
+git_root=$(git rev-parse --show-toplevel)
+readonly git_root
+
+for image in "${images[@]}"; do
+  docker pull "${image}"
+  docker run --rm --entrypoint=/bin/bash --volume="${git_root}:/src:ro" "${image}" -c """
+set -exuo pipefail
+
+# Common setup
+export DEBIAN_FRONTEND=noninteractive
+apt-get -qq update
+apt-get -qq -y install apt-utils curl pkg-config zip g++ zlib1g-dev unzip python >/dev/null
+# The above command gives some verbose output that can not be silenced easily.
+# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=288778
+
+# Run tests
+cd /src
+tests/scripts/run_tests.sh
+"""
+done
diff --git a/tests/stdlib.cc b/tests/stdlib.cc
new file mode 100644
index 0000000..60e7b0d
--- /dev/null
+++ b/tests/stdlib.cc
@@ -0,0 +1,17 @@
+// 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.
+
+#include <iostream>
+
+void hello() { std::cout << "Hello World!" << std::endl; }
\ No newline at end of file
diff --git a/tests/stdlib.h b/tests/stdlib.h
new file mode 100644
index 0000000..4ce4c60
--- /dev/null
+++ b/tests/stdlib.h
@@ -0,0 +1,17 @@
+// 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.
+
+void hello();
+
+void test_pthread_symbols();
diff --git a/tests/stdlib_test.cc b/tests/stdlib_test.cc
new file mode 100644
index 0000000..5f2904a
--- /dev/null
+++ b/tests/stdlib_test.cc
@@ -0,0 +1,17 @@
+// 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.
+
+#include "stdlib.h"
+
+int main() { hello(); }
diff --git a/tests/transitions.bzl b/tests/transitions.bzl
new file mode 100644
index 0000000..1279d92
--- /dev/null
+++ b/tests/transitions.bzl
@@ -0,0 +1,85 @@
+"""Helper transitions for tests."""
+
+# This transition function sets `--features=per_object_debug_info` and
+# `--fission` as well as the compilation mode.
+#
+# These three Bazel flags influence whether or not `.dwo` and `.dwp` are
+# created.
+def _fission_transition_impl(settings, attr):
+    features = settings["//command_line_option:features"]
+    if "per_object_debug_info" in features:
+        features.remove("per_object_debug_info")
+
+    enable_per_object_debug_info = attr.per_object_debug_info
+    if enable_per_object_debug_info:
+        features.append("per_object_debug_info")
+
+    compilation_mode = settings["//command_line_option:compilation_mode"]
+    if attr.override_compilation_mode:
+        compilation_mode = attr.override_compilation_mode
+
+    return {
+        "//command_line_option:compilation_mode": compilation_mode,
+        "//command_line_option:fission": attr.fission,
+        "//command_line_option:features": features,
+    }
+
+fission_transition = transition(
+    implementation = _fission_transition_impl,
+    inputs = [
+        "//command_line_option:compilation_mode",
+        "//command_line_option:features",
+    ],
+    outputs = [
+        "//command_line_option:compilation_mode",
+        "//command_line_option:features",
+        "//command_line_option:fission",
+    ],
+)
+
+def _dwp_file_impl(ctx):
+    file = ctx.attr.name
+    file = ctx.actions.declare_file(file)
+    ctx.actions.symlink(
+        output = file,
+        target_file = ctx.attr.src[0][DebugPackageInfo].dwp_file,
+    )
+
+    return [DefaultInfo(files = depset([file]))]
+
+dwp_file = rule(
+    implementation = _dwp_file_impl,
+    attrs = {
+        "src": attr.label(
+            cfg = fission_transition,
+            mandatory = True,
+            doc = "The actual target to build and grab the .dwp file from.",
+            providers = [DebugPackageInfo],
+        ),
+        # NOTE: we should eventually be able to remove this (see #109).
+        "per_object_debug_info": attr.bool(
+            default = True,
+        ),
+        "fission": attr.string(
+            default = "yes",
+            values = ["yes", "no", "dbg", "fastbuild", "opt"],
+        ),
+        # NOTE: this should eventually not be necessary; see #109 for context
+        # and also:
+        #   - https://reviews.llvm.org/D80391
+        #   - https://github.com/bazelbuild/bazel/issues/14038
+        #   - https://github.com/bazelbuild/rules_cc/pull/115
+        #
+        # Essentially, we now need to specify `-g2` explicitly to generate
+        # `.dwo` files.
+        "override_compilation_mode": attr.string(
+            default = "",
+            mandatory = False,
+            values = ["dbg", "fastbuild", "opt"],
+        ),
+        "_allowlist_function_transition": attr.label(
+            default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
+        ),
+    },
+    incompatible_use_toolchain_transition = True,
+)
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()
diff --git a/utils/llvm_checksums.sh b/utils/llvm_checksums.sh
new file mode 100755
index 0000000..79c5383
--- /dev/null
+++ b/utils/llvm_checksums.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+set -euo pipefail
+
+use_github_host=0
+
+while getopts "v:gh" opt; do
+  case "$opt" in
+    "v") llvm_version="$OPTARG";;
+    "g") use_github_host=1;;
+    "h") echo "Usage:"
+       echo "-v - Version of clang+llvm to use"
+       echo "-g - Use github to download releases"
+       exit 2
+       ;;
+    "?") echo "invalid option: -$OPTARG"; exit 1;;
+  esac
+done
+
+if ! [[ "${llvm_version:-}" ]]; then
+  echo "Usage: ${BASH_SOURCE[0]} -v llvm_version"
+  exit 1
+fi
+
+tmp_dir="$(mktemp -d)"
+
+cleanup() {
+  rc=$?
+  rm -rf "${tmp_dir}"
+  exit $rc
+}
+trap 'cleanup' INT HUP QUIT TERM EXIT
+
+llvm_host() {
+  local url_base="releases.llvm.org/${llvm_version}"
+  output_dir="${tmp_dir}/${url_base}"
+  wget --compression gzip --recursive --level 1 --directory-prefix="${tmp_dir}" \
+    --accept-regex "clang%2bllvm.*tar.xz$" "http://${url_base}/"
+}
+
+github_host() {
+  output_dir="${tmp_dir}"
+  (
+  cd "${output_dir}"
+  curl -s "https://api.github.com/repos/llvm/llvm-project/releases/tags/llvmorg-${llvm_version}" | \
+    jq .assets[].browser_download_url | \
+    tee ./urls.txt | \
+    grep 'clang%2Bllvm.*tar.xz"$' | \
+    tee ./filtered_urls.txt | \
+    xargs -n1 curl -L -O
+  )
+}
+
+if (( use_github_host )); then
+  github_host
+else
+  llvm_host
+fi
+
+echo ""
+echo "===="
+echo "Checksums for clang+llvm distributions are:"
+find "${output_dir}" -type f -name '*.xz' -exec shasum -a 256 {} \; | \
+  sed -e "s@${output_dir}/@@" | \
+  awk '{ printf "\"%s\": \"%s\",\n", $2, $1 }'