C++: Move tools/cpp from bazel_tools to rules_cc

Here we are duplicating bazel_tools/tools/cpp. The goal is for the BUILD files in bazel_tools/tools/cpp to have an alias that point to rules_cc. Then later on with the incompatible flag these aliases will no longer be valid.

Working towards #8743

RELNOTES:none
PiperOrigin-RevId: 264604076
Change-Id: I389702793a1a95b0990dce93577de2b7182e2e6b
diff --git a/WORKSPACE b/WORKSPACE
index d37b398..8d3caad 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -24,3 +24,15 @@
 
 load("//:internal_setup.bzl", "rules_cc_internal_setup")
 rules_cc_internal_setup()
+
+# We're pinning to a commit because this project does not have a recent release.
+# Nothing special about this commit, though.
+http_archive(
+    name = "com_google_googletest",
+    sha256 = "0fb00ff413f6b9b80ccee44a374ca7a18af7315aea72a43c62f2acd1ca74e9b5",
+    strip_prefix = "googletest-f13bbe2992d188e834339abe6f715b2b2f840a77",
+    urls = [
+        "https://mirror.bazel.build/github.com/google/googletest/archive/f13bbe2992d188e834339abe6f715b2b2f840a77.tar.gz",
+        "https://github.com/google/googletest/archive/f13bbe2992d188e834339abe6f715b2b2f840a77.tar.gz",
+    ],
+)
diff --git a/cc/BUILD b/cc/BUILD
index 145d2f9..47af570 100644
--- a/cc/BUILD
+++ b/cc/BUILD
@@ -1,8 +1,46 @@
+# Copyright 2018 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.
+
+package(default_visibility = ["//visibility:public"])
+
 licenses(["notice"])  # Apache 2.0
 
+filegroup(
+    name = "all_files_for_testing",
+    srcs = glob(["**"]) + [
+        "//cc/private/rules_impl:srcs",
+        "//cc/private/toolchain:srcs",
+    ],
+)
+
+exports_files([
+    "defs.bzl",
+    "action_names.bzl",
+])
+
+# The toolchain type used to distinguish cc toolchains.
 alias(
     name = "toolchain_type",
     actual = "@bazel_tools//tools/cpp:toolchain_type",
 )
 
-exports_files(["defs.bzl"])
+filegroup(
+    name = "action_names_test_files",
+    testonly = True,
+    srcs = [
+        "BUILD",
+        "action_names.bzl",
+    ],
+    visibility = ["//visibility:public"],
+)
diff --git a/cc/action_names.bzl b/cc/action_names.bzl
new file mode 100644
index 0000000..60e8a5f
--- /dev/null
+++ b/cc/action_names.bzl
@@ -0,0 +1,122 @@
+# Copyright 2018 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.
+"""Constants for action names used for C++ rules."""
+
+# Name for the C compilation action.
+C_COMPILE_ACTION_NAME = "c-compile"
+
+# Name of the C++ compilation action.
+CPP_COMPILE_ACTION_NAME = "c++-compile"
+
+# Name of the linkstamp-compile action.
+LINKSTAMP_COMPILE_ACTION_NAME = "linkstamp-compile"
+
+# Name of the action used to compute CC_FLAGS make variable.
+CC_FLAGS_MAKE_VARIABLE_ACTION_NAME = "cc-flags-make-variable"
+
+# Name of the C++ module codegen action.
+CPP_MODULE_CODEGEN_ACTION_NAME = "c++-module-codegen"
+
+# Name of the C++ header parsing action.
+CPP_HEADER_PARSING_ACTION_NAME = "c++-header-parsing"
+
+# Name of the C++ module compile action.
+CPP_MODULE_COMPILE_ACTION_NAME = "c++-module-compile"
+
+# Name of the assembler action.
+ASSEMBLE_ACTION_NAME = "assemble"
+
+# Name of the assembly preprocessing action.
+PREPROCESS_ASSEMBLE_ACTION_NAME = "preprocess-assemble"
+
+# Name of the action producing ThinLto index.
+LTO_INDEXING_ACTION_NAME = "lto-indexing"
+
+# Name of the action producing ThinLto index for executable.
+LTO_INDEX_FOR_EXECUTABLE_ACTION_NAME = "lto-index-for-executable"
+
+# Name of the action producing ThinLto index for dynamic library.
+LTO_INDEX_FOR_DYNAMIC_LIBRARY_ACTION_NAME = "lto-index-for-dynamic-library"
+
+# Name of the action producing ThinLto index for nodeps dynamic library.
+LTO_INDEX_FOR_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME = "lto-index-for-nodeps-dynamic-library"
+
+# Name of the action compiling lto bitcodes into native objects.
+LTO_BACKEND_ACTION_NAME = "lto-backend"
+
+# Name of the link action producing executable binary.
+CPP_LINK_EXECUTABLE_ACTION_NAME = "c++-link-executable"
+
+# Name of the link action producing dynamic library.
+CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME = "c++-link-dynamic-library"
+
+# Name of the link action producing dynamic library that doesn't include it's
+# transitive dependencies.
+CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME = "c++-link-nodeps-dynamic-library"
+
+# Name of the archiving action producing static library.
+CPP_LINK_STATIC_LIBRARY_ACTION_NAME = "c++-link-static-library"
+
+# Name of the action stripping the binary.
+STRIP_ACTION_NAME = "strip"
+
+# A string constant for the objc archive action.
+OBJC_ARCHIVE_ACTION_NAME = "objc-archive"
+
+# A string constant for the objc compilation action.
+OBJC_COMPILE_ACTION_NAME = "objc-compile"
+
+# A string constant for the objc++ compile action.
+OBJCPP_COMPILE_ACTION_NAME = "objc++-compile"
+
+# A string constant for the objc executable link action.
+OBJC_EXECUTABLE_ACTION_NAME = "objc-executable"
+
+# A string constant for the objc++ executable link action.
+OBJCPP_EXECUTABLE_ACTION_NAME = "objc++-executable"
+
+# A string constant for the objc fully-link link action.
+OBJC_FULLY_LINK_ACTION_NAME = "objc-fully-link"
+
+# A string constant for the clif actions.
+CLIF_MATCH_ACTION_NAME = "clif-match"
+
+ACTION_NAMES = struct(
+    c_compile = C_COMPILE_ACTION_NAME,
+    cpp_compile = CPP_COMPILE_ACTION_NAME,
+    linkstamp_compile = LINKSTAMP_COMPILE_ACTION_NAME,
+    cc_flags_make_variable = CC_FLAGS_MAKE_VARIABLE_ACTION_NAME,
+    cpp_module_codegen = CPP_MODULE_CODEGEN_ACTION_NAME,
+    cpp_header_parsing = CPP_HEADER_PARSING_ACTION_NAME,
+    cpp_module_compile = CPP_MODULE_COMPILE_ACTION_NAME,
+    assemble = ASSEMBLE_ACTION_NAME,
+    preprocess_assemble = PREPROCESS_ASSEMBLE_ACTION_NAME,
+    lto_indexing = LTO_INDEXING_ACTION_NAME,
+    lto_backend = LTO_BACKEND_ACTION_NAME,
+    lto_index_for_executable = LTO_INDEX_FOR_EXECUTABLE_ACTION_NAME,
+    lto_index_for_dynamic_library = LTO_INDEX_FOR_DYNAMIC_LIBRARY_ACTION_NAME,
+    lto_index_for_nodeps_dynamic_library = LTO_INDEX_FOR_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME,
+    cpp_link_executable = CPP_LINK_EXECUTABLE_ACTION_NAME,
+    cpp_link_dynamic_library = CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME,
+    cpp_link_nodeps_dynamic_library = CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME,
+    cpp_link_static_library = CPP_LINK_STATIC_LIBRARY_ACTION_NAME,
+    strip = STRIP_ACTION_NAME,
+    objc_archive = OBJC_ARCHIVE_ACTION_NAME,
+    objc_compile = OBJC_COMPILE_ACTION_NAME,
+    objc_executable = OBJC_EXECUTABLE_ACTION_NAME,
+    objc_fully_link = OBJC_FULLY_LINK_ACTION_NAME,
+    objcpp_compile = OBJCPP_COMPILE_ACTION_NAME,
+    objcpp_executable = OBJCPP_EXECUTABLE_ACTION_NAME,
+    clif_match = CLIF_MATCH_ACTION_NAME,
+)
diff --git a/cc/defs.bzl b/cc/defs.bzl
index 5060efe..8de01bd 100644
--- a/cc/defs.bzl
+++ b/cc/defs.bzl
@@ -14,8 +14,8 @@
 
 """Starlark rules for building C++ projects."""
 
-load("@bazel_tools//tools/cpp:cc_flags_supplier.bzl", _cc_flags_supplier = "cc_flags_supplier")
-load("@bazel_tools//tools/cpp:compiler_flag.bzl", _compiler_flag = "compiler_flag")
+load("@rules_cc//cc/private/rules_impl:cc_flags_supplier.bzl", _cc_flags_supplier = "cc_flags_supplier")
+load("@rules_cc//cc/private/rules_impl:compiler_flag.bzl", _compiler_flag = "compiler_flag")
 
 _MIGRATION_TAG = "__CC_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__"
 
diff --git a/cc/find_cc_toolchain.bzl b/cc/find_cc_toolchain.bzl
index 8964772..5784fa7 100644
--- a/cc/find_cc_toolchain.bzl
+++ b/cc/find_cc_toolchain.bzl
@@ -24,7 +24,7 @@
 foo = rule(
     implementation = _foo_impl,
     attrs = {
-        "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
+        "_cc_toolchain": attr.label(default = Label("@rules_cc//cc/private/toolchain:current_cc_toolchain")),
     },
 )
 * When https://github.com/bazelbuild/bazel/issues/7260 **is** flipped, current
diff --git a/cc/private/rules_impl/BUILD b/cc/private/rules_impl/BUILD
new file mode 100644
index 0000000..54eef46
--- /dev/null
+++ b/cc/private/rules_impl/BUILD
@@ -0,0 +1,14 @@
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])  # Apache 2.0
+
+filegroup(
+    name = "srcs",
+    srcs = glob(
+        ["**"],
+        exclude = [
+            ".*",
+            "*~",
+        ],
+    ),
+)
diff --git a/cc/private/rules_impl/cc_flags_supplier.bzl b/cc/private/rules_impl/cc_flags_supplier.bzl
new file mode 100644
index 0000000..3711369
--- /dev/null
+++ b/cc/private/rules_impl/cc_flags_supplier.bzl
@@ -0,0 +1,35 @@
+# Copyright 2018 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.
+"""Rule that provides the CC_FLAGS Make variable."""
+
+load("//cc:action_names.bzl", "CC_FLAGS_MAKE_VARIABLE_ACTION_NAME")
+load("//cc/private/rules_impl:cc_flags_supplier_lib.bzl", "build_cc_flags")
+load("//cc:toolchain_utils.bzl", "find_cpp_toolchain")
+
+def _cc_flags_supplier_impl(ctx):
+    cc_toolchain = find_cpp_toolchain(ctx)
+    cc_flags = build_cc_flags(ctx, cc_toolchain, CC_FLAGS_MAKE_VARIABLE_ACTION_NAME)
+    variables = platform_common.TemplateVariableInfo({
+        "CC_FLAGS": cc_flags,
+    })
+    return [variables]
+
+cc_flags_supplier = rule(
+    implementation = _cc_flags_supplier_impl,
+    attrs = {
+        "_cc_toolchain": attr.label(default = Label("@rules_cc//cc/private/toolchain:current_cc_toolchain")),
+    },
+    toolchains = ["@rules_cc//cc:toolchain_type"],
+    fragments = ["cpp"],
+)
diff --git a/cc/private/rules_impl/cc_flags_supplier_lib.bzl b/cc/private/rules_impl/cc_flags_supplier_lib.bzl
new file mode 100644
index 0000000..042ecef
--- /dev/null
+++ b/cc/private/rules_impl/cc_flags_supplier_lib.bzl
@@ -0,0 +1,71 @@
+# Copyright 2018 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.
+"""Library of functions that provide the CC_FLAGS Make variable."""
+
+# This should match the logic in CcCommon.computeCcFlags:
+def build_cc_flags(ctx, cc_toolchain, action_name):
+    """Determine the value for CC_FLAGS based on the given toolchain."""
+
+    # Get default cc flags from toolchain's make_variables.
+    legacy_cc_flags = cc_common.legacy_cc_flags_make_variable_do_not_use(
+        cc_toolchain = cc_toolchain,
+    )
+
+    # Determine the sysroot flag.
+    sysroot_cc_flags = _from_sysroot(cc_toolchain)
+
+    # Flags from feature config.
+    feature_config_cc_flags = _from_features(ctx, cc_toolchain, action_name)
+
+    # Combine the different sources, but only add the sysroot flag if nothing
+    # else adds sysroot.
+    # If added, it must appear before the feature config flags.
+    cc_flags = []
+    if legacy_cc_flags:
+        cc_flags.append(legacy_cc_flags)
+    if sysroot_cc_flags and not _contains_sysroot(feature_config_cc_flags):
+        cc_flags.append(sysroot_cc_flags)
+    cc_flags.extend(feature_config_cc_flags)
+
+    return " ".join(cc_flags)
+
+def _contains_sysroot(flags):
+    for flag in flags:
+        if "--sysroot=" in flag:
+            return True
+    return False
+
+def _from_sysroot(cc_toolchain):
+    sysroot = cc_toolchain.sysroot
+    if sysroot:
+        return "--sysroot=%s" % sysroot
+    else:
+        return None
+
+def _from_features(ctx, cc_toolchain, action_name):
+    feature_configuration = cc_common.configure_features(
+        ctx = ctx,
+        cc_toolchain = cc_toolchain,
+        requested_features = ctx.features,
+        unsupported_features = ctx.disabled_features,
+    )
+
+    variables = cc_common.empty_variables()
+
+    cc_flags = cc_common.get_memory_inefficient_command_line(
+        feature_configuration = feature_configuration,
+        action_name = action_name,
+        variables = variables,
+    )
+    return cc_flags
diff --git a/cc/private/rules_impl/compiler_flag.bzl b/cc/private/rules_impl/compiler_flag.bzl
new file mode 100644
index 0000000..b399922
--- /dev/null
+++ b/cc/private/rules_impl/compiler_flag.bzl
@@ -0,0 +1,29 @@
+# Copyright 2018 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.
+
+"""Rule that allows select() to differentiate between compilers."""
+
+load("@rules_cc//cc:toolchain_utils.bzl", "find_cpp_toolchain")
+
+def _compiler_flag_impl(ctx):
+    toolchain = find_cpp_toolchain(ctx)
+    return [config_common.FeatureFlagInfo(value = toolchain.compiler)]
+
+compiler_flag = rule(
+    implementation = _compiler_flag_impl,
+    attrs = {
+        "_cc_toolchain": attr.label(default = Label("@rules_cc//cc/private/toolchain:current_cc_toolchain")),
+    },
+    toolchains = ["@rules_cc//cc:toolchain_type"],
+)
diff --git a/cc/private/toolchain/BUILD b/cc/private/toolchain/BUILD
new file mode 100644
index 0000000..9860828
--- /dev/null
+++ b/cc/private/toolchain/BUILD
@@ -0,0 +1,124 @@
+# Copyright 2018 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.
+#
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])  # Apache 2.0
+
+load("//cc:defs.bzl", "cc_flags_supplier", "cc_library", "compiler_flag")
+
+# It is frequently necessary to constrain platforms based on the cc compiler type.
+constraint_setting(name = "cc_compiler")
+
+constraint_value(
+    name = "clang",
+    constraint_setting = ":cc_compiler",
+)
+
+constraint_value(
+    name = "gcc",
+    constraint_setting = ":cc_compiler",
+)
+
+constraint_value(
+    name = "msvc",
+    constraint_setting = ":cc_compiler",
+)
+
+constraint_value(
+    name = "clang-cl",
+    constraint_setting = ":cc_compiler",
+)
+
+constraint_value(
+    name = "mingw",
+    constraint_setting = ":cc_compiler",
+)
+
+constraint_value(
+    name = "msys",
+    constraint_setting = ":cc_compiler",
+)
+
+cc_toolchain_alias(name = "current_cc_toolchain")
+
+cc_host_toolchain_alias(name = "current_cc_host_toolchain")
+
+cc_libc_top_alias(name = "current_libc_top")
+
+cc_library(
+    name = "malloc",
+)
+
+filegroup(
+    name = "grep-includes",
+    srcs = ["grep-includes.sh"],
+)
+
+filegroup(
+    name = "empty",
+    srcs = [],
+)
+
+# This is the entry point for --crosstool_top.  Toolchains are found
+# by lopping off the name of --crosstool_top and searching for
+# "cc-compiler-${CPU}" in this BUILD file, where CPU is the target CPU
+# specified in --cpu.
+#
+# This file group should include
+#   * all cc_toolchain targets supported
+#   * all file groups that said cc_toolchain might refer to
+alias(
+    name = "toolchain",
+    actual = "//external:cc_toolchain",
+)
+
+filegroup(
+    name = "srcs",
+    srcs = glob(["**"]) + [
+        "//cc/private/toolchain/runfiles:srcs",
+    ],
+)
+
+filegroup(
+    name = "embedded_tools",
+    srcs = glob(["**"]) + [
+        "//cc:action_names.bzl",
+        "//cc/private/toolchain/runfiles:embedded_tools",
+    ],
+)
+
+filegroup(
+    name = "interface_library_builder",
+    srcs = ["build_interface_so"],
+)
+
+filegroup(
+    name = "osx_wrapper",
+    srcs = ["osx_cc_wrapper.sh"],
+)
+
+filegroup(
+    name = "link_dynamic_library",
+    srcs = ["link_dynamic_library.sh"],
+)
+
+filegroup(
+    name = "lib_cc_configure",
+    srcs = ["lib_cc_configure.bzl"],
+)
+
+compiler_flag(name = "compiler")
+
+cc_flags_supplier(name = "cc_flags")
diff --git a/cc/private/toolchain/BUILD.empty b/cc/private/toolchain/BUILD.empty
new file mode 100644
index 0000000..fd95fc4
--- /dev/null
+++ b/cc/private/toolchain/BUILD.empty
@@ -0,0 +1,50 @@
+# Copyright 2018 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.
+
+package(default_visibility = ["//visibility:public"])
+
+load(":cc_toolchain_config.bzl", "cc_toolchain_config")
+
+cc_library(
+    name = "malloc",
+)
+
+filegroup(
+    name = "empty",
+    srcs = [],
+)
+
+cc_toolchain_suite(
+    name = "toolchain",
+    toolchains = {
+        "local|local": ":local",
+        "local": ":local",
+    },
+)
+
+cc_toolchain(
+    name = "local",
+    toolchain_identifier = "local",
+    toolchain_config = ":local_config",
+    all_files = ":empty",
+    ar_files = ":empty",
+    as_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+)
+
+cc_toolchain_config(name = "local_config")
diff --git a/cc/private/toolchain/BUILD.static.freebsd b/cc/private/toolchain/BUILD.static.freebsd
new file mode 100644
index 0000000..c1fa44e
--- /dev/null
+++ b/cc/private/toolchain/BUILD.static.freebsd
@@ -0,0 +1,112 @@
+# Copyright 2018 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.
+
+# This becomes the BUILD file for @local_config_cc// under FreeBSD.
+
+package(default_visibility = ["//visibility:public"])
+
+load(":cc_toolchain_config.bzl", "cc_toolchain_config")
+load("@rules_cc//cc:defs.bzl", "cc_toolchain_suite", "cc_toolchain", "cc_library")
+
+cc_library(
+    name = "malloc",
+)
+
+filegroup(
+    name = "empty",
+    srcs = [],
+)
+
+# Hardcoded toolchain, legacy behaviour.
+cc_toolchain_suite(
+    name = "toolchain",
+    toolchains = {
+        "armeabi-v7a|compiler": ":cc-compiler-armeabi-v7a",
+        "freebsd|compiler": ":cc-compiler-freebsd",
+        "armeabi-v7a": ":cc-compiler-armeabi-v7a",
+        "freebsd": ":cc-compiler-freebsd",
+    },
+)
+
+cc_toolchain(
+    name = "cc-compiler-freebsd",
+    toolchain_identifier = "local_freebsd",
+    toolchain_config = ":local_freebsd",
+    all_files = ":empty",
+    ar_files = ":empty",
+    as_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    supports_param_files = 0,
+)
+
+cc_toolchain_config(
+    name = "local_freebsd",
+    cpu = "freebsd",
+)
+
+toolchain(
+    name = "cc-toolchain-freebsd",
+    exec_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:freebsd",
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:freebsd",
+    ],
+    toolchain = ":cc-compiler-freebsd",
+    toolchain_type = "@rules_cc//cc:toolchain_type",
+)
+
+cc_toolchain(
+    name = "cc-compiler-armeabi-v7a",
+    toolchain_identifier = "stub_armeabi-v7a",
+    toolchain_config = ":stub_armeabi-v7a",
+    all_files = ":empty",
+    ar_files = ":empty",
+    as_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    supports_param_files = 0,
+)
+
+cc_toolchain_config(
+    name = "stub_armeabi-v7a",
+    cpu = "armeabi-v7a",
+)
+
+toolchain(
+    name = "cc-toolchain-armeabi-v7a",
+    exec_compatible_with = [
+        "@platforms//cpu:arm",
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:arm",
+        "@platforms//os:android",
+    ],
+    toolchain = ":cc-compiler-armeabi-v7a",
+    toolchain_type = "@rules_cc//cc:toolchain_type",
+)
+
+filegroup(
+    name = "link_dynamic_library",
+    srcs = ["link_dynamic_library.sh"],
+)
diff --git a/cc/private/toolchain/BUILD.toolchains.tpl b/cc/private/toolchain/BUILD.toolchains.tpl
new file mode 100644
index 0000000..05ea101
--- /dev/null
+++ b/cc/private/toolchain/BUILD.toolchains.tpl
@@ -0,0 +1,19 @@
+load("@local_config_platform//:constraints.bzl", "HOST_CONSTRAINTS")
+toolchain(
+    name = "cc-toolchain-%{name}",
+    exec_compatible_with = HOST_CONSTRAINTS,
+    target_compatible_with = HOST_CONSTRAINTS,
+    toolchain = "@local_config_cc//:cc-compiler-%{name}",
+    toolchain_type = "@rules_cc//cc:toolchain_type",
+)
+
+toolchain(
+    name = "cc-toolchain-armeabi-v7a",
+    exec_compatible_with = HOST_CONSTRAINTS,
+    target_compatible_with = [
+        "@platforms//cpu:arm",
+        "@platforms//os:android",
+    ],
+    toolchain = "@local_config_cc//:cc-compiler-armeabi-v7a",
+    toolchain_type = "@rules_cc//cc:toolchain_type",
+)
diff --git a/cc/private/toolchain/BUILD.tpl b/cc/private/toolchain/BUILD.tpl
new file mode 100644
index 0000000..d40f7f5
--- /dev/null
+++ b/cc/private/toolchain/BUILD.tpl
@@ -0,0 +1,113 @@
+# Copyright 2016 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.
+
+# This becomes the BUILD file for @local_config_cc// under non-FreeBSD unixes.
+
+package(default_visibility = ["//visibility:public"])
+
+load(":cc_toolchain_config.bzl", "cc_toolchain_config")
+load(":armeabi_cc_toolchain_config.bzl", "armeabi_cc_toolchain_config")
+load("@rules_cc//cc:defs.bzl", "cc_toolchain", "cc_toolchain_suite")
+
+licenses(["notice"])  # Apache 2.0
+
+cc_library(
+    name = "malloc",
+)
+
+filegroup(
+    name = "empty",
+    srcs = [],
+)
+
+filegroup(
+    name = "cc_wrapper",
+    srcs = ["cc_wrapper.sh"],
+)
+
+filegroup(
+    name = "compiler_deps",
+    srcs = glob(["extra_tools/**"], allow_empty = True) + ["%{cc_compiler_deps}"],
+)
+
+# This is the entry point for --crosstool_top.  Toolchains are found
+# by lopping off the name of --crosstool_top and searching for
+# the "${CPU}" entry in the toolchains attribute.
+cc_toolchain_suite(
+    name = "toolchain",
+    toolchains = {
+        "%{name}|%{compiler}": ":cc-compiler-%{name}",
+        "%{name}": ":cc-compiler-%{name}",
+        "armeabi-v7a|compiler": ":cc-compiler-armeabi-v7a",
+        "armeabi-v7a": ":cc-compiler-armeabi-v7a",
+    },
+)
+
+cc_toolchain(
+    name = "cc-compiler-%{name}",
+    toolchain_identifier = "%{cc_toolchain_identifier}",
+    toolchain_config = ":%{cc_toolchain_identifier}",
+    all_files = ":compiler_deps",
+    ar_files = ":compiler_deps",
+    as_files = ":compiler_deps",
+    compiler_files = ":compiler_deps",
+    dwp_files = ":empty",
+    linker_files = ":compiler_deps",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    supports_param_files = %{supports_param_files},
+)
+
+cc_toolchain_config(
+    name = "%{cc_toolchain_identifier}",
+    cpu = "%{target_cpu}",
+    compiler = "%{compiler}",
+    toolchain_identifier = "%{cc_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}],
+    opt_compile_flags = [%{opt_compile_flags}],
+    dbg_compile_flags = [%{dbg_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},
+)
+
+# Android tooling requires a default toolchain for the armeabi-v7a cpu.
+cc_toolchain(
+    name = "cc-compiler-armeabi-v7a",
+    toolchain_identifier = "stub_armeabi-v7a",
+    toolchain_config = ":stub_armeabi-v7a",
+    all_files = ":empty",
+    ar_files = ":empty",
+    as_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    supports_param_files = 1,
+)
+
+armeabi_cc_toolchain_config(name = "stub_armeabi-v7a")
diff --git a/cc/private/toolchain/BUILD.windows.tpl b/cc/private/toolchain/BUILD.windows.tpl
new file mode 100644
index 0000000..7295700
--- /dev/null
+++ b/cc/private/toolchain/BUILD.windows.tpl
@@ -0,0 +1,301 @@
+# Copyright 2018 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.
+
+# This becomes the BUILD file for @local_config_cc// under Windows.
+
+package(default_visibility = ["//visibility:public"])
+
+load("@rules_cc//cc:defs.bzl", "cc_toolchain", "cc_toolchain_suite", "cc_library")
+load(":windows_cc_toolchain_config.bzl", "cc_toolchain_config")
+load(":armeabi_cc_toolchain_config.bzl", "armeabi_cc_toolchain_config")
+cc_library(
+    name = "malloc",
+)
+
+filegroup(
+    name = "empty",
+    srcs = [],
+)
+
+# Hardcoded toolchain, legacy behaviour.
+cc_toolchain_suite(
+    name = "toolchain",
+    toolchains = {
+        "armeabi-v7a|compiler": ":cc-compiler-armeabi-v7a",
+        "x64_windows|msvc-cl": ":cc-compiler-x64_windows",
+        "x64_windows|msys-gcc": ":cc-compiler-x64_windows_msys",
+        "x64_windows|mingw-gcc": ":cc-compiler-x64_windows_mingw",
+        "x64_windows|clang-cl": ":cc-compiler-x64_windows-clang-cl",
+        "x64_windows_msys": ":cc-compiler-x64_windows_msys",
+        "x64_windows": ":cc-compiler-x64_windows",
+        "armeabi-v7a": ":cc-compiler-armeabi-v7a",
+    },
+)
+
+cc_toolchain(
+    name = "cc-compiler-x64_windows_msys",
+    toolchain_identifier = "msys_x64",
+    toolchain_config = ":msys_x64",
+    all_files = ":empty",
+    ar_files = ":empty",
+    as_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    supports_param_files = 1,
+)
+
+cc_toolchain_config(
+    name = "msys_x64",
+    cpu = "x64_windows",
+    compiler = "msys-gcc",
+    host_system_name = "local",
+    target_system_name = "local",
+    target_libc = "msys",
+    abi_version = "local",
+    abi_libc_version = "local",
+    cxx_builtin_include_directories = [%{cxx_builtin_include_directories}],
+    tool_paths = {%{tool_paths}},
+    tool_bin_path = "%{tool_bin_path}",
+    dbg_mode_debug_flag = "%{dbg_mode_debug_flag}",
+    fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag}",
+)
+
+toolchain(
+    name = "cc-toolchain-x64_windows_msys",
+    exec_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:windows",
+        "@rules_cc//cc/private/toolchain:msys",
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:windows",
+    ],
+    toolchain = ":cc-compiler-x64_windows_msys",
+    toolchain_type = "@rules_cc//cc:toolchain_type",
+)
+
+cc_toolchain(
+    name = "cc-compiler-x64_windows_mingw",
+    toolchain_identifier = "msys_x64_mingw",
+    toolchain_config = ":msys_x64_mingw",
+    all_files = ":empty",
+    ar_files = ":empty",
+    as_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    supports_param_files = 0,
+)
+
+cc_toolchain_config(
+    name = "msys_x64_mingw",
+    cpu = "x64_windows",
+    compiler = "mingw-gcc",
+    host_system_name = "local",
+    target_system_name = "local",
+    target_libc = "mingw",
+    abi_version = "local",
+    abi_libc_version = "local",
+    tool_bin_path = "%{mingw_tool_bin_path}",
+    cxx_builtin_include_directories = [%{mingw_cxx_builtin_include_directories}],
+    tool_paths = {%{mingw_tool_paths}},
+    dbg_mode_debug_flag = "%{dbg_mode_debug_flag}",
+    fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag}",
+)
+
+toolchain(
+    name = "cc-toolchain-x64_windows_mingw",
+    exec_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:windows",
+        "@rules_cc//cc/private/toolchain:mingw",
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:windows",
+    ],
+    toolchain = ":cc-compiler-x64_windows_mingw",
+    toolchain_type = "@rules_cc//cc:toolchain_type",
+)
+
+cc_toolchain(
+    name = "cc-compiler-x64_windows",
+    toolchain_identifier = "msvc_x64",
+    toolchain_config = ":msvc_x64",
+    all_files = ":empty",
+    ar_files = ":empty",
+    as_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    supports_param_files = 1,
+)
+
+cc_toolchain_config(
+    name = "msvc_x64",
+    cpu = "x64_windows",
+    compiler = "msvc-cl",
+    host_system_name = "local",
+    target_system_name = "local",
+    target_libc = "msvcrt",
+    abi_version = "local",
+    abi_libc_version = "local",
+    toolchain_identifier = "msvc_x64",
+    msvc_env_tmp = "%{msvc_env_tmp}",
+    msvc_env_path = "%{msvc_env_path}",
+    msvc_env_include = "%{msvc_env_include}",
+    msvc_env_lib = "%{msvc_env_lib}",
+    msvc_cl_path = "%{msvc_cl_path}",
+    msvc_ml_path = "%{msvc_ml_path}",
+    msvc_link_path = "%{msvc_link_path}",
+    msvc_lib_path = "%{msvc_lib_path}",
+    cxx_builtin_include_directories = [%{msvc_cxx_builtin_include_directories}],
+    tool_paths = {
+        "ar": "%{msvc_lib_path}",
+        "ml": "%{msvc_ml_path}",
+        "cpp": "%{msvc_cl_path}",
+        "gcc": "%{msvc_cl_path}",
+        "gcov": "wrapper/bin/msvc_nop.bat",
+        "ld": "%{msvc_link_path}",
+        "nm": "wrapper/bin/msvc_nop.bat",
+        "objcopy": "wrapper/bin/msvc_nop.bat",
+        "objdump": "wrapper/bin/msvc_nop.bat",
+        "strip": "wrapper/bin/msvc_nop.bat",
+    },
+    default_link_flags = ["/MACHINE:X64"],
+    dbg_mode_debug_flag = "%{dbg_mode_debug_flag}",
+    fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag}",
+)
+
+toolchain(
+    name = "cc-toolchain-x64_windows",
+    exec_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:windows",
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:windows",
+    ],
+    toolchain = ":cc-compiler-x64_windows",
+    toolchain_type = "@rules_cc//cc:toolchain_type",
+)
+
+cc_toolchain(
+    name = "cc-compiler-x64_windows-clang-cl",
+    toolchain_identifier = "clang_cl_x64",
+    toolchain_config = ":clang_cl_x64",
+    all_files = ":empty",
+    ar_files = ":empty",
+    as_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    supports_param_files = 1,
+)
+
+cc_toolchain_config(
+    name = "clang_cl_x64",
+    cpu = "x64_windows",
+    compiler = "clang-cl",
+    host_system_name = "local",
+    target_system_name = "local",
+    target_libc = "msvcrt",
+    abi_version = "local",
+    abi_libc_version = "local",
+    toolchain_identifier = "clang_cl_x64",
+    msvc_env_tmp = "%{clang_cl_env_tmp}",
+    msvc_env_path = "%{clang_cl_env_path}",
+    msvc_env_include = "%{clang_cl_env_include}",
+    msvc_env_lib = "%{clang_cl_env_lib}",
+    msvc_cl_path = "%{clang_cl_cl_path}",
+    msvc_ml_path = "%{clang_cl_ml_path}",
+    msvc_link_path = "%{clang_cl_link_path}",
+    msvc_lib_path = "%{clang_cl_lib_path}",
+    cxx_builtin_include_directories = [%{clang_cl_cxx_builtin_include_directories}],
+    tool_paths = {
+        "ar": "%{clang_cl_lib_path}",
+        "ml": "%{clang_cl_ml_path}",
+        "cpp": "%{clang_cl_cl_path}",
+        "gcc": "%{clang_cl_cl_path}",
+        "gcov": "wrapper/bin/msvc_nop.bat",
+        "ld": "%{clang_cl_link_path}",
+        "nm": "wrapper/bin/msvc_nop.bat",
+        "objcopy": "wrapper/bin/msvc_nop.bat",
+        "objdump": "wrapper/bin/msvc_nop.bat",
+        "strip": "wrapper/bin/msvc_nop.bat",
+    },
+    default_link_flags = ["/MACHINE:X64", "/DEFAULTLIB:clang_rt.builtins-x86_64.lib"],
+    dbg_mode_debug_flag = "%{clang_cl_dbg_mode_debug_flag}",
+    fastbuild_mode_debug_flag = "%{clang_cl_fastbuild_mode_debug_flag}",
+)
+
+toolchain(
+    name = "cc-toolchain-x64_windows-clang-cl",
+    exec_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:windows",
+        "@rules_cc//cc/private/toolchain:clang-cl",
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:x86_64",
+        "@platforms//os:windows",
+    ],
+    toolchain = ":cc-compiler-x64_windows-clang-cl",
+    toolchain_type = "@rules_cc//cc:toolchain_type",
+)
+
+cc_toolchain(
+    name = "cc-compiler-armeabi-v7a",
+    toolchain_identifier = "stub_armeabi-v7a",
+    toolchain_config = ":stub_armeabi-v7a",
+    all_files = ":empty",
+    ar_files = ":empty",
+    as_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    supports_param_files = 1,
+)
+
+armeabi_cc_toolchain_config(name = "stub_armeabi-v7a")
+
+toolchain(
+    name = "cc-toolchain-armeabi-v7a",
+    exec_compatible_with = [
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:arm",
+        "@platforms//os:android",
+    ],
+    toolchain = ":cc-compiler-armeabi-v7a",
+    toolchain_type = "@rules_cc//cc:toolchain_type",
+)
+
+filegroup(
+    name = "link_dynamic_library",
+    srcs = ["link_dynamic_library.sh"],
+)
diff --git a/cc/private/toolchain/armeabi_cc_toolchain_config.bzl b/cc/private/toolchain/armeabi_cc_toolchain_config.bzl
new file mode 100644
index 0000000..3d2aa74
--- /dev/null
+++ b/cc/private/toolchain/armeabi_cc_toolchain_config.bzl
@@ -0,0 +1,82 @@
+# Copyright 2019 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.
+
+"""A Starlark cc_toolchain configuration rule"""
+
+load(
+    "@rules_cc//cc/private/toolchain:cc_toolchain_config_lib.bzl",
+    "feature",
+    "tool_path",
+)
+
+def _impl(ctx):
+    toolchain_identifier = "stub_armeabi-v7a"
+    host_system_name = "armeabi-v7a"
+    target_system_name = "armeabi-v7a"
+    target_cpu = "armeabi-v7a"
+    target_libc = "armeabi-v7a"
+    compiler = "compiler"
+    abi_version = "armeabi-v7a"
+    abi_libc_version = "armeabi-v7a"
+    cc_target_os = None
+    builtin_sysroot = None
+    action_configs = []
+
+    supports_pic_feature = feature(name = "supports_pic", enabled = True)
+    supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True)
+    features = [supports_dynamic_linker_feature, supports_pic_feature]
+
+    cxx_builtin_include_directories = []
+    artifact_name_patterns = []
+    make_variables = []
+
+    tool_paths = [
+        tool_path(name = "ar", path = "/bin/false"),
+        tool_path(name = "compat-ld", path = "/bin/false"),
+        tool_path(name = "cpp", path = "/bin/false"),
+        tool_path(name = "dwp", path = "/bin/false"),
+        tool_path(name = "gcc", path = "/bin/false"),
+        tool_path(name = "gcov", path = "/bin/false"),
+        tool_path(name = "ld", path = "/bin/false"),
+        tool_path(name = "nm", path = "/bin/false"),
+        tool_path(name = "objcopy", path = "/bin/false"),
+        tool_path(name = "objdump", path = "/bin/false"),
+        tool_path(name = "strip", path = "/bin/false"),
+    ]
+
+    return cc_common.create_cc_toolchain_config_info(
+        ctx = ctx,
+        features = features,
+        action_configs = action_configs,
+        artifact_name_patterns = artifact_name_patterns,
+        cxx_builtin_include_directories = cxx_builtin_include_directories,
+        toolchain_identifier = toolchain_identifier,
+        host_system_name = host_system_name,
+        target_system_name = target_system_name,
+        target_cpu = target_cpu,
+        target_libc = target_libc,
+        compiler = compiler,
+        abi_version = abi_version,
+        abi_libc_version = abi_libc_version,
+        tool_paths = tool_paths,
+        make_variables = make_variables,
+        builtin_sysroot = builtin_sysroot,
+        cc_target_os = cc_target_os,
+    )
+
+armeabi_cc_toolchain_config = rule(
+    implementation = _impl,
+    attrs = {},
+    provides = [CcToolchainConfigInfo],
+)
diff --git a/cc/private/toolchain/build_interface_so b/cc/private/toolchain/build_interface_so
new file mode 100644
index 0000000..626e707
--- /dev/null
+++ b/cc/private/toolchain/build_interface_so
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+if [[ $# != 2 ]]; then
+   echo "Usage: $0 <so> <interface so>" 1>&2
+   exit 1
+fi
+
+exec cp $1 $2
diff --git a/cc/private/toolchain/cc_configure.bzl b/cc/private/toolchain/cc_configure.bzl
new file mode 100644
index 0000000..3ef32bf
--- /dev/null
+++ b/cc/private/toolchain/cc_configure.bzl
@@ -0,0 +1,181 @@
+# Copyright 2016 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.
+"""Rules for configuring the C++ toolchain (experimental)."""
+
+load("@rules_cc//cc/private/toolchain:windows_cc_configure.bzl", "configure_windows_toolchain")
+load("@rules_cc//cc/private/toolchain:osx_cc_configure.bzl", "configure_osx_toolchain")
+load("@rules_cc//cc/private/toolchain:unix_cc_configure.bzl", "configure_unix_toolchain")
+load(
+    "@rules_cc//cc/private/toolchain:lib_cc_configure.bzl",
+    "get_cpu_value",
+    "resolve_labels",
+)
+load("@bazel_tools//tools/osx:xcode_configure.bzl", "run_xcode_locator")
+
+def _generate_cpp_only_build_file(repository_ctx, cpu_value, paths):
+    repository_ctx.template(
+        "BUILD",
+        paths["@rules_cc//cc/private/toolchain:BUILD.toolchains.tpl"],
+        {"%{name}": cpu_value},
+    )
+
+def cc_autoconf_toolchains_impl(repository_ctx):
+    """Generate BUILD file with 'toolchain' targets for the local host C++ toolchain.
+
+    Args:
+      repository_ctx: repository context
+    """
+    paths = resolve_labels(repository_ctx, [
+        "@rules_cc//cc/private/toolchain:BUILD.toolchains.tpl",
+        "@bazel_tools//tools/osx/crosstool:BUILD.toolchains",
+        "@bazel_tools//tools/osx/crosstool:osx_archs.bzl",
+        "@bazel_tools//tools/osx:xcode_locator.m",
+    ])
+    env = repository_ctx.os.environ
+    cpu_value = get_cpu_value(repository_ctx)
+
+    # Should we try to find C++ toolchain at all? If not, we don't have to generate toolchains for C++ at all.
+    should_detect_cpp_toolchain = "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN" not in env or env["BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN"] != "1"
+
+    # Should we unconditionally *not* use xcode? If so, we don't have to run Xcode locator ever.
+    should_use_cpp_only_toolchain = "BAZEL_USE_CPP_ONLY_TOOLCHAIN" in env and env["BAZEL_USE_CPP_ONLY_TOOLCHAIN"] == "1"
+
+    # Should we unconditionally use xcode? If so, we don't have to run Xcode locator now.
+    should_use_xcode = "BAZEL_USE_XCODE_TOOLCHAIN" in env and env["BAZEL_USE_XCODE_TOOLCHAIN"] == "1"
+
+    if not should_detect_cpp_toolchain:
+        repository_ctx.file("BUILD", "# C++ toolchain autoconfiguration was disabled by BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN env variable.")
+    elif cpu_value == "darwin" and not should_use_cpp_only_toolchain:
+        xcode_toolchains = []
+
+        # Only detect xcode if the user didn't tell us it will be there.
+        if not should_use_xcode:
+            # TODO(#6926): Unify C++ and ObjC toolchains so we don't have to run xcode locator to generate toolchain targets.
+            # And also so we don't have to keep this code in sync with @rules_cc//cc/private/toolchain:osx_cc_configure.bzl.
+            (xcode_toolchains, _xcodeloc_err) = run_xcode_locator(
+                repository_ctx,
+                paths["@bazel_tools//tools/osx:xcode_locator.m"],
+            )
+
+        if should_use_xcode or xcode_toolchains:
+            repository_ctx.symlink(paths["@bazel_tools//tools/osx/crosstool:BUILD.toolchains"], "BUILD")
+            repository_ctx.symlink(paths["@bazel_tools//tools/osx/crosstool:osx_archs.bzl"], "osx_archs.bzl")
+        else:
+            _generate_cpp_only_build_file(repository_ctx, cpu_value, paths)
+    else:
+        _generate_cpp_only_build_file(repository_ctx, cpu_value, paths)
+
+cc_autoconf_toolchains = repository_rule(
+    environ = [
+        "BAZEL_USE_CPP_ONLY_TOOLCHAIN",
+        "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN",
+    ],
+    implementation = cc_autoconf_toolchains_impl,
+)
+
+def cc_autoconf_impl(repository_ctx, overriden_tools = dict()):
+    """Generate BUILD file with 'cc_toolchain' targets for the local host C++ toolchain.
+
+    Args:
+       repository_ctx: repository context
+       overriden_tools: dict of tool paths to use instead of autoconfigured tools
+    """
+
+    env = repository_ctx.os.environ
+    cpu_value = get_cpu_value(repository_ctx)
+    if "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN" in env and env["BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN"] == "1":
+        paths = resolve_labels(repository_ctx, [
+            "@rules_cc//cc/private/toolchain:BUILD.empty",
+            "@rules_cc//cc/private/toolchain:empty_cc_toolchain_config.bzl",
+        ])
+        repository_ctx.symlink(paths["@rules_cc//cc/private/toolchain:empty_cc_toolchain_config.bzl"], "cc_toolchain_config.bzl")
+        repository_ctx.symlink(paths("@rules_cc//cc/private/toolchain:BUILD.empty"), "BUILD")
+    elif cpu_value == "freebsd":
+        paths = resolve_labels(repository_ctx, [
+            "@rules_cc//cc/private/toolchain:BUILD.static.freebsd",
+            "@rules_cc//cc/private/toolchain:freebsd_cc_toolchain_config.bzl",
+        ])
+
+        # This is defaulting to a static crosstool, we should eventually
+        # autoconfigure this platform too.  Theorically, FreeBSD should be
+        # straightforward to add but we cannot run it in a docker container so
+        # skipping until we have proper tests for FreeBSD.
+        repository_ctx.symlink(paths["@rules_cc//cc/private/toolchain:freebsd_cc_toolchain_config.bzl"], "cc_toolchain_config.bzl")
+        repository_ctx.symlink(paths["@rules_cc//cc/private/toolchain:BUILD.static.freebsd"], "BUILD")
+    elif cpu_value == "x64_windows":
+        # TODO(ibiryukov): overriden_tools are only supported in configure_unix_toolchain.
+        # We might want to add that to Windows too(at least for msys toolchain).
+        configure_windows_toolchain(repository_ctx)
+    elif (cpu_value == "darwin" and
+          ("BAZEL_USE_CPP_ONLY_TOOLCHAIN" not in env or env["BAZEL_USE_CPP_ONLY_TOOLCHAIN"] != "1")):
+        configure_osx_toolchain(repository_ctx, overriden_tools)
+    else:
+        configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools)
+
+MSVC_ENVVARS = [
+    "BAZEL_VC",
+    "BAZEL_VC_FULL_VERSION",
+    "BAZEL_VS",
+    "BAZEL_WINSDK_FULL_VERSION",
+    "VS90COMNTOOLS",
+    "VS100COMNTOOLS",
+    "VS110COMNTOOLS",
+    "VS120COMNTOOLS",
+    "VS140COMNTOOLS",
+    "VS150COMNTOOLS",
+    "VS160COMNTOOLS",
+    "TMP",
+    "TEMP",
+]
+
+cc_autoconf = repository_rule(
+    environ = [
+        "ABI_LIBC_VERSION",
+        "ABI_VERSION",
+        "BAZEL_COMPILER",
+        "BAZEL_HOST_SYSTEM",
+        "BAZEL_CXXOPTS",
+        "BAZEL_LINKOPTS",
+        "BAZEL_LINKLIBS",
+        "BAZEL_PYTHON",
+        "BAZEL_SH",
+        "BAZEL_TARGET_CPU",
+        "BAZEL_TARGET_LIBC",
+        "BAZEL_TARGET_SYSTEM",
+        "BAZEL_USE_CPP_ONLY_TOOLCHAIN",
+        "BAZEL_USE_XCODE_TOOLCHAIN",
+        "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN",
+        "BAZEL_USE_LLVM_NATIVE_COVERAGE",
+        "BAZEL_LLVM",
+        "USE_CLANG_CL",
+        "CC",
+        "CC_CONFIGURE_DEBUG",
+        "CC_TOOLCHAIN_NAME",
+        "CPLUS_INCLUDE_PATH",
+        "GCOV",
+        "HOMEBREW_RUBY_PATH",
+        "SYSTEMROOT",
+    ] + MSVC_ENVVARS,
+    implementation = cc_autoconf_impl,
+)
+
+def cc_configure():
+    """A C++ configuration rules that generate the crosstool file."""
+    cc_autoconf_toolchains(name = "local_config_cc_toolchains")
+    cc_autoconf(name = "local_config_cc")
+    native.bind(name = "cc_toolchain", actual = "@local_config_cc//:toolchain")
+    native.register_toolchains(
+        # Use register_toolchain's target pattern expansion to register all toolchains in the package.
+        "@local_config_cc_toolchains//:all",
+    )
diff --git a/cc/private/toolchain/cc_toolchain_config.bzl b/cc/private/toolchain/cc_toolchain_config.bzl
new file mode 100644
index 0000000..df36274
--- /dev/null
+++ b/cc/private/toolchain/cc_toolchain_config.bzl
@@ -0,0 +1,1493 @@
+# Copyright 2019 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.
+
+"""A Starlark cc_toolchain configuration rule"""
+
+load(
+    "@rules_cc//cc/private/toolchain:cc_toolchain_config_lib.bzl",
+    "action_config",
+    "artifact_name_pattern",
+    "env_entry",
+    "env_set",
+    "feature",
+    "feature_set",
+    "flag_group",
+    "flag_set",
+    "make_variable",
+    "tool",
+    "tool_path",
+    "variable_with_value",
+    "with_feature_set",
+)
+load(
+    "@rules_cc//cc:action_names.bzl",
+    _ASSEMBLE_ACTION_NAME = "ASSEMBLE_ACTION_NAME",
+    _CLIF_MATCH_ACTION_NAME = "CLIF_MATCH_ACTION_NAME",
+    _CPP_COMPILE_ACTION_NAME = "CPP_COMPILE_ACTION_NAME",
+    _CPP_HEADER_PARSING_ACTION_NAME = "CPP_HEADER_PARSING_ACTION_NAME",
+    _CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME = "CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME",
+    _CPP_LINK_EXECUTABLE_ACTION_NAME = "CPP_LINK_EXECUTABLE_ACTION_NAME",
+    _CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME = "CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME",
+    _CPP_LINK_STATIC_LIBRARY_ACTION_NAME = "CPP_LINK_STATIC_LIBRARY_ACTION_NAME",
+    _CPP_MODULE_CODEGEN_ACTION_NAME = "CPP_MODULE_CODEGEN_ACTION_NAME",
+    _CPP_MODULE_COMPILE_ACTION_NAME = "CPP_MODULE_COMPILE_ACTION_NAME",
+    _C_COMPILE_ACTION_NAME = "C_COMPILE_ACTION_NAME",
+    _LINKSTAMP_COMPILE_ACTION_NAME = "LINKSTAMP_COMPILE_ACTION_NAME",
+    _LTO_BACKEND_ACTION_NAME = "LTO_BACKEND_ACTION_NAME",
+    _LTO_INDEXING_ACTION_NAME = "LTO_INDEXING_ACTION_NAME",
+    _PREPROCESS_ASSEMBLE_ACTION_NAME = "PREPROCESS_ASSEMBLE_ACTION_NAME",
+    _STRIP_ACTION_NAME = "STRIP_ACTION_NAME",
+)
+
+all_compile_actions = [
+    _C_COMPILE_ACTION_NAME,
+    _CPP_COMPILE_ACTION_NAME,
+    _LINKSTAMP_COMPILE_ACTION_NAME,
+    _ASSEMBLE_ACTION_NAME,
+    _PREPROCESS_ASSEMBLE_ACTION_NAME,
+    _CPP_HEADER_PARSING_ACTION_NAME,
+    _CPP_MODULE_COMPILE_ACTION_NAME,
+    _CPP_MODULE_CODEGEN_ACTION_NAME,
+    _CLIF_MATCH_ACTION_NAME,
+    _LTO_BACKEND_ACTION_NAME,
+]
+
+all_cpp_compile_actions = [
+    _CPP_COMPILE_ACTION_NAME,
+    _LINKSTAMP_COMPILE_ACTION_NAME,
+    _CPP_HEADER_PARSING_ACTION_NAME,
+    _CPP_MODULE_COMPILE_ACTION_NAME,
+    _CPP_MODULE_CODEGEN_ACTION_NAME,
+    _CLIF_MATCH_ACTION_NAME,
+]
+
+preprocessor_compile_actions = [
+    _C_COMPILE_ACTION_NAME,
+    _CPP_COMPILE_ACTION_NAME,
+    _LINKSTAMP_COMPILE_ACTION_NAME,
+    _PREPROCESS_ASSEMBLE_ACTION_NAME,
+    _CPP_HEADER_PARSING_ACTION_NAME,
+    _CPP_MODULE_COMPILE_ACTION_NAME,
+    _CLIF_MATCH_ACTION_NAME,
+]
+
+codegen_compile_actions = [
+    _C_COMPILE_ACTION_NAME,
+    _CPP_COMPILE_ACTION_NAME,
+    _LINKSTAMP_COMPILE_ACTION_NAME,
+    _ASSEMBLE_ACTION_NAME,
+    _PREPROCESS_ASSEMBLE_ACTION_NAME,
+    _CPP_MODULE_CODEGEN_ACTION_NAME,
+    _LTO_BACKEND_ACTION_NAME,
+]
+
+all_link_actions = [
+    _CPP_LINK_EXECUTABLE_ACTION_NAME,
+    _CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME,
+    _CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME,
+]
+
+def _impl(ctx):
+    if ctx.attr.disable_static_cc_toolchains:
+        fail("@rules_cc//cc/private/toolchain:default-toolchain, as well as the cc_toolchains it points " +
+             "to have been removed. See https://github.com/bazelbuild/bazel/issues/8546.")
+
+    if (ctx.attr.cpu == "darwin"):
+        toolchain_identifier = "local_darwin"
+    elif (ctx.attr.cpu == "freebsd"):
+        toolchain_identifier = "local_freebsd"
+    elif (ctx.attr.cpu == "local"):
+        toolchain_identifier = "local_linux"
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_clang"):
+        toolchain_identifier = "local_windows_clang"
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_mingw"):
+        toolchain_identifier = "local_windows_mingw"
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64"):
+        toolchain_identifier = "local_windows_msys64"
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64_mingw64"):
+        toolchain_identifier = "local_windows_msys64_mingw64"
+    elif (ctx.attr.cpu == "armeabi-v7a"):
+        toolchain_identifier = "stub_armeabi-v7a"
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        toolchain_identifier = "vc_14_0_x64"
+    else:
+        fail("Unreachable")
+
+    if (ctx.attr.cpu == "armeabi-v7a"):
+        host_system_name = "armeabi-v7a"
+    elif (ctx.attr.cpu == "darwin" or
+          ctx.attr.cpu == "freebsd" or
+          ctx.attr.cpu == "local" or
+          ctx.attr.cpu == "x64_windows" or
+          ctx.attr.cpu == "x64_windows_msvc"):
+        host_system_name = "local"
+    else:
+        fail("Unreachable")
+
+    if (ctx.attr.cpu == "armeabi-v7a"):
+        target_system_name = "armeabi-v7a"
+    elif (ctx.attr.cpu == "darwin" or
+          ctx.attr.cpu == "freebsd" or
+          ctx.attr.cpu == "local" or
+          ctx.attr.cpu == "x64_windows" or
+          ctx.attr.cpu == "x64_windows_msvc"):
+        target_system_name = "local"
+    else:
+        fail("Unreachable")
+
+    if (ctx.attr.cpu == "armeabi-v7a"):
+        target_cpu = "armeabi-v7a"
+    elif (ctx.attr.cpu == "darwin"):
+        target_cpu = "darwin"
+    elif (ctx.attr.cpu == "freebsd"):
+        target_cpu = "freebsd"
+    elif (ctx.attr.cpu == "local"):
+        target_cpu = "local"
+    elif (ctx.attr.cpu == "x64_windows"):
+        target_cpu = "x64_windows"
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        target_cpu = "x64_windows_msvc"
+    else:
+        fail("Unreachable")
+
+    if (ctx.attr.cpu == "armeabi-v7a"):
+        target_libc = "armeabi-v7a"
+    elif (ctx.attr.cpu == "freebsd" or
+          ctx.attr.cpu == "local" or
+          ctx.attr.cpu == "x64_windows"):
+        target_libc = "local"
+    elif (ctx.attr.cpu == "darwin"):
+        target_libc = "macosx"
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        target_libc = "msvcrt140"
+    else:
+        fail("Unreachable")
+
+    if (ctx.attr.cpu == "x64_windows_msvc"):
+        compiler = "cl"
+    elif (ctx.attr.cpu == "armeabi-v7a" or
+          ctx.attr.cpu == "darwin" or
+          ctx.attr.cpu == "freebsd" or
+          ctx.attr.cpu == "local"):
+        compiler = "compiler"
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_clang"):
+        compiler = "windows_clang"
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_mingw"):
+        compiler = "windows_mingw"
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64"):
+        compiler = "windows_msys64"
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64_mingw64"):
+        compiler = "windows_msys64_mingw64"
+    else:
+        fail("Unreachable")
+
+    if (ctx.attr.cpu == "armeabi-v7a"):
+        abi_version = "armeabi-v7a"
+    elif (ctx.attr.cpu == "darwin" or
+          ctx.attr.cpu == "freebsd" or
+          ctx.attr.cpu == "local" or
+          ctx.attr.cpu == "x64_windows" or
+          ctx.attr.cpu == "x64_windows_msvc"):
+        abi_version = "local"
+    else:
+        fail("Unreachable")
+
+    if (ctx.attr.cpu == "armeabi-v7a"):
+        abi_libc_version = "armeabi-v7a"
+    elif (ctx.attr.cpu == "darwin" or
+          ctx.attr.cpu == "freebsd" or
+          ctx.attr.cpu == "local" or
+          ctx.attr.cpu == "x64_windows" or
+          ctx.attr.cpu == "x64_windows_msvc"):
+        abi_libc_version = "local"
+    else:
+        fail("Unreachable")
+
+    cc_target_os = None
+
+    builtin_sysroot = None
+
+    if (ctx.attr.cpu == "darwin" or
+        ctx.attr.cpu == "freebsd" or
+        ctx.attr.cpu == "local"):
+        objcopy_embed_data_action = action_config(
+            action_name = "objcopy_embed_data",
+            enabled = True,
+            tools = [tool(path = "/usr/bin/objcopy")],
+        )
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_clang"):
+        objcopy_embed_data_action = action_config(
+            action_name = "objcopy_embed_data",
+            enabled = True,
+            tools = [tool(path = "C:/Program Files (x86)/LLVM/bin/objcopy")],
+        )
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_mingw"):
+        objcopy_embed_data_action = action_config(
+            action_name = "objcopy_embed_data",
+            enabled = True,
+            tools = [tool(path = "C:/mingw/bin/objcopy")],
+        )
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64_mingw64"):
+        objcopy_embed_data_action = action_config(
+            action_name = "objcopy_embed_data",
+            enabled = True,
+            tools = [tool(path = "C:/tools/msys64/mingw64/bin/objcopy")],
+        )
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64"):
+        objcopy_embed_data_action = action_config(
+            action_name = "objcopy_embed_data",
+            enabled = True,
+            tools = [tool(path = "C:/tools/msys64/usr/bin/objcopy")],
+        )
+
+    c_compile_action = action_config(
+        action_name = _C_COMPILE_ACTION_NAME,
+        implies = [
+            "compiler_input_flags",
+            "compiler_output_flags",
+            "default_compile_flags",
+            "user_compile_flags",
+            "sysroot",
+            "unfiltered_compile_flags",
+        ],
+        tools = [tool(path = "wrapper/bin/msvc_cl.bat")],
+    )
+
+    cpp_compile_action = action_config(
+        action_name = _CPP_COMPILE_ACTION_NAME,
+        implies = [
+            "compiler_input_flags",
+            "compiler_output_flags",
+            "default_compile_flags",
+            "user_compile_flags",
+            "sysroot",
+            "unfiltered_compile_flags",
+        ],
+        tools = [tool(path = "wrapper/bin/msvc_cl.bat")],
+    )
+
+    if (ctx.attr.cpu == "armeabi-v7a"):
+        action_configs = []
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        action_configs = [c_compile_action, cpp_compile_action]
+    elif (ctx.attr.cpu == "darwin" or
+          ctx.attr.cpu == "freebsd" or
+          ctx.attr.cpu == "local" or
+          ctx.attr.cpu == "x64_windows"):
+        action_configs = [objcopy_embed_data_action]
+    else:
+        fail("Unreachable")
+
+    random_seed_feature = feature(name = "random_seed", enabled = True)
+
+    compiler_output_flags_feature = feature(
+        name = "compiler_output_flags",
+        flag_sets = [
+            flag_set(
+                actions = [_ASSEMBLE_ACTION_NAME],
+                flag_groups = [
+                    flag_group(
+                        flags = ["/Fo%{output_file}", "/Zi"],
+                        expand_if_available = "output_file",
+                        expand_if_not_available = "output_assembly_file",
+                    ),
+                ],
+            ),
+            flag_set(
+                actions = [
+                    _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                    _C_COMPILE_ACTION_NAME,
+                    _CPP_COMPILE_ACTION_NAME,
+                    _CPP_HEADER_PARSING_ACTION_NAME,
+                    _CPP_MODULE_COMPILE_ACTION_NAME,
+                    _CPP_MODULE_CODEGEN_ACTION_NAME,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["/Fo%{output_file}"],
+                        expand_if_available = "output_file",
+                        expand_if_not_available = "output_assembly_file",
+                    ),
+                    flag_group(
+                        flags = ["/Fa%{output_file}"],
+                        expand_if_available = "output_file",
+                    ),
+                    flag_group(
+                        flags = ["/P", "/Fi%{output_file}"],
+                        expand_if_available = "output_file",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    if (ctx.attr.cpu == "local"):
+        default_link_flags_feature = feature(
+            name = "default_link_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-lstdc++",
+                                "-Wl,-z,relro,-z,now",
+                                "-no-canonical-prefixes",
+                                "-pass-exit-codes",
+                            ],
+                        ),
+                    ],
+                ),
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["-Wl,--gc-sections"])],
+                    with_features = [with_feature_set(features = ["opt"])],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "freebsd"):
+        default_link_flags_feature = feature(
+            name = "default_link_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-lstdc++",
+                                "-Wl,-z,relro,-z,now",
+                                "-no-canonical-prefixes",
+                            ],
+                        ),
+                    ],
+                ),
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["-Wl,--gc-sections"])],
+                    with_features = [with_feature_set(features = ["opt"])],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "darwin"):
+        default_link_flags_feature = feature(
+            name = "default_link_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-lstdc++",
+                                "-undefined",
+                                "dynamic_lookup",
+                                "-headerpad_max_install_names",
+                                "-no-canonical-prefixes",
+                            ],
+                        ),
+                    ],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64"):
+        default_link_flags_feature = feature(
+            name = "default_link_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["-lstdc++"])],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        default_link_flags_feature = feature(
+            name = "default_link_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["-m64"])],
+                ),
+            ],
+        )
+
+    if (ctx.attr.cpu == "darwin" or
+        ctx.attr.cpu == "freebsd"):
+        unfiltered_compile_flags_feature = feature(
+            name = "unfiltered_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-no-canonical-prefixes",
+                                "-Wno-builtin-macro-redefined",
+                                "-D__DATE__=\"redacted\"",
+                                "-D__TIMESTAMP__=\"redacted\"",
+                                "-D__TIME__=\"redacted\"",
+                            ],
+                        ),
+                    ],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "local"):
+        unfiltered_compile_flags_feature = feature(
+            name = "unfiltered_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-no-canonical-prefixes",
+                                "-fno-canonical-system-headers",
+                                "-Wno-builtin-macro-redefined",
+                                "-D__DATE__=\"redacted\"",
+                                "-D__TIMESTAMP__=\"redacted\"",
+                                "-D__TIME__=\"redacted\"",
+                            ],
+                        ),
+                    ],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        unfiltered_compile_flags_feature = feature(
+            name = "unfiltered_compile_flags",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["%{unfiltered_compile_flags}"],
+                            iterate_over = "unfiltered_compile_flags",
+                            expand_if_available = "unfiltered_compile_flags",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+    supports_pic_feature = feature(name = "supports_pic", enabled = True)
+
+    if (ctx.attr.cpu == "darwin"):
+        default_compile_flags_feature = feature(
+            name = "default_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-D_FORTIFY_SOURCE=1",
+                                "-fstack-protector",
+                                "-fcolor-diagnostics",
+                                "-Wall",
+                                "-Wthread-safety",
+                                "-Wself-assign",
+                                "-fno-omit-frame-pointer",
+                            ],
+                        ),
+                    ],
+                ),
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [flag_group(flags = ["-g"])],
+                    with_features = [with_feature_set(features = ["dbg"])],
+                ),
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-g0",
+                                "-O2",
+                                "-DNDEBUG",
+                                "-ffunction-sections",
+                                "-fdata-sections",
+                            ],
+                        ),
+                    ],
+                    with_features = [with_feature_set(features = ["opt"])],
+                ),
+                flag_set(
+                    actions = [
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [flag_group(flags = ["-std=c++0x"])],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "local"):
+        default_compile_flags_feature = feature(
+            name = "default_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-U_FORTIFY_SOURCE",
+                                "-D_FORTIFY_SOURCE=1",
+                                "-fstack-protector",
+                                "-Wall",
+                                "-Wunused-but-set-parameter",
+                                "-Wno-free-nonheap-object",
+                                "-fno-omit-frame-pointer",
+                            ],
+                        ),
+                    ],
+                ),
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [flag_group(flags = ["-g"])],
+                    with_features = [with_feature_set(features = ["dbg"])],
+                ),
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-g0",
+                                "-O2",
+                                "-DNDEBUG",
+                                "-ffunction-sections",
+                                "-fdata-sections",
+                            ],
+                        ),
+                    ],
+                    with_features = [with_feature_set(features = ["opt"])],
+                ),
+                flag_set(
+                    actions = [
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [flag_group(flags = ["-std=c++0x"])],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "freebsd"):
+        default_compile_flags_feature = feature(
+            name = "default_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-U_FORTIFY_SOURCE",
+                                "-D_FORTIFY_SOURCE=1",
+                                "-fstack-protector",
+                                "-Wall",
+                                "-fno-omit-frame-pointer",
+                            ],
+                        ),
+                    ],
+                ),
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [flag_group(flags = ["-g"])],
+                    with_features = [with_feature_set(features = ["dbg"])],
+                ),
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-g0",
+                                "-O2",
+                                "-DNDEBUG",
+                                "-ffunction-sections",
+                                "-fdata-sections",
+                            ],
+                        ),
+                    ],
+                    with_features = [with_feature_set(features = ["opt"])],
+                ),
+                flag_set(
+                    actions = [
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [flag_group(flags = ["-std=c++0x"])],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        default_compile_flags_feature = feature(
+            name = "default_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "-m64",
+                                "/D__inline__=__inline",
+                                "/DCOMPILER_MSVC",
+                                "/DNOGDI",
+                                "/DNOMINMAX",
+                                "/DPRAGMA_SUPPORTED",
+                                "/D_WIN32_WINNT=0x0601",
+                                "/D_CRT_SECURE_NO_DEPRECATE",
+                                "/D_CRT_SECURE_NO_WARNINGS",
+                                "/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS",
+                                "/D_USE_MATH_DEFINES",
+                                "/nologo",
+                                "/bigobj",
+                                "/Zm500",
+                                "/J",
+                                "/Gy",
+                                "/GF",
+                                "/W3",
+                                "/EHsc",
+                                "/wd4351",
+                                "/wd4291",
+                                "/wd4250",
+                                "/wd4996",
+                            ],
+                        ),
+                    ],
+                ),
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["/DDEBUG=1", "-g", "/Od", "-Xcompilation-mode=dbg"],
+                        ),
+                    ],
+                    with_features = [with_feature_set(features = ["dbg"])],
+                ),
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["/DNDEBUG", "/Od", "-Xcompilation-mode=fastbuild"],
+                        ),
+                    ],
+                    with_features = [with_feature_set(features = ["fastbuild"])],
+                ),
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["/DNDEBUG", "/O2", "-Xcompilation-mode=opt"],
+                        ),
+                    ],
+                    with_features = [with_feature_set(features = ["opt"])],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_clang" or
+          ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_mingw" or
+          ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64_mingw64"):
+        default_compile_flags_feature = feature(
+            name = "default_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [flag_group(flags = ["-std=c++0x"])],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64"):
+        default_compile_flags_feature = feature(
+            name = "default_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [flag_group(flags = ["-std=gnu++0x"])],
+                ),
+            ],
+        )
+
+    opt_feature = feature(name = "opt")
+
+    supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True)
+
+    objcopy_embed_flags_feature = feature(
+        name = "objcopy_embed_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = ["objcopy_embed_data"],
+                flag_groups = [flag_group(flags = ["-I", "binary"])],
+            ),
+        ],
+    )
+
+    dbg_feature = feature(name = "dbg")
+
+    if (ctx.attr.cpu == "darwin" or
+        ctx.attr.cpu == "freebsd" or
+        ctx.attr.cpu == "local"):
+        user_compile_flags_feature = feature(
+            name = "user_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["%{user_compile_flags}"],
+                            iterate_over = "user_compile_flags",
+                            expand_if_available = "user_compile_flags",
+                        ),
+                    ],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        user_compile_flags_feature = feature(
+            name = "user_compile_flags",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["%{user_compile_flags}"],
+                            iterate_over = "user_compile_flags",
+                            expand_if_available = "user_compile_flags",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+    if (ctx.attr.cpu == "darwin" or
+        ctx.attr.cpu == "freebsd" or
+        ctx.attr.cpu == "local"):
+        sysroot_feature = feature(
+            name = "sysroot",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _LINKSTAMP_COMPILE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _LTO_BACKEND_ACTION_NAME,
+                        _CLIF_MATCH_ACTION_NAME,
+                        _CPP_LINK_EXECUTABLE_ACTION_NAME,
+                        _CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME,
+                        _CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["--sysroot=%{sysroot}"],
+                            expand_if_available = "sysroot",
+                        ),
+                    ],
+                ),
+            ],
+        )
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        sysroot_feature = feature(
+            name = "sysroot",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        _ASSEMBLE_ACTION_NAME,
+                        _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                        _C_COMPILE_ACTION_NAME,
+                        _CPP_COMPILE_ACTION_NAME,
+                        _CPP_HEADER_PARSING_ACTION_NAME,
+                        _CPP_MODULE_COMPILE_ACTION_NAME,
+                        _CPP_MODULE_CODEGEN_ACTION_NAME,
+                        _CPP_LINK_EXECUTABLE_ACTION_NAME,
+                        _CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME,
+                        _CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["--sysroot=%{sysroot}"],
+                            iterate_over = "sysroot",
+                            expand_if_available = "sysroot",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+    include_paths_feature = feature(
+        name = "include_paths",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                    _C_COMPILE_ACTION_NAME,
+                    _CPP_COMPILE_ACTION_NAME,
+                    _CPP_HEADER_PARSING_ACTION_NAME,
+                    _CPP_MODULE_COMPILE_ACTION_NAME,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["/I%{quote_include_paths}"],
+                        iterate_over = "quote_include_paths",
+                    ),
+                    flag_group(
+                        flags = ["/I%{include_paths}"],
+                        iterate_over = "include_paths",
+                    ),
+                    flag_group(
+                        flags = ["/I%{system_include_paths}"],
+                        iterate_over = "system_include_paths",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    dependency_file_feature = feature(
+        name = "dependency_file",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    _ASSEMBLE_ACTION_NAME,
+                    _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                    _C_COMPILE_ACTION_NAME,
+                    _CPP_COMPILE_ACTION_NAME,
+                    _CPP_MODULE_COMPILE_ACTION_NAME,
+                    _CPP_HEADER_PARSING_ACTION_NAME,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["/DEPENDENCY_FILE", "%{dependency_file}"],
+                        expand_if_available = "dependency_file",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    compiler_input_flags_feature = feature(
+        name = "compiler_input_flags",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    _ASSEMBLE_ACTION_NAME,
+                    _PREPROCESS_ASSEMBLE_ACTION_NAME,
+                    _C_COMPILE_ACTION_NAME,
+                    _CPP_COMPILE_ACTION_NAME,
+                    _CPP_HEADER_PARSING_ACTION_NAME,
+                    _CPP_MODULE_COMPILE_ACTION_NAME,
+                    _CPP_MODULE_CODEGEN_ACTION_NAME,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["/c", "%{source_file}"],
+                        expand_if_available = "source_file",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    fastbuild_feature = feature(name = "fastbuild")
+
+    if (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64"):
+        features = [
+            default_compile_flags_feature,
+            default_link_flags_feature,
+            supports_dynamic_linker_feature,
+            objcopy_embed_flags_feature,
+        ]
+    elif (ctx.attr.cpu == "darwin"):
+        features = [
+            default_compile_flags_feature,
+            default_link_flags_feature,
+            supports_dynamic_linker_feature,
+            supports_pic_feature,
+            objcopy_embed_flags_feature,
+            dbg_feature,
+            opt_feature,
+            user_compile_flags_feature,
+            sysroot_feature,
+            unfiltered_compile_flags_feature,
+        ]
+    elif (ctx.attr.cpu == "freebsd" or
+          ctx.attr.cpu == "local"):
+        features = [
+            default_compile_flags_feature,
+            default_link_flags_feature,
+            supports_dynamic_linker_feature,
+            supports_pic_feature,
+            objcopy_embed_flags_feature,
+            opt_feature,
+            dbg_feature,
+            user_compile_flags_feature,
+            sysroot_feature,
+            unfiltered_compile_flags_feature,
+        ]
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_clang" or
+          ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_mingw" or
+          ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64_mingw64"):
+        features = [
+            default_compile_flags_feature,
+            supports_dynamic_linker_feature,
+            objcopy_embed_flags_feature,
+        ]
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        features = [
+            default_link_flags_feature,
+            random_seed_feature,
+            default_compile_flags_feature,
+            include_paths_feature,
+            dependency_file_feature,
+            user_compile_flags_feature,
+            sysroot_feature,
+            unfiltered_compile_flags_feature,
+            compiler_output_flags_feature,
+            compiler_input_flags_feature,
+            dbg_feature,
+            fastbuild_feature,
+            opt_feature,
+        ]
+    elif (ctx.attr.cpu == "armeabi-v7a"):
+        features = [supports_dynamic_linker_feature, supports_pic_feature]
+
+    if (ctx.attr.cpu == "armeabi-v7a"):
+        cxx_builtin_include_directories = []
+    elif (ctx.attr.cpu == "darwin"):
+        cxx_builtin_include_directories = ["/"]
+    elif (ctx.attr.cpu == "freebsd"):
+        cxx_builtin_include_directories = ["/usr/lib/clang", "/usr/local/include", "/usr/include"]
+    elif (ctx.attr.cpu == "local" or
+          ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_clang"):
+        cxx_builtin_include_directories = ["/usr/lib/gcc/", "/usr/local/include", "/usr/include"]
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        cxx_builtin_include_directories = [
+            "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/INCLUDE",
+            "C:/Program Files (x86)/Windows Kits/10/include/",
+            "C:/Program Files (x86)/Windows Kits/8.1/include/",
+            "C:/Program Files (x86)/GnuWin32/include/",
+            "C:/python_27_amd64/files/include",
+        ]
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_mingw"):
+        cxx_builtin_include_directories = ["C:/mingw/include", "C:/mingw/lib/gcc"]
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64_mingw64"):
+        cxx_builtin_include_directories = ["C:/tools/msys64/mingw64/x86_64-w64-mingw32/include"]
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64"):
+        cxx_builtin_include_directories = ["C:/tools/msys64/", "/usr/"]
+    else:
+        fail("Unreachable")
+
+    artifact_name_patterns = []
+
+    make_variables = []
+
+    if (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64_mingw64"):
+        tool_paths = [
+            tool_path(
+                name = "ar",
+                path = "C:/tools/msys64/mingw64/bin/ar",
+            ),
+            tool_path(
+                name = "compat-ld",
+                path = "C:/tools/msys64/mingw64/bin/ld",
+            ),
+            tool_path(
+                name = "cpp",
+                path = "C:/tools/msys64/mingw64/bin/cpp",
+            ),
+            tool_path(
+                name = "dwp",
+                path = "C:/tools/msys64/mingw64/bin/dwp",
+            ),
+            tool_path(
+                name = "gcc",
+                path = "C:/tools/msys64/mingw64/bin/gcc",
+            ),
+            tool_path(
+                name = "gcov",
+                path = "C:/tools/msys64/mingw64/bin/gcov",
+            ),
+            tool_path(
+                name = "ld",
+                path = "C:/tools/msys64/mingw64/bin/ld",
+            ),
+            tool_path(
+                name = "nm",
+                path = "C:/tools/msys64/mingw64/bin/nm",
+            ),
+            tool_path(
+                name = "objcopy",
+                path = "C:/tools/msys64/mingw64/bin/objcopy",
+            ),
+            tool_path(
+                name = "objdump",
+                path = "C:/tools/msys64/mingw64/bin/objdump",
+            ),
+            tool_path(
+                name = "strip",
+                path = "C:/tools/msys64/mingw64/bin/strip",
+            ),
+        ]
+    elif (ctx.attr.cpu == "armeabi-v7a"):
+        tool_paths = [
+            tool_path(name = "ar", path = "/bin/false"),
+            tool_path(name = "compat-ld", path = "/bin/false"),
+            tool_path(name = "cpp", path = "/bin/false"),
+            tool_path(name = "dwp", path = "/bin/false"),
+            tool_path(name = "gcc", path = "/bin/false"),
+            tool_path(name = "gcov", path = "/bin/false"),
+            tool_path(name = "ld", path = "/bin/false"),
+            tool_path(name = "nm", path = "/bin/false"),
+            tool_path(name = "objcopy", path = "/bin/false"),
+            tool_path(name = "objdump", path = "/bin/false"),
+            tool_path(name = "strip", path = "/bin/false"),
+        ]
+    elif (ctx.attr.cpu == "freebsd"):
+        tool_paths = [
+            tool_path(name = "ar", path = "/usr/bin/ar"),
+            tool_path(name = "compat-ld", path = "/usr/bin/ld"),
+            tool_path(name = "cpp", path = "/usr/bin/cpp"),
+            tool_path(name = "dwp", path = "/usr/bin/dwp"),
+            tool_path(name = "gcc", path = "/usr/bin/clang"),
+            tool_path(name = "gcov", path = "/usr/bin/gcov"),
+            tool_path(name = "ld", path = "/usr/bin/ld"),
+            tool_path(name = "nm", path = "/usr/bin/nm"),
+            tool_path(name = "objcopy", path = "/usr/bin/objcopy"),
+            tool_path(name = "objdump", path = "/usr/bin/objdump"),
+            tool_path(name = "strip", path = "/usr/bin/strip"),
+        ]
+    elif (ctx.attr.cpu == "local"):
+        tool_paths = [
+            tool_path(name = "ar", path = "/usr/bin/ar"),
+            tool_path(name = "compat-ld", path = "/usr/bin/ld"),
+            tool_path(name = "cpp", path = "/usr/bin/cpp"),
+            tool_path(name = "dwp", path = "/usr/bin/dwp"),
+            tool_path(name = "gcc", path = "/usr/bin/gcc"),
+            tool_path(name = "gcov", path = "/usr/bin/gcov"),
+            tool_path(name = "ld", path = "/usr/bin/ld"),
+            tool_path(name = "nm", path = "/usr/bin/nm"),
+            tool_path(name = "objcopy", path = "/usr/bin/objcopy"),
+            tool_path(name = "objdump", path = "/usr/bin/objdump"),
+            tool_path(name = "strip", path = "/usr/bin/strip"),
+        ]
+    elif (ctx.attr.cpu == "darwin"):
+        tool_paths = [
+            tool_path(name = "ar", path = "/usr/bin/libtool"),
+            tool_path(name = "compat-ld", path = "/usr/bin/ld"),
+            tool_path(name = "cpp", path = "/usr/bin/cpp"),
+            tool_path(name = "dwp", path = "/usr/bin/dwp"),
+            tool_path(name = "gcc", path = "osx_cc_wrapper.sh"),
+            tool_path(name = "gcov", path = "/usr/bin/gcov"),
+            tool_path(name = "ld", path = "/usr/bin/ld"),
+            tool_path(name = "nm", path = "/usr/bin/nm"),
+            tool_path(name = "objcopy", path = "/usr/bin/objcopy"),
+            tool_path(name = "objdump", path = "/usr/bin/objdump"),
+            tool_path(name = "strip", path = "/usr/bin/strip"),
+        ]
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_clang"):
+        tool_paths = [
+            tool_path(name = "ar", path = "C:/mingw/bin/ar"),
+            tool_path(
+                name = "compat-ld",
+                path = "C:/Program Files (x86)/LLVM/bin/ld",
+            ),
+            tool_path(
+                name = "cpp",
+                path = "C:/Program Files (x86)/LLVM/bin/cpp",
+            ),
+            tool_path(
+                name = "dwp",
+                path = "C:/Program Files (x86)/LLVM/bin/dwp",
+            ),
+            tool_path(
+                name = "gcc",
+                path = "C:/Program Files (x86)/LLVM/bin/clang",
+            ),
+            tool_path(
+                name = "gcov",
+                path = "C:/Program Files (x86)/LLVM/bin/gcov",
+            ),
+            tool_path(
+                name = "ld",
+                path = "C:/Program Files (x86)/LLVM/bin/ld",
+            ),
+            tool_path(
+                name = "nm",
+                path = "C:/Program Files (x86)/LLVM/bin/nm",
+            ),
+            tool_path(
+                name = "objcopy",
+                path = "C:/Program Files (x86)/LLVM/bin/objcopy",
+            ),
+            tool_path(
+                name = "objdump",
+                path = "C:/Program Files (x86)/LLVM/bin/objdump",
+            ),
+            tool_path(
+                name = "strip",
+                path = "C:/Program Files (x86)/LLVM/bin/strip",
+            ),
+        ]
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_mingw"):
+        tool_paths = [
+            tool_path(name = "ar", path = "C:/mingw/bin/ar"),
+            tool_path(name = "compat-ld", path = "C:/mingw/bin/ld"),
+            tool_path(name = "cpp", path = "C:/mingw/bin/cpp"),
+            tool_path(name = "dwp", path = "C:/mingw/bin/dwp"),
+            tool_path(name = "gcc", path = "C:/mingw/bin/gcc"),
+            tool_path(name = "gcov", path = "C:/mingw/bin/gcov"),
+            tool_path(name = "ld", path = "C:/mingw/bin/ld"),
+            tool_path(name = "nm", path = "C:/mingw/bin/nm"),
+            tool_path(name = "objcopy", path = "C:/mingw/bin/objcopy"),
+            tool_path(name = "objdump", path = "C:/mingw/bin/objdump"),
+            tool_path(name = "strip", path = "C:/mingw/bin/strip"),
+        ]
+    elif (ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "windows_msys64"):
+        tool_paths = [
+            tool_path(name = "ar", path = "C:/tools/msys64/usr/bin/ar"),
+            tool_path(
+                name = "compat-ld",
+                path = "C:/tools/msys64/usr/bin/ld",
+            ),
+            tool_path(
+                name = "cpp",
+                path = "C:/tools/msys64/usr/bin/cpp",
+            ),
+            tool_path(
+                name = "dwp",
+                path = "C:/tools/msys64/usr/bin/dwp",
+            ),
+            tool_path(
+                name = "gcc",
+                path = "C:/tools/msys64/usr/bin/gcc",
+            ),
+            tool_path(
+                name = "gcov",
+                path = "C:/tools/msys64/usr/bin/gcov",
+            ),
+            tool_path(name = "ld", path = "C:/tools/msys64/usr/bin/ld"),
+            tool_path(name = "nm", path = "C:/tools/msys64/usr/bin/nm"),
+            tool_path(
+                name = "objcopy",
+                path = "C:/tools/msys64/usr/bin/objcopy",
+            ),
+            tool_path(
+                name = "objdump",
+                path = "C:/tools/msys64/usr/bin/objdump",
+            ),
+            tool_path(
+                name = "strip",
+                path = "C:/tools/msys64/usr/bin/strip",
+            ),
+        ]
+    elif (ctx.attr.cpu == "x64_windows_msvc"):
+        tool_paths = [
+            tool_path(name = "ar", path = "wrapper/bin/msvc_link.bat"),
+            tool_path(name = "cpp", path = "wrapper/bin/msvc_cl.bat"),
+            tool_path(name = "gcc", path = "wrapper/bin/msvc_cl.bat"),
+            tool_path(name = "gcov", path = "wrapper/bin/msvc_nop.bat"),
+            tool_path(name = "ld", path = "wrapper/bin/msvc_link.bat"),
+            tool_path(name = "nm", path = "wrapper/bin/msvc_nop.bat"),
+            tool_path(
+                name = "objcopy",
+                path = "wrapper/bin/msvc_nop.bat",
+            ),
+            tool_path(
+                name = "objdump",
+                path = "wrapper/bin/msvc_nop.bat",
+            ),
+            tool_path(
+                name = "strip",
+                path = "wrapper/bin/msvc_nop.bat",
+            ),
+        ]
+    else:
+        fail("Unreachable")
+
+    out = ctx.actions.declare_file(ctx.label.name)
+    ctx.actions.write(out, "Fake executable")
+    return [
+        cc_common.create_cc_toolchain_config_info(
+            ctx = ctx,
+            features = features,
+            action_configs = action_configs,
+            artifact_name_patterns = artifact_name_patterns,
+            cxx_builtin_include_directories = cxx_builtin_include_directories,
+            toolchain_identifier = toolchain_identifier,
+            host_system_name = host_system_name,
+            target_system_name = target_system_name,
+            target_cpu = target_cpu,
+            target_libc = target_libc,
+            compiler = compiler,
+            abi_version = abi_version,
+            abi_libc_version = abi_libc_version,
+            tool_paths = tool_paths,
+            make_variables = make_variables,
+            builtin_sysroot = builtin_sysroot,
+            cc_target_os = cc_target_os,
+        ),
+        DefaultInfo(
+            executable = out,
+        ),
+    ]
+
+cc_toolchain_config = rule(
+    implementation = _impl,
+    attrs = {
+        "cpu": attr.string(mandatory = True),
+        "compiler": attr.string(),
+        "disable_static_cc_toolchains": attr.bool(),
+    },
+    provides = [CcToolchainConfigInfo],
+    executable = True,
+)
diff --git a/cc/private/toolchain/cc_toolchain_config_lib.bzl b/cc/private/toolchain/cc_toolchain_config_lib.bzl
new file mode 100644
index 0000000..48a855b
--- /dev/null
+++ b/cc/private/toolchain/cc_toolchain_config_lib.bzl
@@ -0,0 +1,542 @@
+# Copyright 2018 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.
+
+""" A library of functions creating structs for CcToolchainConfigInfo."""
+
+def _check_is_none_or_right_type(obj, obj_of_right_type, parameter_name, method_name):
+    if obj != None:
+        _check_right_type(obj, obj_of_right_type, parameter_name, method_name)
+
+def _check_right_type(obj, obj_of_right_type, parameter_name, method_name):
+    if type(obj) != type(obj_of_right_type):
+        fail("{} parameter of {} should be a {}, found {}."
+            .format(parameter_name, method_name, type(obj_of_right_type), type(obj)))
+
+def _check_is_nonempty_string(obj, parameter_name, method_name):
+    _check_right_type(obj, "", parameter_name, method_name)
+    if obj == "":
+        fail("{} parameter of {} must be a nonempty string."
+            .format(parameter_name, method_name))
+
+def _check_is_nonempty_list(obj, parameter_name, method_name):
+    _check_right_type(obj, [], parameter_name, method_name)
+    if len(obj) == 0:
+        fail("{} parameter of {} must be a nonempty list."
+            .format(parameter_name, method_name))
+
+EnvEntryInfo = provider(fields = ["key", "value", "type_name"])
+
+def env_entry(key, value):
+    """ A key/value pair to be added as an environment variable.
+
+    The returned EnvEntry provider finds its use in EnvSet creation through
+    the env_entries parameter of env_set(); EnvSet groups environment variables
+    that need to be expanded for specific actions.
+    The value of this pair is expanded in the same way as is described in
+    flag_group. The key remains an unexpanded string literal.
+
+    Args:
+        key: a string literal representing the name of the variable.
+        value: the value to be expanded.
+
+    Returns:
+        An EnvEntryInfo provider.
+    """
+    _check_is_nonempty_string(key, "key", "env_entry")
+    _check_is_nonempty_string(value, "value", "env_entry")
+    return EnvEntryInfo(key = key, value = value, type_name = "env_entry")
+
+VariableWithValueInfo = provider(fields = ["name", "value", "type_name"])
+
+def variable_with_value(name, value):
+    """ Represents equality check between a variable and a certain value.
+
+    The returned provider finds its use through flag_group.expand_if_equal,
+    making the expansion of the flag_group conditional on the value of the
+    variable.
+
+    Args:
+        name: name of the variable.
+        value: the value the variable should be compared against.
+
+    Returns:
+        A VariableWithValueInfo provider.
+    """
+    _check_is_nonempty_string(name, "name", "variable_with_value")
+    _check_is_nonempty_string(value, "value", "variable_with_value")
+    return VariableWithValueInfo(
+        name = name,
+        value = value,
+        type_name = "variable_with_value",
+    )
+
+MakeVariableInfo = provider(fields = ["name", "value", "type_name"])
+
+def make_variable(name, value):
+    """ A make variable that is made accessible to rules."""
+    _check_is_nonempty_string(name, "name", "make_variable")
+    _check_is_nonempty_string(value, "value", "make_variable")
+    return MakeVariableInfo(
+        name = name,
+        value = value,
+        type_name = "make_variable",
+    )
+
+FeatureSetInfo = provider(fields = ["features", "type_name"])
+
+def feature_set(features = []):
+    """ A set of features.
+
+    Used to support logical 'and' when specifying feature requirements in a
+    feature.
+
+    Args:
+        features: A list of unordered feature names.
+
+    Returns:
+        A FeatureSetInfo provider.
+    """
+    _check_right_type(features, [], "features", "feature_set")
+    return FeatureSetInfo(features = features, type_name = "feature_set")
+
+WithFeatureSetInfo = provider(fields = ["features", "not_features", "type_name"])
+
+def with_feature_set(features = [], not_features = []):
+    """ A set of positive and negative features.
+
+    This stanza will evaluate to true when every 'feature' is enabled, and
+    every 'not_feature' is not enabled.
+
+    Args:
+        features: A list of feature names that need to be enabled.
+        not_features: A list of feature names that need to not be enabled.
+
+    Returns:
+        A WithFeatureSetInfo provider.
+    """
+    _check_right_type(features, [], "features", "with_feature_set")
+    _check_right_type(not_features, [], "not_features", "with_feature_set")
+    return WithFeatureSetInfo(
+        features = features,
+        not_features = not_features,
+        type_name = "with_feature_set",
+    )
+
+EnvSetInfo = provider(fields = ["actions", "env_entries", "with_features", "type_name"])
+
+def env_set(actions, env_entries = [], with_features = []):
+    """ Groups a set of environment variables to apply for certain actions.
+
+    EnvSet providers are passed to feature() and action_config(), to be applied to
+    the actions they are specified for.
+
+    Args:
+        actions: A list of actions this env set applies to; each env set must
+            specify at least one action.
+        env_entries: A list of EnvEntry - the environment variables applied
+            via this env set.
+        with_features: A list of feature sets defining when this env set gets
+            applied. The env set will be applied when any one of the feature
+            sets evaluate to true. (That is, when when every 'feature' is
+            enabled, and every 'not_feature' is not enabled.)
+            If 'with_features' is omitted, the env set will be applied
+            unconditionally for every action specified.
+
+    Returns:
+        An EnvSetInfo provider.
+    """
+    _check_is_nonempty_list(actions, "actions", "env_set")
+    _check_right_type(env_entries, [], "env_entries", "env_set")
+    _check_right_type(with_features, [], "with_features", "env_set")
+    return EnvSetInfo(
+        actions = actions,
+        env_entries = env_entries,
+        with_features = with_features,
+        type_name = "env_set",
+    )
+
+FlagGroupInfo = provider(fields = [
+    "flags",
+    "flag_groups",
+    "iterate_over",
+    "expand_if_available",
+    "expand_if_not_available",
+    "expand_if_true",
+    "expand_if_false",
+    "expand_if_equal",
+    "type_name",
+])
+
+def flag_group(
+        flags = [],
+        flag_groups = [],
+        iterate_over = None,
+        expand_if_available = None,
+        expand_if_not_available = None,
+        expand_if_true = None,
+        expand_if_false = None,
+        expand_if_equal = None):
+    """ A group of flags. Supports parametrization via variable expansion.
+
+    To expand a variable of list type, flag_group has to be annotated with
+    `iterate_over` message. Then all nested flags or flag_groups will be
+    expanded repeatedly for each element of the list.
+    For example:
+       flag_group(
+         iterate_over = 'include_path',
+         flags = ['-I', '%{include_path}'],
+       )
+    ... will get expanded to -I /to/path1 -I /to/path2 ... for each
+    include_path /to/pathN.
+
+    To expand a variable of structure type, use dot-notation, e.g.:
+        flag_group(
+          iterate_over = "libraries_to_link",
+          flag_groups = [
+            flag_group(
+              iterate_over = "libraries_to_link.libraries",
+              flags = ["-L%{libraries_to_link.libraries.directory}"],
+            )
+          ]
+        )
+
+    Flag groups can be nested; if they are, the flag group must only contain
+    other flag groups (no flags) so the order is unambiguously specified.
+    In order to expand a variable of nested lists, 'iterate_over' can be used.
+    For example:
+       flag_group (
+         iterate_over = 'object_files',
+         flag_groups = [
+           flag_group (
+             flags = ['--start-lib'],
+           ),
+           flag_group (
+             iterate_over = 'object_files',
+             flags = ['%{object_files}'],
+           ),
+           flag_group (
+             flags = ['--end-lib'],
+           )
+        ]
+     )
+     ... will get expanded to
+       --start-lib a1.o a2.o ... --end-lib --start-lib b1.o b2.o .. --end-lib
+       with %{object_files} being a variable of nested list type
+       [['a1.o', 'a2.o', ...], ['b1.o', 'b2.o', ...], ...].
+
+    Args:
+        flags: a string list, representing flags. Only one of flags and
+            flag_groups can be set, as to avoid ambiguity.
+        flag_groups: a list of FlagGroup entries. Only one of flags and
+            flag_groups can be set, as to avoid ambiguity.
+        iterate_over: a string, representing a variable of list type.
+        expand_if_available: A build variable that needs to be available
+            in order to expand the flag_group.
+        expand_if_not_available: A build variable that needs to be
+            unavailable in order for this flag_group to be expanded.
+        expand_if_true: if set, this variable needs to evaluate to True in
+            order for the flag_group to be expanded.
+        expand_if_false: if set, this variable needs to evalate to False in
+            order for the flag_group to be expanded.
+        expand_if_equal: a VariableWithValue, the flag_group is expanded in
+           case of equality.
+
+    Returns:
+        A FlagGroupInfo provider.
+    """
+
+    _check_right_type(flags, [], "flags", "flag_group")
+    _check_right_type(flag_groups, [], "flag_groups", "flag_group")
+    if len(flags) > 0 and len(flag_groups) > 0:
+        fail("flag_group must not contain both a flag and another flag_group.")
+    if len(flags) == 0 and len(flag_groups) == 0:
+        fail("flag_group must contain either a list of flags or a list of flag_groups.")
+    _check_is_none_or_right_type(expand_if_true, "string", "expand_if_true", "flag_group")
+    _check_is_none_or_right_type(expand_if_false, "string", "expand_if_false", "flag_group")
+    _check_is_none_or_right_type(expand_if_available, "string", "expand_if_available", "flag_group")
+    _check_is_none_or_right_type(
+        expand_if_not_available,
+        "string",
+        "expand_if_not_available",
+        "flag_group",
+    )
+    _check_is_none_or_right_type(iterate_over, "string", "iterate_over", "flag_group")
+
+    return FlagGroupInfo(
+        flags = flags,
+        flag_groups = flag_groups,
+        iterate_over = iterate_over,
+        expand_if_available = expand_if_available,
+        expand_if_not_available = expand_if_not_available,
+        expand_if_true = expand_if_true,
+        expand_if_false = expand_if_false,
+        expand_if_equal = expand_if_equal,
+        type_name = "flag_group",
+    )
+
+FlagSetInfo = provider(fields = [
+    "actions",
+    "with_features",
+    "flag_groups",
+    "type_name",
+])
+
+def flag_set(
+        actions = [],
+        with_features = [],
+        flag_groups = []):
+    """ A set of flags to be expanded in the command line for specific actions.
+
+    Args:
+        actions: The actions this flag set applies to; each flag set must
+            specify at least one action.
+        with_features: A list of feature sets defining when this flag set gets
+            applied. The flag set will be applied when any one of the feature
+            sets evaluate to true. (That is, when when every 'feature' is
+            enabled, and every 'not_feature' is not enabled.)
+            If 'with_feature' is omitted, the flag set will be applied
+            unconditionally for every action specified.
+        flag_groups: A FlagGroup list - the flags applied via this flag set.
+
+    Returns:
+        A FlagSetInfo provider.
+    """
+    _check_right_type(actions, [], "actions", "flag_set")
+    _check_right_type(with_features, [], "with_features", "flag_set")
+    _check_right_type(flag_groups, [], "flag_groups", "flag_set")
+    return FlagSetInfo(
+        actions = actions,
+        with_features = with_features,
+        flag_groups = flag_groups,
+        type_name = "flag_set",
+    )
+
+FeatureInfo = provider(fields = [
+    "name",
+    "enabled",
+    "flag_sets",
+    "env_sets",
+    "requires",
+    "implies",
+    "provides",
+    "type_name",
+])
+
+def feature(
+        name,
+        enabled = False,
+        flag_sets = [],
+        env_sets = [],
+        requires = [],
+        implies = [],
+        provides = []):
+    """ Contains all flag specifications for one feature.
+
+    Args:
+        name: The feature's name. It is possible to introduce a feature without
+            a change to Bazel by adding a 'feature' section to the toolchain
+            and adding the corresponding string as feature in the BUILD file.
+        enabled: If 'True', this feature is enabled unless a rule type
+            explicitly marks it as unsupported.
+        flag_sets: A FlagSet list - If the given feature is enabled, the flag
+            sets will be applied for the actions are specified for.
+        env_sets: an EnvSet list - If the given feature is enabled, the env
+            sets will be applied for the actions they are specified for.
+        requires: A list of feature sets defining when this feature is
+            supported by the  toolchain. The feature is supported if any of the
+            feature sets fully apply, that is, when all features of a feature
+            set are enabled.
+            If 'requires' is omitted, the feature is supported independently of
+            which other features are enabled.
+            Use this for example to filter flags depending on the build mode
+            enabled (opt / fastbuild / dbg).
+        implies: A string list of features or action configs that are
+            automatically enabled when this feature is enabled. If any of the
+            implied features or action configs cannot be enabled, this feature
+            will (silently) not be enabled either.
+        provides: A list of names this feature conflicts with.
+            A feature cannot be enabled if:
+              - 'provides' contains the name of a different feature or action
+            config that we want to enable.
+              - 'provides' contains the same value as a 'provides' in a
+            different feature or action config that we want to enable.
+            Use this in order to ensure that incompatible features cannot be
+            accidentally activated at the same time, leading to hard to
+            diagnose compiler errors.
+
+    Returns:
+        A FeatureInfo provider.
+    """
+    _check_right_type(enabled, True, "enabled", "feature")
+    _check_right_type(flag_sets, [], "flag_sets", "feature")
+    _check_right_type(env_sets, [], "env_sets", "feature")
+    _check_right_type(requires, [], "requires", "feature")
+    _check_right_type(provides, [], "provides", "feature")
+    _check_right_type(implies, [], "implies", "feature")
+    return FeatureInfo(
+        name = name,
+        enabled = enabled,
+        flag_sets = flag_sets,
+        env_sets = env_sets,
+        requires = requires,
+        implies = implies,
+        provides = provides,
+        type_name = "feature",
+    )
+
+ToolPathInfo = provider(fields = ["name", "path", "type_name"])
+
+def tool_path(name, path):
+    """ Tool locations.
+
+    Args:
+        name: Name of the tool.
+        path: Location of the tool; Can be absolute path (in case of non hermetic
+            toolchain), or path relative to the cc_toolchain's package.
+
+    Returns:
+        A ToolPathInfo provider.
+
+    Deprecated:
+         Prefer specifying an ActionConfig for the action that needs the tool.
+         TODO(b/27903698) migrate to ActionConfig.
+    """
+    _check_is_nonempty_string(name, "name", "tool_path")
+    _check_is_nonempty_string(path, "path", "tool_path")
+    return ToolPathInfo(name = name, path = path, type_name = "tool_path")
+
+ToolInfo = provider(fields = ["path", "with_features", "execution_requirements", "type_name"])
+
+def tool(path, with_features = [], execution_requirements = []):
+    """ Describes a tool associated with a crosstool action config.
+
+    Args:
+        path: Location of the tool; Can be absolute path (in case of non hermetic
+            toolchain), or path relative to the cc_toolchain's package.
+        with_features: A list of feature sets defining when this tool is
+            applicable. The tool will used when any one of the feature sets
+            evaluate to true. (That is, when when every 'feature' is enabled,
+            and every 'not_feature' is not enabled.)
+            If 'with_feature' is omitted, the tool will apply for any feature
+            configuration.
+        execution_requirements: Requirements on the execution environment for
+            the execution of this tool, to be passed as out-of-band "hints" to
+            the execution backend.
+            Ex. "requires-darwin"
+
+    Returns:
+        A ToolInfo provider.
+    """
+    _check_is_nonempty_string(path, "path", "tool")
+    _check_right_type(with_features, [], "with_features", "tool")
+    _check_right_type(execution_requirements, [], "execution_requirements", "tool")
+    return ToolInfo(
+        path = path,
+        with_features = with_features,
+        execution_requirements = execution_requirements,
+        type_name = "tool",
+    )
+
+ActionConfigInfo = provider(fields = [
+    "config_name",
+    "action_name",
+    "enabled",
+    "tools",
+    "flag_sets",
+    "implies",
+    "type_name",
+])
+
+def action_config(
+        action_name,
+        enabled = False,
+        tools = [],
+        flag_sets = [],
+        implies = []):
+    """ Configuration of a Bazel action.
+
+    An action config corresponds to a Bazel action, and allows selection of
+    a tool based on activated features.
+    Action config activation occurs by the same semantics as features: a
+    feature can 'require' or 'imply' an action config in the same way that it
+    would another feature.
+
+    Args:
+        action_name: The name of the Bazel action that this config applies to,
+            ex. 'c-compile' or 'c-module-compile'.
+        enabled: If 'True', this action is enabled unless a rule type
+            explicitly marks it as unsupported.
+        tools: The tool applied to the action will be the first Tool with a
+            feature set that matches the feature configuration.  An error will
+            be thrown if no tool matches a provided feature configuration - for
+            that reason, it's a good idea to provide a default tool with an
+            empty feature set.
+        flag_sets: If the given action config is enabled, the flag sets will be
+            applied to the corresponding action.
+        implies: A list of features or action configs that are automatically
+            enabled when this action config is enabled. If any of the implied
+            features or action configs cannot be enabled, this action config
+            will (silently) not be enabled either.
+
+    Returns:
+        An ActionConfigInfo provider.
+    """
+    _check_is_nonempty_string(action_name, "name", "action_config")
+    _check_right_type(enabled, True, "enabled", "action_config")
+    _check_right_type(tools, [], "tools", "action_config")
+    _check_right_type(flag_sets, [], "flag_sets", "action_config")
+    _check_right_type(implies, [], "implies", "action_config")
+    return ActionConfigInfo(
+        action_name = action_name,
+        enabled = enabled,
+        tools = tools,
+        flag_sets = flag_sets,
+        implies = implies,
+        type_name = "action_config",
+    )
+
+ArtifactNamePatternInfo = provider(fields = [
+    "category_name",
+    "prefix",
+    "extension",
+    "type_name",
+])
+
+def artifact_name_pattern(category_name, prefix, extension):
+    """ The name for an artifact of a given category of input or output artifacts to an action.
+
+    Args:
+        category_name: The category of artifacts that this selection applies
+            to. This field is compared against a list of categories defined
+            in bazel. Example categories include "linked_output" or
+            "debug_symbols". An error is thrown if no category is matched.
+        prefix: The prefix for creating the artifact for this selection.
+            Together with the extension it is used to create an artifact name
+            based on the target name.
+        extension: The extension for creating the artifact for this selection.
+            Together with the prefix it is used to create an artifact name
+            based on the target name.
+
+    Returns:
+        An ArtifactNamePatternInfo provider
+    """
+    _check_is_nonempty_string(category_name, "category_name", "artifact_name_pattern")
+    _check_is_none_or_right_type(prefix, "", "prefix", "artifact_name_pattern")
+    _check_is_none_or_right_type(extension, "", "extension", "artifact_name_pattern")
+    return ArtifactNamePatternInfo(
+        category_name = category_name,
+        prefix = prefix,
+        extension = extension,
+        type_name = "artifact_name_pattern",
+    )
diff --git a/cc/private/toolchain/clang_installation_error.bat.tpl b/cc/private/toolchain/clang_installation_error.bat.tpl
new file mode 100644
index 0000000..bec44eb
--- /dev/null
+++ b/cc/private/toolchain/clang_installation_error.bat.tpl
@@ -0,0 +1,24 @@
+:: Copyright 2019 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.
+
+@echo OFF
+
+echo. 1>&2
+echo The target you are compiling requires the Clang compiler. 1>&2
+echo Bazel couldn't find a valid Clang installation on your machine. 1>&2
+%{clang_error_message}
+echo Please check your installation following https://docs.bazel.build/versions/master/windows.html#using 1>&2
+echo. 1>&2
+
+exit /b 1
diff --git a/cc/private/toolchain/empty.cc b/cc/private/toolchain/empty.cc
new file mode 100644
index 0000000..4cda5c6
--- /dev/null
+++ b/cc/private/toolchain/empty.cc
@@ -0,0 +1,15 @@
+// Copyright 2017 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.
+
+int main() {}
diff --git a/cc/private/toolchain/empty_cc_toolchain_config.bzl b/cc/private/toolchain/empty_cc_toolchain_config.bzl
new file mode 100644
index 0000000..5d42d06
--- /dev/null
+++ b/cc/private/toolchain/empty_cc_toolchain_config.bzl
@@ -0,0 +1,42 @@
+# Copyright 2019 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.
+
+"""A fake C++ toolchain configuration rule"""
+
+def _impl(ctx):
+    out = ctx.actions.declare_file(ctx.label.name)
+    ctx.actions.write(out, "Fake executable")
+    return [
+        cc_common.create_cc_toolchain_config_info(
+            ctx = ctx,
+            toolchain_identifier = "local_linux",
+            host_system_name = "local",
+            target_system_name = "local",
+            target_cpu = "local",
+            target_libc = "local",
+            compiler = "compiler",
+            abi_version = "local",
+            abi_libc_version = "local",
+        ),
+        DefaultInfo(
+            executable = out,
+        ),
+    ]
+
+cc_toolchain_config = rule(
+    implementation = _impl,
+    attrs = {},
+    provides = [CcToolchainConfigInfo],
+    executable = True,
+)
diff --git a/cc/private/toolchain/freebsd_cc_toolchain_config.bzl b/cc/private/toolchain/freebsd_cc_toolchain_config.bzl
new file mode 100644
index 0000000..4b55cbb
--- /dev/null
+++ b/cc/private/toolchain/freebsd_cc_toolchain_config.bzl
@@ -0,0 +1,307 @@
+# Copyright 2019 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.
+
+"""A Starlark cc_toolchain configuration rule for freebsd."""
+
+load(
+    "@rules_cc//cc/private/toolchain:cc_toolchain_config_lib.bzl",
+    "action_config",
+    "feature",
+    "flag_group",
+    "flag_set",
+    "tool",
+    "tool_path",
+    "with_feature_set",
+)
+load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
+
+all_compile_actions = [
+    ACTION_NAMES.c_compile,
+    ACTION_NAMES.cpp_compile,
+    ACTION_NAMES.linkstamp_compile,
+    ACTION_NAMES.assemble,
+    ACTION_NAMES.preprocess_assemble,
+    ACTION_NAMES.cpp_header_parsing,
+    ACTION_NAMES.cpp_module_compile,
+    ACTION_NAMES.cpp_module_codegen,
+    ACTION_NAMES.clif_match,
+    ACTION_NAMES.lto_backend,
+]
+
+all_cpp_compile_actions = [
+    ACTION_NAMES.cpp_compile,
+    ACTION_NAMES.linkstamp_compile,
+    ACTION_NAMES.cpp_header_parsing,
+    ACTION_NAMES.cpp_module_compile,
+    ACTION_NAMES.cpp_module_codegen,
+    ACTION_NAMES.clif_match,
+]
+
+all_link_actions = [
+    ACTION_NAMES.cpp_link_executable,
+    ACTION_NAMES.cpp_link_dynamic_library,
+    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+]
+
+def _impl(ctx):
+    cpu = ctx.attr.cpu
+    compiler = "compiler"
+    toolchain_identifier = "local_freebsd" if cpu == "freebsd" else "stub_armeabi-v7a"
+    host_system_name = "local" if cpu == "freebsd" else "armeabi-v7a"
+    target_system_name = "local" if cpu == "freebsd" else "armeabi-v7a"
+    target_libc = "local" if cpu == "freebsd" else "armeabi-v7a"
+    abi_version = "local" if cpu == "freebsd" else "armeabi-v7a"
+    abi_libc_version = "local" if cpu == "freebsd" else "armeabi-v7a"
+
+    objcopy_embed_data_action = action_config(
+        action_name = "objcopy_embed_data",
+        enabled = True,
+        tools = [tool(path = "/usr/bin/objcopy")],
+    )
+
+    action_configs = [objcopy_embed_data_action] if cpu == "freebsd" else []
+
+    default_link_flags_feature = feature(
+        name = "default_link_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-lstdc++",
+                            "-Wl,-z,relro,-z,now",
+                            "-no-canonical-prefixes",
+                        ],
+                    ),
+                ],
+            ),
+            flag_set(
+                actions = all_link_actions,
+                flag_groups = [flag_group(flags = ["-Wl,--gc-sections"])],
+                with_features = [with_feature_set(features = ["opt"])],
+            ),
+        ],
+    )
+
+    unfiltered_compile_flags_feature = feature(
+        name = "unfiltered_compile_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-no-canonical-prefixes",
+                            "-Wno-builtin-macro-redefined",
+                            "-D__DATE__=\"redacted\"",
+                            "-D__TIMESTAMP__=\"redacted\"",
+                            "-D__TIME__=\"redacted\"",
+                        ],
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    supports_pic_feature = feature(name = "supports_pic", enabled = True)
+
+    default_compile_flags_feature = feature(
+        name = "default_compile_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-U_FORTIFY_SOURCE",
+                            "-D_FORTIFY_SOURCE=1",
+                            "-fstack-protector",
+                            "-Wall",
+                            "-fno-omit-frame-pointer",
+                        ],
+                    ),
+                ],
+            ),
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = [flag_group(flags = ["-g"])],
+                with_features = [with_feature_set(features = ["dbg"])],
+            ),
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-g0",
+                            "-O2",
+                            "-DNDEBUG",
+                            "-ffunction-sections",
+                            "-fdata-sections",
+                        ],
+                    ),
+                ],
+                with_features = [with_feature_set(features = ["opt"])],
+            ),
+            flag_set(
+                actions = all_cpp_compile_actions + [ACTION_NAMES.lto_backend],
+                flag_groups = [flag_group(flags = ["-std=c++0x"])],
+            ),
+        ],
+    )
+
+    opt_feature = feature(name = "opt")
+
+    supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True)
+
+    objcopy_embed_flags_feature = feature(
+        name = "objcopy_embed_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = ["objcopy_embed_data"],
+                flag_groups = [flag_group(flags = ["-I", "binary"])],
+            ),
+        ],
+    )
+
+    dbg_feature = feature(name = "dbg")
+
+    user_compile_flags_feature = feature(
+        name = "user_compile_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = ["%{user_compile_flags}"],
+                        iterate_over = "user_compile_flags",
+                        expand_if_available = "user_compile_flags",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    sysroot_feature = feature(
+        name = "sysroot",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.linkstamp_compile,
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.cpp_header_parsing,
+                    ACTION_NAMES.cpp_module_compile,
+                    ACTION_NAMES.cpp_module_codegen,
+                    ACTION_NAMES.clif_match,
+                    ACTION_NAMES.lto_backend,
+                ] + all_link_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = ["--sysroot=%{sysroot}"],
+                        expand_if_available = "sysroot",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    if cpu == "freebsd":
+        features = [
+            default_compile_flags_feature,
+            default_link_flags_feature,
+            supports_dynamic_linker_feature,
+            supports_pic_feature,
+            objcopy_embed_flags_feature,
+            opt_feature,
+            dbg_feature,
+            user_compile_flags_feature,
+            sysroot_feature,
+            unfiltered_compile_flags_feature,
+        ]
+    else:
+        features = [supports_dynamic_linker_feature, supports_pic_feature]
+
+    if (cpu == "freebsd"):
+        cxx_builtin_include_directories = ["/usr/lib/clang", "/usr/local/include", "/usr/include"]
+    else:
+        cxx_builtin_include_directories = []
+
+    if cpu == "freebsd":
+        tool_paths = [
+            tool_path(name = "ar", path = "/usr/bin/ar"),
+            tool_path(name = "compat-ld", path = "/usr/bin/ld"),
+            tool_path(name = "cpp", path = "/usr/bin/cpp"),
+            tool_path(name = "dwp", path = "/usr/bin/dwp"),
+            tool_path(name = "gcc", path = "/usr/bin/clang"),
+            tool_path(name = "gcov", path = "/usr/bin/gcov"),
+            tool_path(name = "ld", path = "/usr/bin/ld"),
+            tool_path(name = "nm", path = "/usr/bin/nm"),
+            tool_path(name = "objcopy", path = "/usr/bin/objcopy"),
+            tool_path(name = "objdump", path = "/usr/bin/objdump"),
+            tool_path(name = "strip", path = "/usr/bin/strip"),
+        ]
+    else:
+        tool_paths = [
+            tool_path(name = "ar", path = "/bin/false"),
+            tool_path(name = "compat-ld", path = "/bin/false"),
+            tool_path(name = "cpp", path = "/bin/false"),
+            tool_path(name = "dwp", path = "/bin/false"),
+            tool_path(name = "gcc", path = "/bin/false"),
+            tool_path(name = "gcov", path = "/bin/false"),
+            tool_path(name = "ld", path = "/bin/false"),
+            tool_path(name = "nm", path = "/bin/false"),
+            tool_path(name = "objcopy", path = "/bin/false"),
+            tool_path(name = "objdump", path = "/bin/false"),
+            tool_path(name = "strip", path = "/bin/false"),
+        ]
+
+    out = ctx.actions.declare_file(ctx.label.name)
+    ctx.actions.write(out, "Fake executable")
+    return [
+        cc_common.create_cc_toolchain_config_info(
+            ctx = ctx,
+            features = features,
+            action_configs = action_configs,
+            cxx_builtin_include_directories = cxx_builtin_include_directories,
+            toolchain_identifier = toolchain_identifier,
+            host_system_name = host_system_name,
+            target_system_name = target_system_name,
+            target_cpu = cpu,
+            target_libc = target_libc,
+            compiler = compiler,
+            abi_version = abi_version,
+            abi_libc_version = abi_libc_version,
+            tool_paths = tool_paths,
+        ),
+        DefaultInfo(
+            executable = out,
+        ),
+    ]
+
+cc_toolchain_config = rule(
+    implementation = _impl,
+    attrs = {
+        "cpu": attr.string(mandatory = True),
+    },
+    provides = [CcToolchainConfigInfo],
+    executable = True,
+)
diff --git a/cc/private/toolchain/grep-includes.sh b/cc/private/toolchain/grep-includes.sh
new file mode 100755
index 0000000..ee51361
--- /dev/null
+++ b/cc/private/toolchain/grep-includes.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Copyright 2018 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.
+#
+# TODO(bazel-team): Support include scanning and grep-includes in Bazel
+echo "grep-includes is not supported by Bazel"
+exit 1
diff --git a/cc/private/toolchain/lib_cc_configure.bzl b/cc/private/toolchain/lib_cc_configure.bzl
new file mode 100644
index 0000000..789018f
--- /dev/null
+++ b/cc/private/toolchain/lib_cc_configure.bzl
@@ -0,0 +1,219 @@
+# pylint: disable=g-bad-file-header
+# Copyright 2016 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.
+"""Base library for configuring the C++ toolchain."""
+
+def resolve_labels(repository_ctx, labels):
+    """Resolves a collection of labels to their paths.
+
+    Label resolution can cause the evaluation of Skylark functions to restart.
+    For functions with side-effects (like the auto-configuration functions, which
+    inspect the system and touch the file system), such restarts are costly.
+    We cannot avoid the restarts, but we can minimize their penalty by resolving
+    all labels upfront.
+
+    Among other things, doing less work on restarts can cut analysis times by
+    several seconds and may also prevent tickling kernel conditions that cause
+    build failures.  See https://github.com/bazelbuild/bazel/issues/5196 for
+    more details.
+
+    Args:
+      repository_ctx: The context with which to resolve the labels.
+      labels: Labels to be resolved expressed as a list of strings.
+
+    Returns:
+      A dictionary with the labels as keys and their paths as values.
+    """
+    return dict([(label, repository_ctx.path(Label(label))) for label in labels])
+
+def escape_string(arg):
+    """Escape percent sign (%) in the string so it can appear in the Crosstool."""
+    if arg != None:
+        return str(arg).replace("%", "%%")
+    else:
+        return None
+
+def split_escaped(string, delimiter):
+    """Split string on the delimiter unless %-escaped.
+
+    Examples:
+      Basic usage:
+        split_escaped("a:b:c", ":") -> [ "a", "b", "c" ]
+
+      Delimeter that is not supposed to be splitten on has to be %-escaped:
+        split_escaped("a%:b", ":") -> [ "a:b" ]
+
+      Literal % can be represented by escaping it as %%:
+        split_escaped("a%%b", ":") -> [ "a%b" ]
+
+      Consecutive delimiters produce empty strings:
+        split_escaped("a::b", ":") -> [ "a", "", "", "b" ]
+
+    Args:
+      string: The string to be split.
+      delimiter: Non-empty string not containing %-sign to be used as a
+          delimiter.
+
+    Returns:
+      A list of substrings.
+    """
+    if delimiter == "":
+        fail("Delimiter cannot be empty")
+    if delimiter.find("%") != -1:
+        fail("Delimiter cannot contain %-sign")
+
+    i = 0
+    result = []
+    accumulator = []
+    length = len(string)
+    delimiter_length = len(delimiter)
+
+    if not string:
+        return []
+
+    # Iterate over the length of string since Skylark doesn't have while loops
+    for _ in range(length):
+        if i >= length:
+            break
+        if i + 2 <= length and string[i:i + 2] == "%%":
+            accumulator.append("%")
+            i += 2
+        elif (i + 1 + delimiter_length <= length and
+              string[i:i + 1 + delimiter_length] == "%" + delimiter):
+            accumulator.append(delimiter)
+            i += 1 + delimiter_length
+        elif i + delimiter_length <= length and string[i:i + delimiter_length] == delimiter:
+            result.append("".join(accumulator))
+            accumulator = []
+            i += delimiter_length
+        else:
+            accumulator.append(string[i])
+            i += 1
+
+    # Append the last group still in accumulator
+    result.append("".join(accumulator))
+    return result
+
+def auto_configure_fail(msg):
+    """Output failure message when auto configuration fails."""
+    red = "\033[0;31m"
+    no_color = "\033[0m"
+    fail("\n%sAuto-Configuration Error:%s %s\n" % (red, no_color, msg))
+
+def auto_configure_warning(msg):
+    """Output warning message during auto configuration."""
+    yellow = "\033[1;33m"
+    no_color = "\033[0m"
+    print("\n%sAuto-Configuration Warning:%s %s\n" % (yellow, no_color, msg))
+
+def get_env_var(repository_ctx, name, default = None, enable_warning = True):
+    """Find an environment variable in system path. Doesn't %-escape the value!"""
+    if name in repository_ctx.os.environ:
+        return repository_ctx.os.environ[name]
+    if default != None:
+        if enable_warning:
+            auto_configure_warning("'%s' environment variable is not set, using '%s' as default" % (name, default))
+        return default
+    auto_configure_fail("'%s' environment variable is not set" % name)
+
+def which(repository_ctx, cmd, default = None):
+    """A wrapper around repository_ctx.which() to provide a fallback value. Doesn't %-escape the value!"""
+    result = repository_ctx.which(cmd)
+    return default if result == None else str(result)
+
+def which_cmd(repository_ctx, cmd, default = None):
+    """Find cmd in PATH using repository_ctx.which() and fail if cannot find it. Doesn't %-escape the cmd!"""
+    result = repository_ctx.which(cmd)
+    if result != None:
+        return str(result)
+    path = get_env_var(repository_ctx, "PATH")
+    if default != None:
+        auto_configure_warning("Cannot find %s in PATH, using '%s' as default.\nPATH=%s" % (cmd, default, path))
+        return default
+    auto_configure_fail("Cannot find %s in PATH, please make sure %s is installed and add its directory in PATH.\nPATH=%s" % (cmd, cmd, path))
+    return str(result)
+
+def execute(
+        repository_ctx,
+        command,
+        environment = None,
+        expect_failure = False):
+    """Execute a command, return stdout if succeed and throw an error if it fails. Doesn't %-escape the result!"""
+    if environment:
+        result = repository_ctx.execute(command, environment = environment)
+    else:
+        result = repository_ctx.execute(command)
+    if expect_failure != (result.return_code != 0):
+        if expect_failure:
+            auto_configure_fail(
+                "expected failure, command %s, stderr: (%s)" % (
+                    command,
+                    result.stderr,
+                ),
+            )
+        else:
+            auto_configure_fail(
+                "non-zero exit code: %d, command %s, stderr: (%s)" % (
+                    result.return_code,
+                    command,
+                    result.stderr,
+                ),
+            )
+    stripped_stdout = result.stdout.strip()
+    if not stripped_stdout:
+        auto_configure_fail(
+            "empty output from command %s, stderr: (%s)" % (command, result.stderr),
+        )
+    return stripped_stdout
+
+def get_cpu_value(repository_ctx):
+    """Compute the cpu_value based on the OS name. Doesn't %-escape the result!"""
+    os_name = repository_ctx.os.name.lower()
+    if os_name.startswith("mac os"):
+        return "darwin"
+    if os_name.find("freebsd") != -1:
+        return "freebsd"
+    if os_name.find("windows") != -1:
+        return "x64_windows"
+
+    # Use uname to figure out whether we are on x86_32 or x86_64
+    result = repository_ctx.execute(["uname", "-m"])
+    if result.stdout.strip() in ["power", "ppc64le", "ppc", "ppc64"]:
+        return "ppc"
+    if result.stdout.strip() in ["s390x"]:
+        return "s390x"
+    if result.stdout.strip() in ["arm", "armv7l"]:
+        return "arm"
+    if result.stdout.strip() in ["aarch64"]:
+        return "aarch64"
+    return "k8" if result.stdout.strip() in ["amd64", "x86_64", "x64"] else "piii"
+
+def is_cc_configure_debug(repository_ctx):
+    """Returns True if CC_CONFIGURE_DEBUG is set to 1."""
+    env = repository_ctx.os.environ
+    return "CC_CONFIGURE_DEBUG" in env and env["CC_CONFIGURE_DEBUG"] == "1"
+
+def build_flags(flags):
+    """Convert `flags` to a string of flag fields."""
+    return "\n".join(["        flag: '" + flag + "'" for flag in flags])
+
+def get_starlark_list(values):
+    if not values:
+        return ""
+    return "\"" + "\",\n    \"".join(values) + "\""
+
+def auto_configure_warning_maybe(repository_ctx, msg):
+    """Output warning message when CC_CONFIGURE_DEBUG is enabled."""
+    if is_cc_configure_debug(repository_ctx):
+        auto_configure_warning(msg)
diff --git a/cc/private/toolchain/link_dynamic_library.sh b/cc/private/toolchain/link_dynamic_library.sh
new file mode 100755
index 0000000..c71d498
--- /dev/null
+++ b/cc/private/toolchain/link_dynamic_library.sh
@@ -0,0 +1,113 @@
+#!/bin/bash
+#
+# Copyright 2016 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.
+
+# This script handles interface library generation for dynamic library
+# link action.
+#
+# Bazel can be configured to generate external interface library script
+# to generate interface libraries in CppLinkAction for dynamic libraries.
+# This is not needed on Windows (as the "interface" libraries are
+# generated by default). This script therefore handles the cases when
+# external script is provided, or when no script should be used.
+
+set -eu
+
+E_LINKER_COMMAND_NOT_FOUND=12
+E_INTERFACE_BUILDER_NOT_FOUND=13
+
+
+SUFFIX=".rewritten"
+
+other_args=""
+
+if [[ "$#" -eq 1 ]]; then
+  if [[ "$1" != @* ]]; then
+    echo "Parameter file must start with @" 1>&2;
+    exit "$E_LINKER_COMMAND_NOT_FOUND"
+  fi
+
+  filename=$(echo "$1" | cut -c2-)
+  first_five_lines=$(head -n 5 $filename)
+
+  # Should generate interface library switch (<yes|no>); if the value is "no",
+  # following 3 args are ignored (but must be present)
+  GENERATE_INTERFACE_LIBRARY=$(echo "$first_five_lines" | head -n1 | tail -n1)
+  # Tool which can generate interface library from dynamic library file
+  INTERFACE_LIBRARY_BUILDER=$(echo "$first_five_lines" | head -n2 | tail -n1)
+  # Dynamic library from which we want to generate interface library
+  DYNAMIC_LIBRARY=$(echo "$first_five_lines" | head -n3 | tail -n1)
+  # Resulting interface library
+  INTERFACE_LIBRARY=$(echo "$first_five_lines" | head -n4 | tail -n1)
+  # The command used to generate the dynamic library
+  LINKER_COMMAND=$(echo "$first_five_lines" | head -n5 | tail -n1)
+
+  rest_of_lines=$(tail -n +6 $filename)
+  new_param_file="${filename}${SUFFIX}"
+  echo "$rest_of_lines" > $new_param_file
+  other_args="@$new_param_file"
+
+  if [[ ! -e "$LINKER_COMMAND" ]]; then
+    echo "Linker command ($LINKER_COMMAND) not found." 1>&2;
+    exit "$E_LINKER_COMMAND_NOT_FOUND"
+  fi
+
+  if [[ "no" == "$GENERATE_INTERFACE_LIBRARY" ]]; then
+      INTERFACE_GENERATION=:
+  else
+      if [[ ! -e "$INTERFACE_LIBRARY_BUILDER" ]]; then
+        echo "Interface library builder ($INTERFACE_LIBRARY_BUILDER)
+        not found." 1>&2;
+        exit "$E_INTERFACE_BUILDER_NOT_FOUND"
+      fi
+      INTERFACE_GENERATION="${INTERFACE_LIBRARY_BUILDER} ${DYNAMIC_LIBRARY}
+      ${INTERFACE_LIBRARY}"
+  fi
+
+  ${LINKER_COMMAND} "$other_args" && ${INTERFACE_GENERATION}
+else
+  # TODO(b/113358321): Remove this branch once projects are migrated to not
+  #  splitting the linking command line.
+  # Should generate interface library switch (<yes|no>); if the value is "no",
+  # following 3 args are ignored (but must be present)
+  GENERATE_INTERFACE_LIBRARY="$1"
+  # Tool which can generate interface library from dynamic library file
+  INTERFACE_LIBRARY_BUILDER="$2"
+  # Dynamic library from which we want to generate interface library
+  DYNAMIC_LIBRARY="$3"
+  # Resulting interface library
+  INTERFACE_LIBRARY="$4"
+  # The command used to generate the dynamic library
+  LINKER_COMMAND="$5"
+  shift 5
+  if [[ ! -e "$LINKER_COMMAND" ]]; then
+    echo "Linker command ($LINKER_COMMAND) not found." 1>&2;
+    exit "$E_LINKER_COMMAND_NOT_FOUND"
+  fi
+
+  if [[ "no" == "$GENERATE_INTERFACE_LIBRARY" ]]; then
+      INTERFACE_GENERATION=:
+  else
+      if [[ ! -e "$INTERFACE_LIBRARY_BUILDER" ]]; then
+        echo "Interface library builder ($INTERFACE_LIBRARY_BUILDER)
+        not found." 1>&2;
+        exit "$E_INTERFACE_BUILDER_NOT_FOUND"
+      fi
+      INTERFACE_GENERATION="${INTERFACE_LIBRARY_BUILDER} ${DYNAMIC_LIBRARY}
+      ${INTERFACE_LIBRARY}"
+  fi
+
+  ${LINKER_COMMAND} "$@" && ${INTERFACE_GENERATION}
+fi
diff --git a/cc/private/toolchain/linux_cc_wrapper.sh.tpl b/cc/private/toolchain/linux_cc_wrapper.sh.tpl
new file mode 100644
index 0000000..a83be50
--- /dev/null
+++ b/cc/private/toolchain/linux_cc_wrapper.sh.tpl
@@ -0,0 +1,25 @@
+#!/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.
+#
+# Ship the environment to the C++ action
+#
+set -eu
+
+# Set-up the environment
+%{env}
+
+# Call the C++ compiler
+%{cc} "$@"
diff --git a/cc/private/toolchain/msys_gcc_installation_error.bat b/cc/private/toolchain/msys_gcc_installation_error.bat
new file mode 100644
index 0000000..25c3553
--- /dev/null
+++ b/cc/private/toolchain/msys_gcc_installation_error.bat
@@ -0,0 +1,23 @@
+:: Copyright 2018 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.
+
+@echo OFF
+
+echo. 1>&2
+echo The target you are compiling requires MSYS gcc / MINGW gcc. 1>&2
+echo Bazel couldn't find gcc installation on your machine. 1>&2
+echo Please install MSYS gcc / MINGW gcc and set BAZEL_SH environment variable 1>&2
+echo. 1>&2
+
+exit /b 1
diff --git a/cc/private/toolchain/osx_cc_configure.bzl b/cc/private/toolchain/osx_cc_configure.bzl
new file mode 100644
index 0000000..e40b4e4
--- /dev/null
+++ b/cc/private/toolchain/osx_cc_configure.bzl
@@ -0,0 +1,148 @@
+# pylint: disable=g-bad-file-header
+# Copyright 2016 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.
+"""Configuring the C++ toolchain on macOS."""
+
+load("@bazel_tools//tools/osx:xcode_configure.bzl", "run_xcode_locator")
+load(
+    "@rules_cc//cc/private/toolchain:lib_cc_configure.bzl",
+    "escape_string",
+    "resolve_labels",
+)
+load(
+    "@rules_cc//cc/private/toolchain:unix_cc_configure.bzl",
+    "configure_unix_toolchain",
+    "find_cc",
+    "get_env",
+    "get_escaped_cxx_inc_directories",
+)
+
+def _get_escaped_xcode_cxx_inc_directories(repository_ctx, cc, xcode_toolchains):
+    """Compute the list of default C++ include paths on Xcode-enabled darwin.
+
+    Args:
+      repository_ctx: The repository context.
+      cc: The default C++ compiler on the local system.
+      xcode_toolchains: A list containing the xcode toolchains available
+    Returns:
+      include_paths: A list of builtin include paths.
+    """
+
+    # TODO(cparsons): Falling back to the default C++ compiler builtin include
+    # paths shouldn't be unnecessary once all actions are using xcrun.
+    include_dirs = get_escaped_cxx_inc_directories(repository_ctx, cc, "-xc++")
+    for toolchain in xcode_toolchains:
+        include_dirs.append(escape_string(toolchain.developer_dir))
+
+    # Assume that all paths that point to /Applications/ are built in include paths
+    include_dirs.append("/Applications/")
+    return include_dirs
+
+def configure_osx_toolchain(repository_ctx, overriden_tools):
+    """Configure C++ toolchain on macOS."""
+    paths = resolve_labels(repository_ctx, [
+        "@rules_cc//cc/private/toolchain:osx_cc_wrapper.sh.tpl",
+        "@bazel_tools//tools/objc:libtool.sh",
+        "@bazel_tools//tools/objc:make_hashed_objlist.py",
+        "@bazel_tools//tools/objc:xcrunwrapper.sh",
+        "@bazel_tools//tools/osx/crosstool:BUILD.tpl",
+        "@bazel_tools//tools/osx/crosstool:cc_toolchain_config.bzl",
+        "@bazel_tools//tools/osx/crosstool:wrapped_ar.tpl",
+        "@bazel_tools//tools/osx/crosstool:wrapped_clang.cc",
+        "@bazel_tools//tools/osx:xcode_locator.m",
+    ])
+
+    env = repository_ctx.os.environ
+    should_use_xcode = "BAZEL_USE_XCODE_TOOLCHAIN" in env and env["BAZEL_USE_XCODE_TOOLCHAIN"] == "1"
+    xcode_toolchains = []
+
+    # Make the following logic in sync with @rules_cc//cc/private/toolchain:cc_configure.bzl#cc_autoconf_toolchains_impl
+    (xcode_toolchains, xcodeloc_err) = run_xcode_locator(
+        repository_ctx,
+        paths["@bazel_tools//tools/osx:xcode_locator.m"],
+    )
+    if should_use_xcode and not xcode_toolchains:
+        fail("BAZEL_USE_XCODE_TOOLCHAIN is set to 1 but Bazel couldn't find Xcode installed on the " +
+             "system. Verify that 'xcode-select -p' is correct.")
+    if xcode_toolchains:
+        cc = find_cc(repository_ctx, overriden_tools = {})
+        repository_ctx.template(
+            "cc_wrapper.sh",
+            paths["@rules_cc//cc/private/toolchain:osx_cc_wrapper.sh.tpl"],
+            {
+                "%{cc}": escape_string(str(cc)),
+                "%{env}": escape_string(get_env(repository_ctx)),
+            },
+        )
+        repository_ctx.symlink(
+            paths["@bazel_tools//tools/objc:xcrunwrapper.sh"],
+            "xcrunwrapper.sh",
+        )
+        repository_ctx.symlink(
+            paths["@bazel_tools//tools/objc:libtool.sh"],
+            "libtool",
+        )
+        repository_ctx.symlink(
+            paths["@bazel_tools//tools/objc:make_hashed_objlist.py"],
+            "make_hashed_objlist.py",
+        )
+        repository_ctx.symlink(
+            paths["@bazel_tools//tools/osx/crosstool:wrapped_ar.tpl"],
+            "wrapped_ar",
+        )
+        repository_ctx.symlink(
+            paths["@bazel_tools//tools/osx/crosstool:cc_toolchain_config.bzl"],
+            "cc_toolchain_config.bzl",
+        )
+        wrapped_clang_src_path = str(repository_ctx.path(
+            paths["@bazel_tools//tools/osx/crosstool:wrapped_clang.cc"],
+        ))
+        xcrun_result = repository_ctx.execute([
+            "env",
+            "-i",
+            "xcrun",
+            "clang",
+            "-std=c++11",
+            "-lc++",
+            "-o",
+            "wrapped_clang",
+            wrapped_clang_src_path,
+        ], 30)
+        if (xcrun_result.return_code == 0):
+            repository_ctx.symlink("wrapped_clang", "wrapped_clang_pp")
+        else:
+            error_msg = (
+                "return code {code}, stderr: {err}, stdout: {out}"
+            ).format(
+                code = xcrun_result.return_code,
+                err = xcrun_result.stderr,
+                out = xcrun_result.stdout,
+            )
+            fail("wrapped_clang failed to generate. Please file an issue at " +
+                 "https://github.com/bazelbuild/bazel/issues with the following:\n" +
+                 error_msg)
+
+        escaped_include_paths = _get_escaped_xcode_cxx_inc_directories(repository_ctx, cc, xcode_toolchains)
+        escaped_cxx_include_directories = []
+        for path in escaped_include_paths:
+            escaped_cxx_include_directories.append(("        \"%s\"," % path))
+        if xcodeloc_err:
+            escaped_cxx_include_directories.append("# Error: " + xcodeloc_err + "\n")
+        repository_ctx.template(
+            "BUILD",
+            paths["@bazel_tools//tools/osx/crosstool:BUILD.tpl"],
+            {"%{cxx_builtin_include_directories}": "\n".join(escaped_cxx_include_directories)},
+        )
+    else:
+        configure_unix_toolchain(repository_ctx, cpu_value = "darwin", overriden_tools = overriden_tools)
diff --git a/cc/private/toolchain/osx_cc_wrapper.sh b/cc/private/toolchain/osx_cc_wrapper.sh
new file mode 100755
index 0000000..207bcef
--- /dev/null
+++ b/cc/private/toolchain/osx_cc_wrapper.sh
@@ -0,0 +1,104 @@
+#!/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
+
+GCC=/usr/bin/gcc
+INSTALL_NAME_TOOL="/usr/bin/install_name_tool"
+
+LIBS=
+LIB_DIRS=
+RPATHS=
+OUTPUT=
+# let parse the option list
+for i in "$@"; do
+    if [[ "${OUTPUT}" = "1" ]]; then
+        OUTPUT=$i
+    elif [[ "$i" =~ ^-l(.*)$ ]]; then
+        LIBS="${BASH_REMATCH[1]} $LIBS"
+    elif [[ "$i" =~ ^-L(.*)$ ]]; then
+        LIB_DIRS="${BASH_REMATCH[1]} $LIB_DIRS"
+    elif [[ "$i" =~ ^-Wl,-rpath,\@loader_path/(.*)$ ]]; then
+        RPATHS="${BASH_REMATCH[1]} ${RPATHS}"
+    elif [[ "$i" = "-o" ]]; then
+        # output is coming
+        OUTPUT=1
+    fi
+done
+
+# Call gcc
+${GCC} "$@"
+
+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/cc/private/toolchain/osx_cc_wrapper.sh.tpl b/cc/private/toolchain/osx_cc_wrapper.sh.tpl
new file mode 100644
index 0000000..4c85cd9
--- /dev/null
+++ b/cc/private/toolchain/osx_cc_wrapper.sh.tpl
@@ -0,0 +1,106 @@
+#!/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=
+# let parse the option list
+for i in "$@"; do
+    if [[ "${OUTPUT}" = "1" ]]; then
+        OUTPUT=$i
+    elif [[ "$i" =~ ^-l(.*)$ ]]; then
+        LIBS="${BASH_REMATCH[1]} $LIBS"
+    elif [[ "$i" =~ ^-L(.*)$ ]]; then
+        LIB_DIRS="${BASH_REMATCH[1]} $LIB_DIRS"
+    elif [[ "$i" =~ ^-Wl,-rpath,\@loader_path/(.*)$ ]]; then
+        RPATHS="${BASH_REMATCH[1]} ${RPATHS}"
+    elif [[ "$i" = "-o" ]]; then
+        # output is coming
+        OUTPUT=1
+    fi
+done
+
+# Set-up the environment
+%{env}
+
+# Call the C++ compiler
+%{cc} "$@"
+
+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/cc/private/toolchain/runfiles/BUILD b/cc/private/toolchain/runfiles/BUILD
new file mode 100644
index 0000000..cb4a9d5
--- /dev/null
+++ b/cc/private/toolchain/runfiles/BUILD
@@ -0,0 +1,84 @@
+package(default_visibility = ["//visibility:private"])
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+
+filegroup(
+    name = "srcs",
+    srcs = glob(
+        ["**"],
+        exclude = [
+            ".*",
+            "*~",
+        ],
+    ),
+    visibility = ["//cc/private/toolchain:__pkg__"],
+)
+
+filegroup(
+    name = "embedded_tools",
+    srcs = [
+        "BUILD.tools",
+        ":srcs_for_embedded_tools",
+    ],
+    visibility = ["//cc/private/toolchain:__pkg__"],
+)
+
+# Rewrite the include path for runfiles.h in runfiles_src.cc, and create
+# "generated_runfiles.{h,cc}". These files are renamed to "runfiles.{h,cc}" as
+# part of creating the embedded tools of Bazel.
+#
+# We cannot just check in runfiles_src.{h,cc} as runfiles.{h,cc}, because it'd
+# cause a header check failure on Windows when building targets in the Bazel
+# source tree, if those targets depend on @rules_cc//cc/private/toolchain/runfiles,
+# because due to lack of sandboxing they would accidentally pick up runfiles.h
+# from @rules_cc//cc/private/toolchain/runfiles.
+genrule(
+    name = "srcs_for_embedded_tools",
+    srcs = [
+        "runfiles_src.cc",
+        "runfiles_src.h",
+    ],
+    outs = [
+        "generated_runfiles.cc",
+        "generated_runfiles.h",
+    ],
+    # Keep this transformation logic in sync with the
+    # //scripts/bootstrap/compile.sh
+    cmd = ("sed " +
+           "  's|^#include.*/runfiles_src.h.*|#include \"tools/cpp/runfiles/runfiles.h\"|' " +
+           "  $(location runfiles_src.cc) > $(location generated_runfiles.cc) && " +
+           "cp $(location runfiles_src.h) $(location generated_runfiles.h)"),
+)
+
+cc_library(
+    name = "runfiles",
+    testonly = 1,
+    srcs = ["runfiles_src.cc"],
+    hdrs = ["runfiles_src.h"],
+)
+
+cc_test(
+    name = "runfiles_test",
+    srcs = ["runfiles_test.cc"],
+    visibility = ["//visibility:public"],
+    deps = [
+        ":runfiles",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+test_suite(
+    name = "windows_tests",
+    tags = [
+        "-no_windows",
+        "-slow",
+    ],
+)
+
+test_suite(
+    name = "all_windows_tests",
+    tests = [
+        ":windows_tests",
+    ],
+    visibility = ["//tools:__pkg__"],
+)
diff --git a/cc/private/toolchain/runfiles/BUILD.tools b/cc/private/toolchain/runfiles/BUILD.tools
new file mode 100644
index 0000000..ef9518c
--- /dev/null
+++ b/cc/private/toolchain/runfiles/BUILD.tools
@@ -0,0 +1,8 @@
+# This package will host the C++ runfiles library when it's finally released.
+
+cc_library(
+    name = "runfiles",
+    srcs = ["runfiles.cc"],
+    hdrs = ["runfiles.h"],
+    visibility = ["//visibility:public"],
+)
diff --git a/cc/private/toolchain/runfiles/runfiles_src.cc b/cc/private/toolchain/runfiles/runfiles_src.cc
new file mode 100644
index 0000000..e1fb7f4
--- /dev/null
+++ b/cc/private/toolchain/runfiles/runfiles_src.cc
@@ -0,0 +1,318 @@
+// Copyright 2018 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.
+
+// The "srcs_for_embedded_tools" rule in the same package sets the line below to
+// include runfiles.h from the correct path. Do not modify the line below.
+#include "cc/private/toolchain/runfiles/runfiles_src.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else  // not _WIN32
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif  // _WIN32
+
+#include <fstream>
+#include <functional>
+#include <map>
+#include <sstream>
+#include <vector>
+
+#ifdef _WIN32
+#include <memory>
+#endif  // _WIN32
+
+namespace bazel {
+namespace tools {
+namespace cpp {
+namespace runfiles {
+
+using std::function;
+using std::map;
+using std::pair;
+using std::string;
+using std::vector;
+
+namespace {
+
+bool starts_with(const string& s, const char* prefix) {
+  if (!prefix || !*prefix) {
+    return true;
+  }
+  if (s.empty()) {
+    return false;
+  }
+  return s.find(prefix) == 0;
+}
+
+bool contains(const string& s, const char* substr) {
+  if (!substr || !*substr) {
+    return true;
+  }
+  if (s.empty()) {
+    return false;
+  }
+  return s.find(substr) != string::npos;
+}
+
+bool ends_with(const string& s, const string& suffix) {
+  if (suffix.empty()) {
+    return true;
+  }
+  if (s.empty()) {
+    return false;
+  }
+  return s.rfind(suffix) == s.size() - suffix.size();
+}
+
+bool IsReadableFile(const string& path) {
+  return std::ifstream(path).is_open();
+}
+
+bool IsDirectory(const string& path) {
+#ifdef _WIN32
+  DWORD attrs = GetFileAttributesA(path.c_str());
+  return (attrs != INVALID_FILE_ATTRIBUTES) &&
+         (attrs & FILE_ATTRIBUTE_DIRECTORY);
+#else
+  struct stat buf;
+  return stat(path.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode);
+#endif
+}
+
+bool PathsFrom(const std::string& argv0, std::string runfiles_manifest_file,
+               std::string runfiles_dir, std::string* out_manifest,
+               std::string* out_directory);
+
+bool PathsFrom(const std::string& argv0, std::string runfiles_manifest_file,
+               std::string runfiles_dir,
+               std::function<bool(const std::string&)> is_runfiles_manifest,
+               std::function<bool(const std::string&)> is_runfiles_directory,
+               std::string* out_manifest, std::string* out_directory);
+
+bool ParseManifest(const string& path, map<string, string>* result,
+                   string* error);
+
+}  // namespace
+
+Runfiles* Runfiles::Create(const string& argv0,
+                           const string& runfiles_manifest_file,
+                           const string& runfiles_dir, string* error) {
+  string manifest, directory;
+  if (!PathsFrom(argv0, runfiles_manifest_file, runfiles_dir, &manifest,
+                 &directory)) {
+    if (error) {
+      std::ostringstream err;
+      err << "ERROR: " << __FILE__ << "(" << __LINE__
+          << "): cannot find runfiles (argv0=\"" << argv0 << "\")";
+      *error = err.str();
+    }
+    return nullptr;
+  }
+
+  const vector<pair<string, string> > envvars = {
+      {"RUNFILES_MANIFEST_FILE", manifest},
+      {"RUNFILES_DIR", directory},
+      // TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can
+      // pick up RUNFILES_DIR.
+      {"JAVA_RUNFILES", directory}};
+
+  map<string, string> runfiles;
+  if (!manifest.empty()) {
+    if (!ParseManifest(manifest, &runfiles, error)) {
+      return nullptr;
+    }
+  }
+
+  return new Runfiles(std::move(runfiles), std::move(directory),
+                      std::move(envvars));
+}
+
+bool IsAbsolute(const string& path) {
+  if (path.empty()) {
+    return false;
+  }
+  char c = path.front();
+  return (c == '/' && (path.size() < 2 || path[1] != '/')) ||
+         (path.size() >= 3 &&
+          ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) &&
+          path[1] == ':' && (path[2] == '\\' || path[2] == '/'));
+}
+
+string GetEnv(const string& key) {
+#ifdef _WIN32
+  DWORD size = ::GetEnvironmentVariableA(key.c_str(), NULL, 0);
+  if (size == 0) {
+    return string();  // unset or empty envvar
+  }
+  std::unique_ptr<char[]> value(new char[size]);
+  ::GetEnvironmentVariableA(key.c_str(), value.get(), size);
+  return value.get();
+#else
+  char* result = getenv(key.c_str());
+  return (result == NULL) ? string() : string(result);
+#endif
+}
+
+string Runfiles::Rlocation(const string& path) const {
+  if (path.empty() || starts_with(path, "../") || contains(path, "/..") ||
+      starts_with(path, "./") || contains(path, "/./") ||
+      ends_with(path, "/.") || contains(path, "//")) {
+    return string();
+  }
+  if (IsAbsolute(path)) {
+    return path;
+  }
+  const auto value = runfiles_map_.find(path);
+  if (value != runfiles_map_.end()) {
+    return value->second;
+  }
+  if (!directory_.empty()) {
+    return directory_ + "/" + path;
+  }
+  return "";
+}
+
+namespace {
+
+bool ParseManifest(const string& path, map<string, string>* result,
+                   string* error) {
+  std::ifstream stm(path);
+  if (!stm.is_open()) {
+    if (error) {
+      std::ostringstream err;
+      err << "ERROR: " << __FILE__ << "(" << __LINE__
+          << "): cannot open runfiles manifest \"" << path << "\"";
+      *error = err.str();
+    }
+    return false;
+  }
+  string line;
+  std::getline(stm, line);
+  size_t line_count = 1;
+  while (!line.empty()) {
+    string::size_type idx = line.find_first_of(' ');
+    if (idx == string::npos) {
+      if (error) {
+        std::ostringstream err;
+        err << "ERROR: " << __FILE__ << "(" << __LINE__
+            << "): bad runfiles manifest entry in \"" << path << "\" line #"
+            << line_count << ": \"" << line << "\"";
+        *error = err.str();
+      }
+      return false;
+    }
+    (*result)[line.substr(0, idx)] = line.substr(idx + 1);
+    std::getline(stm, line);
+    ++line_count;
+  }
+  return true;
+}
+
+}  // namespace
+
+namespace testing {
+
+bool TestOnly_PathsFrom(const string& argv0, string mf, string dir,
+                        function<bool(const string&)> is_runfiles_manifest,
+                        function<bool(const string&)> is_runfiles_directory,
+                        string* out_manifest, string* out_directory) {
+  return PathsFrom(argv0, mf, dir, is_runfiles_manifest, is_runfiles_directory,
+                   out_manifest, out_directory);
+}
+
+bool TestOnly_IsAbsolute(const string& path) { return IsAbsolute(path); }
+
+}  // namespace testing
+
+Runfiles* Runfiles::Create(const string& argv0, string* error) {
+  return Runfiles::Create(argv0, GetEnv("RUNFILES_MANIFEST_FILE"),
+                          GetEnv("RUNFILES_DIR"), error);
+}
+
+Runfiles* Runfiles::CreateForTest(std::string* error) {
+  return Runfiles::Create(std::string(), GetEnv("RUNFILES_MANIFEST_FILE"),
+                          GetEnv("TEST_SRCDIR"), error);
+}
+
+namespace {
+
+bool PathsFrom(const string& argv0, string mf, string dir, string* out_manifest,
+               string* out_directory) {
+  return PathsFrom(
+      argv0, mf, dir, [](const string& path) { return IsReadableFile(path); },
+      [](const string& path) { return IsDirectory(path); }, out_manifest,
+      out_directory);
+}
+
+bool PathsFrom(const string& argv0, string mf, string dir,
+               function<bool(const string&)> is_runfiles_manifest,
+               function<bool(const string&)> is_runfiles_directory,
+               string* out_manifest, string* out_directory) {
+  out_manifest->clear();
+  out_directory->clear();
+
+  bool mfValid = is_runfiles_manifest(mf);
+  bool dirValid = is_runfiles_directory(dir);
+
+  if (!argv0.empty() && !mfValid && !dirValid) {
+    mf = argv0 + ".runfiles/MANIFEST";
+    dir = argv0 + ".runfiles";
+    mfValid = is_runfiles_manifest(mf);
+    dirValid = is_runfiles_directory(dir);
+    if (!mfValid) {
+      mf = argv0 + ".runfiles_manifest";
+      mfValid = is_runfiles_manifest(mf);
+    }
+  }
+
+  if (!mfValid && !dirValid) {
+    return false;
+  }
+
+  if (!mfValid) {
+    mf = dir + "/MANIFEST";
+    mfValid = is_runfiles_manifest(mf);
+    if (!mfValid) {
+      mf = dir + "_manifest";
+      mfValid = is_runfiles_manifest(mf);
+    }
+  }
+
+  if (!dirValid &&
+      (ends_with(mf, ".runfiles_manifest") || ends_with(mf, "/MANIFEST"))) {
+    static const size_t kSubstrLen = 9;  // "_manifest" or "/MANIFEST"
+    dir = mf.substr(0, mf.size() - kSubstrLen);
+    dirValid = is_runfiles_directory(dir);
+  }
+
+  if (mfValid) {
+    *out_manifest = mf;
+  }
+
+  if (dirValid) {
+    *out_directory = dir;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+}  // namespace runfiles
+}  // namespace cpp
+}  // namespace tools
+}  // namespace bazel
diff --git a/cc/private/toolchain/runfiles/runfiles_src.h b/cc/private/toolchain/runfiles/runfiles_src.h
new file mode 100644
index 0000000..b6e6178
--- /dev/null
+++ b/cc/private/toolchain/runfiles/runfiles_src.h
@@ -0,0 +1,222 @@
+// Copyright 2018 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.
+
+// Runfiles lookup library for Bazel-built C++ binaries and tests.
+//
+// USAGE:
+// 1.  Depend on this runfiles library from your build rule:
+//
+//       cc_binary(
+//           name = "my_binary",
+//           ...
+//           deps = ["@rules_cc//cc/private/toolchain/runfiles"],
+//       )
+//
+// 2.  Include the runfiles library.
+//
+//       #include "tools/cpp/runfiles/runfiles.h"
+//
+//       using bazel::tools::cpp::runfiles::Runfiles;
+//
+// 3.  Create a Runfiles object and use rlocation to look up runfile paths:
+//
+//       int main(int argc, char** argv) {
+//         std::string error;
+//         std::unique_ptr<Runfiles> runfiles(
+//             Runfiles::Create(argv[0], &error));
+//
+//         // Important:
+//         //   If this is a test, use Runfiles::CreateForTest(&error).
+//         //   Otherwise, if you don't have the value for argv[0] for whatever
+//         //   reason, then use Runfiles::Create(&error).
+//
+//         if (runfiles == nullptr) {
+//           ...  // error handling
+//         }
+//         std::string path =
+//             runfiles->Rlocation("my_workspace/path/to/my/data.txt");
+//         ...
+//
+//      The code above creates a Runfiles object and retrieves a runfile path.
+//
+//      The Runfiles::Create function uses the runfiles manifest and the
+//      runfiles directory from the RUNFILES_MANIFEST_FILE and RUNFILES_DIR
+//      environment variables. If not present, the function looks for the
+//      manifest and directory near argv[0], the path of the main program.
+//
+// To start child processes that also need runfiles, you need to set the right
+// environment variables for them:
+//
+//   std::unique_ptr<Runfiles> runfiles(Runfiles::Create(argv[0], &error));
+//
+//   std::string path = runfiles->Rlocation("path/to/binary"));
+//   if (!path.empty()) {
+//     ... // create "args" argument vector for execv
+//     const auto envvars = runfiles->EnvVars();
+//     pid_t child = fork();
+//     if (child) {
+//       int status;
+//       waitpid(child, &status, 0);
+//     } else {
+//       for (const auto i : envvars) {
+//         setenv(i.first.c_str(), i.second.c_str(), 1);
+//       }
+//       execv(args[0], args);
+//     }
+
+#ifndef TOOLS_CPP_RUNFILES_RUNFILES_H_
+#define TOOLS_CPP_RUNFILES_RUNFILES_H_ 1
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace bazel {
+namespace tools {
+namespace cpp {
+namespace runfiles {
+
+class Runfiles {
+ public:
+  virtual ~Runfiles() {}
+
+  // Returns a new `Runfiles` instance.
+  //
+  // Use this from within `cc_test` rules.
+  //
+  // Returns nullptr on error. If `error` is provided, the method prints an
+  // error message into it.
+  //
+  // This method looks at the RUNFILES_MANIFEST_FILE and TEST_SRCDIR
+  // environment variables.
+  static Runfiles* CreateForTest(std::string* error = nullptr);
+
+  // Returns a new `Runfiles` instance.
+  //
+  // Use this from `cc_binary` or `cc_library` rules. You may pass an empty
+  // `argv0` if `argv[0]` from the `main` method is unknown.
+  //
+  // Returns nullptr on error. If `error` is provided, the method prints an
+  // error message into it.
+  //
+  // This method looks at the RUNFILES_MANIFEST_FILE and RUNFILES_DIR
+  // environment variables. If either is empty, the method looks for the
+  // manifest or directory using the other environment variable, or using argv0
+  // (unless it's empty).
+  static Runfiles* Create(const std::string& argv0,
+                          std::string* error = nullptr);
+
+  // Returns a new `Runfiles` instance.
+  //
+  // Use this from any `cc_*` rule if you want to manually specify the paths to
+  // the runfiles manifest and/or runfiles directory. You may pass an empty
+  // `argv0` if `argv[0]` from the `main` method is unknown.
+  //
+  // This method is the same as `Create(argv0, error)`, except it uses
+  // `runfiles_manifest_file` and `runfiles_dir` as the corresponding
+  // environment variable values, instead of looking up the actual environment
+  // variables.
+  static Runfiles* Create(const std::string& argv0,
+                          const std::string& runfiles_manifest_file,
+                          const std::string& runfiles_dir,
+                          std::string* error = nullptr);
+
+  // Returns the runtime path of a runfile.
+  //
+  // Runfiles are data-dependencies of Bazel-built binaries and tests.
+  //
+  // The returned path may not exist. The caller should verify the path's
+  // existence.
+  //
+  // The function may return an empty string if it cannot find a runfile.
+  //
+  // Args:
+  //   path: runfiles-root-relative path of the runfile; must not be empty and
+  //     must not contain uplevel references.
+  // Returns:
+  //   the path to the runfile, which the caller should check for existence, or
+  //   an empty string if the method doesn't know about this runfile
+  std::string Rlocation(const std::string& path) const;
+
+  // Returns environment variables for subprocesses.
+  //
+  // The caller should set the returned key-value pairs in the environment of
+  // subprocesses, so that those subprocesses can also access runfiles (in case
+  // they are also Bazel-built binaries).
+  const std::vector<std::pair<std::string, std::string> >& EnvVars() const {
+    return envvars_;
+  }
+
+ private:
+  Runfiles(const std::map<std::string, std::string>&& runfiles_map,
+           const std::string&& directory,
+           const std::vector<std::pair<std::string, std::string> >&& envvars)
+      : runfiles_map_(std::move(runfiles_map)),
+        directory_(std::move(directory)),
+        envvars_(std::move(envvars)) {}
+  Runfiles(const Runfiles&) = delete;
+  Runfiles(Runfiles&&) = delete;
+  Runfiles& operator=(const Runfiles&) = delete;
+  Runfiles& operator=(Runfiles&&) = delete;
+
+  const std::map<std::string, std::string> runfiles_map_;
+  const std::string directory_;
+  const std::vector<std::pair<std::string, std::string> > envvars_;
+};
+
+// The "testing" namespace contains functions that allow unit testing the code.
+// Do not use these outside of runfiles_test.cc, they are only part of the
+// public API for the benefit of the tests.
+// These functions and their interface may change without notice.
+namespace testing {
+
+// For testing only.
+//
+// Computes the path of the runfiles manifest and the runfiles directory.
+//
+// If the method finds both a valid manifest and valid directory according to
+// `is_runfiles_manifest` and `is_runfiles_directory`, then the method sets
+// the corresponding values to `out_manifest` and `out_directory` and returns
+// true.
+//
+// If the method only finds a valid manifest or a valid directory, but not
+// both, then it sets the corresponding output variable (`out_manifest` or
+// `out_directory`) to the value while clearing the other output variable. The
+// method still returns true in this case.
+//
+// If the method cannot find either a valid manifest or valid directory, it
+// clears both output variables and returns false.
+bool TestOnly_PathsFrom(
+    const std::string& argv0, std::string runfiles_manifest_file,
+    std::string runfiles_dir,
+    std::function<bool(const std::string&)> is_runfiles_manifest,
+    std::function<bool(const std::string&)> is_runfiles_directory,
+    std::string* out_manifest, std::string* out_directory);
+
+// For testing only.
+// Returns true if `path` is an absolute Unix or Windows path.
+// For Windows paths, this function does not regard drive-less absolute paths
+// (i.e. absolute-on-current-drive, e.g. "\foo\bar") as absolute and returns
+// false for these.
+bool TestOnly_IsAbsolute(const std::string& path);
+
+}  // namespace testing
+}  // namespace runfiles
+}  // namespace cpp
+}  // namespace tools
+}  // namespace bazel
+
+#endif  // TOOLS_CPP_RUNFILES_RUNFILES_H_
diff --git a/cc/private/toolchain/runfiles/runfiles_test.cc b/cc/private/toolchain/runfiles/runfiles_test.cc
new file mode 100644
index 0000000..36ef21f
--- /dev/null
+++ b/cc/private/toolchain/runfiles/runfiles_test.cc
@@ -0,0 +1,582 @@
+// Copyright 2018 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.
+
+#include "cc/private/toolchain/runfiles/runfiles_src.h"
+#ifdef _WIN32
+#include <windows.h>
+#endif  // _WIN32
+
+#include <fstream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+#define RUNFILES_TEST_TOSTRING_HELPER(x) #x
+#define RUNFILES_TEST_TOSTRING(x) RUNFILES_TEST_TOSTRING_HELPER(x)
+#define LINE_AS_STRING() RUNFILES_TEST_TOSTRING(__LINE__)
+
+namespace bazel {
+namespace tools {
+namespace cpp {
+namespace runfiles {
+namespace {
+
+using bazel::tools::cpp::runfiles::testing::TestOnly_IsAbsolute;
+using bazel::tools::cpp::runfiles::testing::TestOnly_PathsFrom;
+using std::cerr;
+using std::endl;
+using std::function;
+using std::pair;
+using std::string;
+using std::unique_ptr;
+using std::vector;
+
+class RunfilesTest : public ::testing::Test {
+ protected:
+  // Create a temporary file that is deleted with the destructor.
+  class MockFile {
+   public:
+    // Create an empty file with the given name under $TEST_TMPDIR.
+    static MockFile* Create(const string& name);
+
+    // Create a file with the given name and contents under $TEST_TMPDIR.
+    // The method ensures to create all parent directories, so `name` is allowed
+    // to contain directory components.
+    static MockFile* Create(const string& name, const vector<string>& lines);
+
+    ~MockFile();
+    const string& Path() const { return path_; }
+
+    string DirName() const {
+      string::size_type pos = path_.find_last_of('/');
+      return pos == string::npos ? "" : path_.substr(0, pos);
+    }
+
+   private:
+    MockFile(const string& path) : path_(path) {}
+    MockFile(const MockFile&) = delete;
+    MockFile(MockFile&&) = delete;
+    MockFile& operator=(const MockFile&) = delete;
+    MockFile& operator=(MockFile&&) = delete;
+
+    const string path_;
+  };
+
+  void AssertEnvvars(const Runfiles& runfiles,
+                     const string& expected_manifest_file,
+                     const string& expected_directory);
+
+  static string GetTemp();
+};
+
+void RunfilesTest::AssertEnvvars(const Runfiles& runfiles,
+                                 const string& expected_manifest_file,
+                                 const string& expected_directory) {
+  vector<pair<string, string> > expected = {
+      {"RUNFILES_MANIFEST_FILE", expected_manifest_file},
+      {"RUNFILES_DIR", expected_directory},
+      {"JAVA_RUNFILES", expected_directory}};
+  ASSERT_EQ(runfiles.EnvVars(), expected);
+}
+
+string RunfilesTest::GetTemp() {
+#ifdef _WIN32
+  DWORD size = ::GetEnvironmentVariableA("TEST_TMPDIR", NULL, 0);
+  if (size == 0) {
+    return string();  // unset or empty envvar
+  }
+  unique_ptr<char[]> value(new char[size]);
+  ::GetEnvironmentVariableA("TEST_TMPDIR", value.get(), size);
+  return value.get();
+#else
+  char* result = getenv("TEST_TMPDIR");
+  return result != NULL ? string(result) : string();
+#endif
+}
+
+RunfilesTest::MockFile* RunfilesTest::MockFile::Create(const string& name) {
+  return Create(name, vector<string>());
+}
+
+RunfilesTest::MockFile* RunfilesTest::MockFile::Create(
+    const string& name, const vector<string>& lines) {
+  if (name.find("..") != string::npos || TestOnly_IsAbsolute(name)) {
+    cerr << "WARNING: " << __FILE__ << "(" << __LINE__ << "): bad name: \""
+         << name << "\"" << endl;
+    return nullptr;
+  }
+
+  string tmp(RunfilesTest::GetTemp());
+  if (tmp.empty()) {
+    cerr << "WARNING: " << __FILE__ << "(" << __LINE__
+         << "): $TEST_TMPDIR is empty" << endl;
+    return nullptr;
+  }
+  string path(tmp + "/" + name);
+
+  string::size_type i = 0;
+#ifdef _WIN32
+  while ((i = name.find_first_of("/\\", i + 1)) != string::npos) {
+    string d = tmp + "\\" + name.substr(0, i);
+    if (!CreateDirectoryA(d.c_str(), NULL)) {
+      cerr << "ERROR: " << __FILE__ << "(" << __LINE__
+           << "): failed to create directory \"" << d << "\"" << endl;
+      return nullptr;
+    }
+  }
+#else
+  while ((i = name.find_first_of('/', i + 1)) != string::npos) {
+    string d = tmp + "/" + name.substr(0, i);
+    if (mkdir(d.c_str(), 0777)) {
+      cerr << "ERROR: " << __FILE__ << "(" << __LINE__
+           << "): failed to create directory \"" << d << "\"" << endl;
+      return nullptr;
+    }
+  }
+#endif
+
+  std::ofstream stm(path);
+  for (auto i : lines) {
+    stm << i << std::endl;
+  }
+  return new MockFile(path);
+}
+
+RunfilesTest::MockFile::~MockFile() { std::remove(path_.c_str()); }
+
+TEST_F(RunfilesTest, CreatesManifestBasedRunfilesFromManifestNextToBinary) {
+  unique_ptr<MockFile> mf(MockFile::Create(
+      "foo" LINE_AS_STRING() ".runfiles_manifest", {"a/b c/d"}));
+  EXPECT_TRUE(mf != nullptr);
+  string argv0(mf->Path().substr(
+      0, mf->Path().size() - string(".runfiles_manifest").size()));
+
+  string error;
+  unique_ptr<Runfiles> r(Runfiles::Create(argv0, "", "", &error));
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+  EXPECT_EQ(r->Rlocation("a/b"), "c/d");
+  // We know it's manifest-based because it returns empty string for unknown
+  // paths.
+  EXPECT_EQ(r->Rlocation("unknown"), "");
+  AssertEnvvars(*r, mf->Path(), "");
+}
+
+TEST_F(RunfilesTest,
+       CreatesManifestBasedRunfilesFromManifestInRunfilesDirectory) {
+  unique_ptr<MockFile> mf(MockFile::Create(
+      "foo" LINE_AS_STRING() ".runfiles/MANIFEST", {"a/b c/d"}));
+  EXPECT_TRUE(mf != nullptr);
+  string argv0(mf->Path().substr(
+      0, mf->Path().size() - string(".runfiles/MANIFEST").size()));
+
+  string error;
+  unique_ptr<Runfiles> r(Runfiles::Create(argv0, "", "", &error));
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+  EXPECT_EQ(r->Rlocation("a/b"), "c/d");
+  EXPECT_EQ(r->Rlocation("foo"), argv0 + ".runfiles/foo");
+  AssertEnvvars(*r, mf->Path(), argv0 + ".runfiles");
+}
+
+TEST_F(RunfilesTest, CreatesManifestBasedRunfilesFromEnvvar) {
+  unique_ptr<MockFile> mf(MockFile::Create(
+      "foo" LINE_AS_STRING() ".runfiles_manifest", {"a/b c/d"}));
+  EXPECT_TRUE(mf != nullptr);
+
+  string error;
+  unique_ptr<Runfiles> r(Runfiles::Create("ignore-argv0", mf->Path(),
+                                          "non-existent-runfiles_dir", &error));
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+  EXPECT_EQ(r->Rlocation("a/b"), "c/d");
+  // We know it's manifest-based because it returns empty string for unknown
+  // paths.
+  EXPECT_EQ(r->Rlocation("unknown"), "");
+  AssertEnvvars(*r, mf->Path(), "");
+}
+
+TEST_F(RunfilesTest, CannotCreateManifestBasedRunfilesDueToBadManifest) {
+  unique_ptr<MockFile> mf(MockFile::Create(
+      "foo" LINE_AS_STRING() ".runfiles_manifest", {"a b", "nospace"}));
+  EXPECT_TRUE(mf != nullptr);
+
+  string error;
+  unique_ptr<Runfiles> r(
+      Runfiles::Create("ignore-argv0", mf->Path(), "", &error));
+  ASSERT_EQ(r, nullptr);
+  EXPECT_NE(error.find("bad runfiles manifest entry"), string::npos);
+  EXPECT_NE(error.find("line #2: \"nospace\""), string::npos);
+}
+
+TEST_F(RunfilesTest, ManifestBasedRunfilesRlocationAndEnvVars) {
+  unique_ptr<MockFile> mf(MockFile::Create(
+      "foo" LINE_AS_STRING() ".runfiles_manifest", {"a/b c/d"}));
+  EXPECT_TRUE(mf != nullptr);
+
+  string error;
+  unique_ptr<Runfiles> r(
+      Runfiles::Create("ignore-argv0", mf->Path(), "", &error));
+
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+  EXPECT_EQ(r->Rlocation("a/b"), "c/d");
+  EXPECT_EQ(r->Rlocation("c/d"), "");
+  EXPECT_EQ(r->Rlocation(""), "");
+  EXPECT_EQ(r->Rlocation("foo"), "");
+  EXPECT_EQ(r->Rlocation("foo/"), "");
+  EXPECT_EQ(r->Rlocation("foo/bar"), "");
+  EXPECT_EQ(r->Rlocation("../foo"), "");
+  EXPECT_EQ(r->Rlocation("foo/.."), "");
+  EXPECT_EQ(r->Rlocation("foo/../bar"), "");
+  EXPECT_EQ(r->Rlocation("./foo"), "");
+  EXPECT_EQ(r->Rlocation("foo/."), "");
+  EXPECT_EQ(r->Rlocation("foo/./bar"), "");
+  EXPECT_EQ(r->Rlocation("//foo"), "");
+  EXPECT_EQ(r->Rlocation("foo//"), "");
+  EXPECT_EQ(r->Rlocation("foo//bar"), "");
+  EXPECT_EQ(r->Rlocation("/Foo"), "/Foo");
+  EXPECT_EQ(r->Rlocation("c:/Foo"), "c:/Foo");
+  EXPECT_EQ(r->Rlocation("c:\\Foo"), "c:\\Foo");
+}
+
+TEST_F(RunfilesTest, DirectoryBasedRunfilesRlocationAndEnvVars) {
+  unique_ptr<MockFile> dummy(
+      MockFile::Create("foo" LINE_AS_STRING() ".runfiles/dummy", {"a/b c/d"}));
+  EXPECT_TRUE(dummy != nullptr);
+  string dir = dummy->DirName();
+
+  string error;
+  unique_ptr<Runfiles> r(Runfiles::Create("ignore-argv0", "", dir, &error));
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+
+  EXPECT_EQ(r->Rlocation("a/b"), dir + "/a/b");
+  EXPECT_EQ(r->Rlocation("c/d"), dir + "/c/d");
+  EXPECT_EQ(r->Rlocation(""), "");
+  EXPECT_EQ(r->Rlocation("foo"), dir + "/foo");
+  EXPECT_EQ(r->Rlocation("foo/"), dir + "/foo/");
+  EXPECT_EQ(r->Rlocation("foo/bar"), dir + "/foo/bar");
+  EXPECT_EQ(r->Rlocation("../foo"), "");
+  EXPECT_EQ(r->Rlocation("foo/.."), "");
+  EXPECT_EQ(r->Rlocation("foo/../bar"), "");
+  EXPECT_EQ(r->Rlocation("./foo"), "");
+  EXPECT_EQ(r->Rlocation("foo/."), "");
+  EXPECT_EQ(r->Rlocation("foo/./bar"), "");
+  EXPECT_EQ(r->Rlocation("//foo"), "");
+  EXPECT_EQ(r->Rlocation("foo//"), "");
+  EXPECT_EQ(r->Rlocation("foo//bar"), "");
+  EXPECT_EQ(r->Rlocation("/Foo"), "/Foo");
+  EXPECT_EQ(r->Rlocation("c:/Foo"), "c:/Foo");
+  EXPECT_EQ(r->Rlocation("c:\\Foo"), "c:\\Foo");
+  AssertEnvvars(*r, "", dir);
+}
+
+TEST_F(RunfilesTest, ManifestAndDirectoryBasedRunfilesRlocationAndEnvVars) {
+  unique_ptr<MockFile> mf(MockFile::Create(
+      "foo" LINE_AS_STRING() ".runfiles/MANIFEST", {"a/b c/d"}));
+  EXPECT_TRUE(mf != nullptr);
+  string dir = mf->DirName();
+
+  string error;
+  unique_ptr<Runfiles> r(
+      Runfiles::Create("ignore-argv0", mf->Path(), "", &error));
+
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+  EXPECT_EQ(r->Rlocation("a/b"), "c/d");
+  EXPECT_EQ(r->Rlocation("c/d"), dir + "/c/d");
+  EXPECT_EQ(r->Rlocation(""), "");
+  EXPECT_EQ(r->Rlocation("foo"), dir + "/foo");
+  EXPECT_EQ(r->Rlocation("foo/"), dir + "/foo/");
+  EXPECT_EQ(r->Rlocation("foo/bar"), dir + "/foo/bar");
+  EXPECT_EQ(r->Rlocation("../foo"), "");
+  EXPECT_EQ(r->Rlocation("foo/.."), "");
+  EXPECT_EQ(r->Rlocation("foo/../bar"), "");
+  EXPECT_EQ(r->Rlocation("./foo"), "");
+  EXPECT_EQ(r->Rlocation("foo/."), "");
+  EXPECT_EQ(r->Rlocation("foo/./bar"), "");
+  EXPECT_EQ(r->Rlocation("//foo"), "");
+  EXPECT_EQ(r->Rlocation("foo//"), "");
+  EXPECT_EQ(r->Rlocation("foo//bar"), "");
+  EXPECT_EQ(r->Rlocation("/Foo"), "/Foo");
+  EXPECT_EQ(r->Rlocation("c:/Foo"), "c:/Foo");
+  EXPECT_EQ(r->Rlocation("c:\\Foo"), "c:\\Foo");
+  AssertEnvvars(*r, mf->Path(), dir);
+}
+
+TEST_F(RunfilesTest, ManifestBasedRunfilesEnvVars) {
+  unique_ptr<MockFile> mf(
+      MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles_manifest")));
+  EXPECT_TRUE(mf != nullptr);
+
+  string error;
+  unique_ptr<Runfiles> r(
+      Runfiles::Create("ignore-argv0", mf->Path(), "", &error));
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+
+  AssertEnvvars(*r, mf->Path(), "");
+}
+
+TEST_F(RunfilesTest, CreatesDirectoryBasedRunfilesFromDirectoryNextToBinary) {
+  // We create a directory as a side-effect of creating a mock file.
+  unique_ptr<MockFile> mf(
+      MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles/dummy")));
+  string argv0(mf->Path().substr(
+      0, mf->Path().size() - string(".runfiles/dummy").size()));
+
+  string error;
+  unique_ptr<Runfiles> r(Runfiles::Create(argv0, "", "", &error));
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+
+  EXPECT_EQ(r->Rlocation("a/b"), argv0 + ".runfiles/a/b");
+  // We know it's directory-based because it returns some result for unknown
+  // paths.
+  EXPECT_EQ(r->Rlocation("unknown"), argv0 + ".runfiles/unknown");
+  AssertEnvvars(*r, "", argv0 + ".runfiles");
+}
+
+TEST_F(RunfilesTest, CreatesDirectoryBasedRunfilesFromEnvvar) {
+  // We create a directory as a side-effect of creating a mock file.
+  unique_ptr<MockFile> mf(
+      MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles/dummy")));
+  string dir = mf->DirName();
+
+  string error;
+  unique_ptr<Runfiles> r(Runfiles::Create("ignore-argv0", "", dir, &error));
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+
+  EXPECT_EQ(r->Rlocation("a/b"), dir + "/a/b");
+  EXPECT_EQ(r->Rlocation("foo"), dir + "/foo");
+  EXPECT_EQ(r->Rlocation("/Foo"), "/Foo");
+  EXPECT_EQ(r->Rlocation("c:/Foo"), "c:/Foo");
+  EXPECT_EQ(r->Rlocation("c:\\Foo"), "c:\\Foo");
+  AssertEnvvars(*r, "", dir);
+}
+
+TEST_F(RunfilesTest, FailsToCreateAnyRunfilesBecauseEnvvarsAreNotDefined) {
+  unique_ptr<MockFile> mf(
+      MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles/MANIFEST")));
+  EXPECT_TRUE(mf != nullptr);
+
+  string error;
+  unique_ptr<Runfiles> r(
+      Runfiles::Create("ignore-argv0", mf->Path(), "whatever", &error));
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+
+  // We create a directory as a side-effect of creating a mock file.
+  mf.reset(MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles/dummy")));
+  r.reset(Runfiles::Create("ignore-argv0", "", mf->DirName(), &error));
+  ASSERT_NE(r, nullptr);
+  EXPECT_TRUE(error.empty());
+
+  r.reset(Runfiles::Create("ignore-argv0", "", "", &error));
+  ASSERT_EQ(r, nullptr);
+  EXPECT_NE(error.find("cannot find runfiles"), string::npos);
+}
+
+TEST_F(RunfilesTest, MockFileTest) {
+  {
+    unique_ptr<MockFile> mf(
+        MockFile::Create(string("foo" LINE_AS_STRING() "/..")));
+    EXPECT_TRUE(mf == nullptr);
+  }
+
+  {
+    unique_ptr<MockFile> mf(MockFile::Create(string("/Foo" LINE_AS_STRING())));
+    EXPECT_TRUE(mf == nullptr);
+  }
+
+  {
+    unique_ptr<MockFile> mf(
+        MockFile::Create(string("C:/Foo" LINE_AS_STRING())));
+    EXPECT_TRUE(mf == nullptr);
+  }
+
+  string path;
+  {
+    unique_ptr<MockFile> mf(
+        MockFile::Create(string("foo" LINE_AS_STRING() "/bar1/qux")));
+    EXPECT_TRUE(mf != nullptr);
+    path = mf->Path();
+
+    std::ifstream stm(path);
+    EXPECT_TRUE(stm.good());
+    string actual;
+    stm >> actual;
+    EXPECT_TRUE(actual.empty());
+  }
+  {
+    std::ifstream stm(path);
+    EXPECT_FALSE(stm.good());
+  }
+
+  {
+    unique_ptr<MockFile> mf(MockFile::Create(
+        string("foo" LINE_AS_STRING() "/bar2/qux"), vector<string>()));
+    EXPECT_TRUE(mf != nullptr);
+    path = mf->Path();
+
+    std::ifstream stm(path);
+    EXPECT_TRUE(stm.good());
+    string actual;
+    stm >> actual;
+    EXPECT_TRUE(actual.empty());
+  }
+  {
+    std::ifstream stm(path);
+    EXPECT_FALSE(stm.good());
+  }
+
+  {
+    unique_ptr<MockFile> mf(
+        MockFile::Create(string("foo" LINE_AS_STRING() "/bar3/qux"),
+                         {"hello world", "you are beautiful"}));
+    EXPECT_TRUE(mf != nullptr);
+    path = mf->Path();
+
+    std::ifstream stm(path);
+    EXPECT_TRUE(stm.good());
+    string actual;
+    std::getline(stm, actual);
+    EXPECT_EQ("hello world", actual);
+    std::getline(stm, actual);
+    EXPECT_EQ("you are beautiful", actual);
+    std::getline(stm, actual);
+    EXPECT_EQ("", actual);
+  }
+  {
+    std::ifstream stm(path);
+    EXPECT_FALSE(stm.good());
+  }
+}
+
+TEST_F(RunfilesTest, IsAbsolute) {
+  EXPECT_FALSE(TestOnly_IsAbsolute("foo"));
+  EXPECT_FALSE(TestOnly_IsAbsolute("foo/bar"));
+  EXPECT_FALSE(TestOnly_IsAbsolute("\\foo"));
+  EXPECT_TRUE(TestOnly_IsAbsolute("c:\\foo"));
+  EXPECT_TRUE(TestOnly_IsAbsolute("c:/foo"));
+  EXPECT_TRUE(TestOnly_IsAbsolute("/foo"));
+  EXPECT_TRUE(TestOnly_IsAbsolute("x:\\foo"));
+  EXPECT_FALSE(TestOnly_IsAbsolute("::\\foo"));
+  EXPECT_FALSE(TestOnly_IsAbsolute("x\\foo"));
+  EXPECT_FALSE(TestOnly_IsAbsolute("x:"));
+  EXPECT_TRUE(TestOnly_IsAbsolute("x:\\"));
+}
+
+TEST_F(RunfilesTest, PathsFromEnvVars) {
+  string mf, dir;
+
+  // Both envvars have a valid value.
+  EXPECT_TRUE(TestOnly_PathsFrom(
+      "argv0", "mock1/MANIFEST", "mock2",
+      [](const string& path) { return path == "mock1/MANIFEST"; },
+      [](const string& path) { return path == "mock2"; }, &mf, &dir));
+  EXPECT_EQ(mf, "mock1/MANIFEST");
+  EXPECT_EQ(dir, "mock2");
+
+  // RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good and there's a
+  // runfiles manifest in the runfiles directory.
+  EXPECT_TRUE(TestOnly_PathsFrom(
+      "argv0", "mock1/MANIFEST", "mock2",
+      [](const string& path) { return path == "mock2/MANIFEST"; },
+      [](const string& path) { return path == "mock2"; }, &mf, &dir));
+  EXPECT_EQ(mf, "mock2/MANIFEST");
+  EXPECT_EQ(dir, "mock2");
+
+  // RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good, but there's no
+  // runfiles manifest in the runfiles directory.
+  EXPECT_TRUE(TestOnly_PathsFrom(
+      "argv0", "mock1/MANIFEST", "mock2",
+      [](const string& path) { return false; },
+      [](const string& path) { return path == "mock2"; }, &mf, &dir));
+  EXPECT_EQ(mf, "");
+  EXPECT_EQ(dir, "mock2");
+
+  // RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, and it is in
+  // a valid-looking runfiles directory.
+  EXPECT_TRUE(TestOnly_PathsFrom(
+      "argv0", "mock1/MANIFEST", "mock2",
+      [](const string& path) { return path == "mock1/MANIFEST"; },
+      [](const string& path) { return path == "mock1"; }, &mf, &dir));
+  EXPECT_EQ(mf, "mock1/MANIFEST");
+  EXPECT_EQ(dir, "mock1");
+
+  // RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, but it is not
+  // in any valid-looking runfiles directory.
+  EXPECT_TRUE(TestOnly_PathsFrom(
+      "argv0", "mock1/MANIFEST", "mock2",
+      [](const string& path) { return path == "mock1/MANIFEST"; },
+      [](const string& path) { return false; }, &mf, &dir));
+  EXPECT_EQ(mf, "mock1/MANIFEST");
+  EXPECT_EQ(dir, "");
+
+  // Both envvars are invalid, but there's a manifest in a runfiles directory
+  // next to argv0, however there's no other content in the runfiles directory.
+  EXPECT_TRUE(TestOnly_PathsFrom(
+      "argv0", "mock1/MANIFEST", "mock2",
+      [](const string& path) { return path == "argv0.runfiles/MANIFEST"; },
+      [](const string& path) { return false; }, &mf, &dir));
+  EXPECT_EQ(mf, "argv0.runfiles/MANIFEST");
+  EXPECT_EQ(dir, "");
+
+  // Both envvars are invalid, but there's a manifest next to argv0. There's
+  // no runfiles tree anywhere.
+  EXPECT_TRUE(TestOnly_PathsFrom(
+      "argv0", "mock1/MANIFEST", "mock2",
+      [](const string& path) { return path == "argv0.runfiles_manifest"; },
+      [](const string& path) { return false; }, &mf, &dir));
+  EXPECT_EQ(mf, "argv0.runfiles_manifest");
+  EXPECT_EQ(dir, "");
+
+  // Both envvars are invalid, but there's a valid manifest next to argv0, and a
+  // valid runfiles directory (without a manifest in it).
+  EXPECT_TRUE(TestOnly_PathsFrom(
+      "argv0", "mock1/MANIFEST", "mock2",
+      [](const string& path) { return path == "argv0.runfiles_manifest"; },
+      [](const string& path) { return path == "argv0.runfiles"; }, &mf, &dir));
+  EXPECT_EQ(mf, "argv0.runfiles_manifest");
+  EXPECT_EQ(dir, "argv0.runfiles");
+
+  // Both envvars are invalid, but there's a valid runfiles directory next to
+  // argv0, though no manifest in it.
+  EXPECT_TRUE(TestOnly_PathsFrom(
+      "argv0", "mock1/MANIFEST", "mock2",
+      [](const string& path) { return false; },
+      [](const string& path) { return path == "argv0.runfiles"; }, &mf, &dir));
+  EXPECT_EQ(mf, "");
+  EXPECT_EQ(dir, "argv0.runfiles");
+
+  // Both envvars are invalid, but there's a valid runfiles directory next to
+  // argv0 with a valid manifest in it.
+  EXPECT_TRUE(TestOnly_PathsFrom(
+      "argv0", "mock1/MANIFEST", "mock2",
+      [](const string& path) { return path == "argv0.runfiles/MANIFEST"; },
+      [](const string& path) { return path == "argv0.runfiles"; }, &mf, &dir));
+  EXPECT_EQ(mf, "argv0.runfiles/MANIFEST");
+  EXPECT_EQ(dir, "argv0.runfiles");
+}
+
+}  // namespace
+}  // namespace runfiles
+}  // namespace cpp
+}  // namespace tools
+}  // namespace bazel
diff --git a/cc/private/toolchain/unix_cc_configure.bzl b/cc/private/toolchain/unix_cc_configure.bzl
new file mode 100644
index 0000000..58b31bb
--- /dev/null
+++ b/cc/private/toolchain/unix_cc_configure.bzl
@@ -0,0 +1,567 @@
+# pylint: disable=g-bad-file-header
+# Copyright 2016 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.
+"""Configuring the C++ toolchain on Unix platforms."""
+
+load(
+    "@rules_cc//cc/private/toolchain:lib_cc_configure.bzl",
+    "auto_configure_fail",
+    "auto_configure_warning",
+    "auto_configure_warning_maybe",
+    "escape_string",
+    "get_env_var",
+    "get_starlark_list",
+    "resolve_labels",
+    "split_escaped",
+    "which",
+)
+
+def _field(name, value):
+    """Returns properly indented top level crosstool field."""
+    if type(value) == "list":
+        return "\n".join(["  " + name + ": '" + v + "'" for v in value])
+    elif type(value) == "string":
+        return "  " + name + ": '" + value + "'"
+    else:
+        auto_configure_fail("Unexpected field type: " + type(value))
+        return ""
+
+def _uniq(iterable):
+    """Remove duplicates from a list."""
+
+    unique_elements = {element: None for element in iterable}
+    return unique_elements.keys()
+
+def _prepare_include_path(repo_ctx, path):
+    """Resolve and sanitize include path before outputting it into the crosstool.
+
+    Args:
+      repo_ctx: repository_ctx object.
+      path: an include path to be sanitized.
+
+    Returns:
+      Sanitized include path that can be written to the crosstoot. Resulting path
+      is absolute if it is outside the repository and relative otherwise.
+    """
+
+    repo_root = str(repo_ctx.path("."))
+
+    # We're on UNIX, so the path delimiter is '/'.
+    repo_root += "/"
+    path = str(repo_ctx.path(path))
+    if path.startswith(repo_root):
+        return escape_string(path[len(repo_root):])
+    return escape_string(path)
+
+def _get_value(it):
+    """Convert `it` in serialized protobuf format."""
+    if type(it) == "int":
+        return str(it)
+    elif type(it) == "bool":
+        return "true" if it else "false"
+    else:
+        return "\"%s\"" % it
+
+def _find_tool(repository_ctx, tool, overriden_tools):
+    """Find a tool for repository, taking overriden tools into account."""
+    if tool in overriden_tools:
+        return overriden_tools[tool]
+    return which(repository_ctx, tool, "/usr/bin/" + tool)
+
+def _get_tool_paths(repository_ctx, overriden_tools):
+    """Compute the %-escaped path to the various tools"""
+    return dict({
+        k: escape_string(_find_tool(repository_ctx, k, overriden_tools))
+        for k in [
+            "ar",
+            "ld",
+            "cpp",
+            "gcc",
+            "dwp",
+            "gcov",
+            "nm",
+            "objcopy",
+            "objdump",
+            "strip",
+        ]
+    }.items())
+
+def _escaped_cplus_include_paths(repository_ctx):
+    """Use ${CPLUS_INCLUDE_PATH} to compute the %-escaped list of flags for cxxflag."""
+    if "CPLUS_INCLUDE_PATH" in repository_ctx.os.environ:
+        result = []
+        for p in repository_ctx.os.environ["CPLUS_INCLUDE_PATH"].split(":"):
+            p = escape_string(str(repository_ctx.path(p)))  # Normalize the path
+            result.append("-I" + p)
+        return result
+    else:
+        return []
+
+_INC_DIR_MARKER_BEGIN = "#include <...>"
+
+# OSX add " (framework directory)" at the end of line, strip it.
+_OSX_FRAMEWORK_SUFFIX = " (framework directory)"
+_OSX_FRAMEWORK_SUFFIX_LEN = len(_OSX_FRAMEWORK_SUFFIX)
+
+def _cxx_inc_convert(path):
+    """Convert path returned by cc -E xc++ in a complete path. Doesn't %-escape the path!"""
+    path = path.strip()
+    if path.endswith(_OSX_FRAMEWORK_SUFFIX):
+        path = path[:-_OSX_FRAMEWORK_SUFFIX_LEN].strip()
+    return path
+
+def get_escaped_cxx_inc_directories(repository_ctx, cc, lang_flag, additional_flags = []):
+    """Compute the list of default %-escaped C++ include directories."""
+    result = repository_ctx.execute([cc, "-E", lang_flag, "-", "-v"] + additional_flags)
+    index1 = result.stderr.find(_INC_DIR_MARKER_BEGIN)
+    if index1 == -1:
+        return []
+    index1 = result.stderr.find("\n", index1)
+    if index1 == -1:
+        return []
+    index2 = result.stderr.rfind("\n ")
+    if index2 == -1 or index2 < index1:
+        return []
+    index2 = result.stderr.find("\n", index2 + 1)
+    if index2 == -1:
+        inc_dirs = result.stderr[index1 + 1:]
+    else:
+        inc_dirs = result.stderr[index1 + 1:index2].strip()
+
+    return [
+        _prepare_include_path(repository_ctx, _cxx_inc_convert(p))
+        for p in inc_dirs.split("\n")
+    ]
+
+def _is_compiler_option_supported(repository_ctx, cc, option):
+    """Checks that `option` is supported by the C compiler. Doesn't %-escape the option."""
+    result = repository_ctx.execute([
+        cc,
+        option,
+        "-o",
+        "/dev/null",
+        "-c",
+        str(repository_ctx.path("tools/cpp/empty.cc")),
+    ])
+    return result.stderr.find(option) == -1
+
+def _is_linker_option_supported(repository_ctx, cc, option, pattern):
+    """Checks that `option` is supported by the C linker. Doesn't %-escape the option."""
+    result = repository_ctx.execute([
+        cc,
+        option,
+        "-o",
+        "/dev/null",
+        str(repository_ctx.path("tools/cpp/empty.cc")),
+    ])
+    return result.stderr.find(pattern) == -1
+
+def _find_gold_linker_path(repository_ctx, cc):
+    """Checks if `gold` is supported by the C compiler.
+
+    Args:
+      repository_ctx: repository_ctx.
+      cc: path to the C compiler.
+
+    Returns:
+      String to put as value to -fuse-ld= flag, or None if gold couldn't be found.
+    """
+    result = repository_ctx.execute([
+        cc,
+        str(repository_ctx.path("tools/cpp/empty.cc")),
+        "-o",
+        "/dev/null",
+        # Some macos clang versions don't fail when setting -fuse-ld=gold, adding
+        # these lines to force it to. This also means that we will not detect
+        # gold when only a very old (year 2010 and older) is present.
+        "-Wl,--start-lib",
+        "-Wl,--end-lib",
+        "-fuse-ld=gold",
+        "-v",
+    ])
+    if result.return_code != 0:
+        return None
+
+    for line in result.stderr.splitlines():
+        if line.find("gold") == -1:
+            continue
+        for flag in line.split(" "):
+            if flag.find("gold") == -1:
+                continue
+
+            # flag is '-fuse-ld=gold' for GCC or "/usr/lib/ld.gold" for Clang
+            # strip space, single quote, and double quotes
+            flag = flag.strip(" \"'")
+
+            # remove -fuse-ld= from GCC output so we have only the flag value part
+            flag = flag.replace("-fuse-ld=", "")
+            return flag
+    auto_configure_warning(
+        "CC with -fuse-ld=gold returned 0, but its -v output " +
+        "didn't contain 'gold', falling back to the default linker.",
+    )
+    return None
+
+def _add_compiler_option_if_supported(repository_ctx, cc, option):
+    """Returns `[option]` if supported, `[]` otherwise. Doesn't %-escape the option."""
+    return [option] if _is_compiler_option_supported(repository_ctx, cc, option) else []
+
+def _add_linker_option_if_supported(repository_ctx, cc, option, pattern):
+    """Returns `[option]` if supported, `[]` otherwise. Doesn't %-escape the option."""
+    return [option] if _is_linker_option_supported(repository_ctx, cc, option, pattern) else []
+
+def _get_no_canonical_prefixes_opt(repository_ctx, cc):
+    # If the compiler sometimes rewrites paths in the .d files without symlinks
+    # (ie when they're shorter), it confuses Bazel's logic for verifying all
+    # #included header files are listed as inputs to the action.
+
+    # The '-fno-canonical-system-headers' should be enough, but clang does not
+    # support it, so we also try '-no-canonical-prefixes' if first option does
+    # not work.
+    opt = _add_compiler_option_if_supported(
+        repository_ctx,
+        cc,
+        "-fno-canonical-system-headers",
+    )
+    if len(opt) == 0:
+        return _add_compiler_option_if_supported(
+            repository_ctx,
+            cc,
+            "-no-canonical-prefixes",
+        )
+    return opt
+
+def get_env(repository_ctx):
+    """Convert the environment in a list of export if in Homebrew. Doesn't %-escape the result!"""
+    env = repository_ctx.os.environ
+    if "HOMEBREW_RUBY_PATH" in env:
+        return "\n".join([
+            "export %s='%s'" % (k, env[k].replace("'", "'\\''"))
+            for k in env
+            if k != "_" and k.find(".") == -1
+        ])
+    else:
+        return ""
+
+def _coverage_flags(repository_ctx, darwin):
+    use_llvm_cov = "1" == get_env_var(
+        repository_ctx,
+        "BAZEL_USE_LLVM_NATIVE_COVERAGE",
+        default = "0",
+        enable_warning = False,
+    )
+    if darwin or use_llvm_cov:
+        compile_flags = '"-fprofile-instr-generate",  "-fcoverage-mapping"'
+        link_flags = '"-fprofile-instr-generate"'
+    else:
+        # gcc requires --coverage being passed for compilation and linking
+        # https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#Instrumentation-Options
+        compile_flags = '"--coverage"'
+        link_flags = '"--coverage"'
+    return compile_flags, link_flags
+
+def _find_generic(repository_ctx, name, env_name, overriden_tools, warn = False, silent = False):
+    """Find a generic C++ toolchain tool. Doesn't %-escape the result."""
+
+    if name in overriden_tools:
+        return overriden_tools[name]
+
+    result = name
+    env_value = repository_ctx.os.environ.get(env_name)
+    env_value_with_paren = ""
+    if env_value != None:
+        env_value = env_value.strip()
+        if env_value:
+            result = env_value
+            env_value_with_paren = " (%s)" % env_value
+    if result.startswith("/"):
+        # Absolute path, maybe we should make this suported by our which function.
+        return result
+    result = repository_ctx.which(result)
+    if result == None:
+        msg = ("Cannot find %s or %s%s; either correct your path or set the %s" +
+               " environment variable") % (name, env_name, env_value_with_paren, env_name)
+        if warn:
+            if not silent:
+                auto_configure_warning(msg)
+        else:
+            auto_configure_fail(msg)
+    return result
+
+def find_cc(repository_ctx, overriden_tools):
+    return _find_generic(repository_ctx, "gcc", "CC", overriden_tools)
+
+def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
+    """Configure C++ toolchain on Unix platforms."""
+    paths = resolve_labels(repository_ctx, [
+        "@rules_cc//cc/private/toolchain:BUILD.tpl",
+        "@rules_cc//cc/private/toolchain:armeabi_cc_toolchain_config.bzl",
+        "@rules_cc//cc/private/toolchain:unix_cc_toolchain_config.bzl",
+        "@rules_cc//cc/private/toolchain:linux_cc_wrapper.sh.tpl",
+        "@rules_cc//cc/private/toolchain:osx_cc_wrapper.sh.tpl",
+    ])
+
+    repository_ctx.symlink(
+        paths["@rules_cc//cc/private/toolchain:unix_cc_toolchain_config.bzl"],
+        "cc_toolchain_config.bzl",
+    )
+
+    repository_ctx.symlink(
+        paths["@rules_cc//cc/private/toolchain:armeabi_cc_toolchain_config.bzl"],
+        "armeabi_cc_toolchain_config.bzl",
+    )
+
+    repository_ctx.file("tools/cpp/empty.cc", "int main() {}")
+    darwin = cpu_value == "darwin"
+
+    cc = _find_generic(repository_ctx, "gcc", "CC", overriden_tools)
+    overriden_tools = dict(overriden_tools)
+    overriden_tools["gcc"] = cc
+    overriden_tools["gcov"] = _find_generic(
+        repository_ctx,
+        "gcov",
+        "GCOV",
+        overriden_tools,
+        warn = True,
+        silent = True,
+    )
+    if darwin:
+        overriden_tools["gcc"] = "cc_wrapper.sh"
+        overriden_tools["ar"] = "/usr/bin/libtool"
+    auto_configure_warning_maybe(repository_ctx, "CC used: " + str(cc))
+    tool_paths = _get_tool_paths(repository_ctx, overriden_tools)
+    cc_toolchain_identifier = escape_string(get_env_var(
+        repository_ctx,
+        "CC_TOOLCHAIN_NAME",
+        "local",
+        False,
+    ))
+
+    cc_wrapper_src = (
+        "@rules_cc//cc/private/toolchain:osx_cc_wrapper.sh.tpl" if darwin else "@rules_cc//cc/private/toolchain:linux_cc_wrapper.sh.tpl"
+    )
+    repository_ctx.template(
+        "cc_wrapper.sh",
+        paths[cc_wrapper_src],
+        {
+            "%{cc}": escape_string(str(cc)),
+            "%{env}": escape_string(get_env(repository_ctx)),
+        },
+    )
+
+    cxx_opts = split_escaped(get_env_var(
+        repository_ctx,
+        "BAZEL_CXXOPTS",
+        "-std=c++0x",
+        False,
+    ), ":")
+    link_opts = split_escaped(get_env_var(
+        repository_ctx,
+        "BAZEL_LINKOPTS",
+        "-lstdc++:-lm",
+        False,
+    ), ":")
+    link_libs = split_escaped(get_env_var(
+        repository_ctx,
+        "BAZEL_LINKLIBS",
+        "",
+        False,
+    ), ":")
+    gold_linker_path = _find_gold_linker_path(repository_ctx, cc)
+    cc_path = repository_ctx.path(cc)
+    if not str(cc_path).startswith(str(repository_ctx.path(".")) + "/"):
+        # cc is outside the repository, set -B
+        bin_search_flag = ["-B" + escape_string(str(cc_path.dirname))]
+    else:
+        # cc is inside the repository, don't set -B.
+        bin_search_flag = []
+
+    coverage_compile_flags, coverage_link_flags = _coverage_flags(repository_ctx, darwin)
+
+    repository_ctx.template(
+        "BUILD",
+        paths["@rules_cc//cc/private/toolchain:BUILD.tpl"],
+        {
+            "%{cc_toolchain_identifier}": cc_toolchain_identifier,
+            "%{name}": cpu_value,
+            "%{supports_param_files}": "0" if darwin else "1",
+            "%{cc_compiler_deps}": ":cc_wrapper" if darwin else ":empty",
+            "%{compiler}": escape_string(get_env_var(
+                repository_ctx,
+                "BAZEL_COMPILER",
+                "compiler",
+                False,
+            )),
+            "%{abi_version}": escape_string(get_env_var(
+                repository_ctx,
+                "ABI_VERSION",
+                "local",
+                False,
+            )),
+            "%{abi_libc_version}": escape_string(get_env_var(
+                repository_ctx,
+                "ABI_LIBC_VERSION",
+                "local",
+                False,
+            )),
+            "%{host_system_name}": escape_string(get_env_var(
+                repository_ctx,
+                "BAZEL_HOST_SYSTEM",
+                "local",
+                False,
+            )),
+            "%{target_libc}": "macosx" if darwin else escape_string(get_env_var(
+                repository_ctx,
+                "BAZEL_TARGET_LIBC",
+                "local",
+                False,
+            )),
+            "%{target_cpu}": escape_string(get_env_var(
+                repository_ctx,
+                "BAZEL_TARGET_CPU",
+                cpu_value,
+                False,
+            )),
+            "%{target_system_name}": escape_string(get_env_var(
+                repository_ctx,
+                "BAZEL_TARGET_SYSTEM",
+                "local",
+                False,
+            )),
+            "%{tool_paths}": ",\n        ".join(
+                ['"%s": "%s"' % (k, v) for k, v in tool_paths.items()],
+            ),
+            "%{cxx_builtin_include_directories}": get_starlark_list(
+                _uniq(
+                    get_escaped_cxx_inc_directories(repository_ctx, cc, "-xc") +
+                    get_escaped_cxx_inc_directories(repository_ctx, cc, "-xc++", cxx_opts) +
+                    get_escaped_cxx_inc_directories(
+                        repository_ctx,
+                        cc,
+                        "-xc",
+                        _get_no_canonical_prefixes_opt(repository_ctx, cc),
+                    ) +
+                    get_escaped_cxx_inc_directories(
+                        repository_ctx,
+                        cc,
+                        "-xc++",
+                        cxx_opts + _get_no_canonical_prefixes_opt(repository_ctx, cc),
+                    ),
+                ),
+            ),
+            "%{compile_flags}": get_starlark_list(
+                [
+                    # Security hardening requires optimization.
+                    # We need to undef it as some distributions now have it enabled by default.
+                    "-U_FORTIFY_SOURCE",
+                    "-fstack-protector",
+                    # All warnings are enabled. Maybe enable -Werror as well?
+                    "-Wall",
+                    # Enable a few more warnings that aren't part of -Wall.
+                ] + ((
+                    _add_compiler_option_if_supported(repository_ctx, cc, "-Wthread-safety") +
+                    _add_compiler_option_if_supported(repository_ctx, cc, "-Wself-assign")
+                )) + (
+                    # Disable problematic warnings.
+                    _add_compiler_option_if_supported(repository_ctx, cc, "-Wunused-but-set-parameter") +
+                    # has false positives
+                    _add_compiler_option_if_supported(repository_ctx, cc, "-Wno-free-nonheap-object") +
+                    # Enable coloring even if there's no attached terminal. Bazel removes the
+                    # escape sequences if --nocolor is specified.
+                    _add_compiler_option_if_supported(repository_ctx, cc, "-fcolor-diagnostics")
+                ) + [
+                    # Keep stack frames for debugging, even in opt mode.
+                    "-fno-omit-frame-pointer",
+                ],
+            ),
+            "%{cxx_flags}": get_starlark_list(cxx_opts + _escaped_cplus_include_paths(repository_ctx)),
+            "%{link_flags}": get_starlark_list((
+                ["-fuse-ld=" + gold_linker_path] if gold_linker_path else []
+            ) + _add_linker_option_if_supported(
+                repository_ctx,
+                cc,
+                "-Wl,-no-as-needed",
+                "-no-as-needed",
+            ) + _add_linker_option_if_supported(
+                repository_ctx,
+                cc,
+                "-Wl,-z,relro,-z,now",
+                "-z",
+            ) + (
+                [
+                    "-undefined",
+                    "dynamic_lookup",
+                    "-headerpad_max_install_names",
+                ] if darwin else bin_search_flag + [
+                    # Gold linker only? Can we enable this by default?
+                    # "-Wl,--warn-execstack",
+                    # "-Wl,--detect-odr-violations"
+                ] + _add_compiler_option_if_supported(
+                    # Have gcc return the exit code from ld.
+                    repository_ctx,
+                    cc,
+                    "-pass-exit-codes",
+                )
+            ) + link_opts),
+            "%{link_libs}": get_starlark_list(link_libs),
+            "%{opt_compile_flags}": get_starlark_list(
+                [
+                    # No debug symbols.
+                    # Maybe we should enable https://gcc.gnu.org/wiki/DebugFission for opt or
+                    # even generally? However, that can't happen here, as it requires special
+                    # handling in Bazel.
+                    "-g0",
+
+                    # Conservative choice for -O
+                    # -O3 can increase binary size and even slow down the resulting binaries.
+                    # Profile first and / or use FDO if you need better performance than this.
+                    "-O2",
+
+                    # Security hardening on by default.
+                    # Conservative choice; -D_FORTIFY_SOURCE=2 may be unsafe in some cases.
+                    "-D_FORTIFY_SOURCE=1",
+
+                    # Disable assertions
+                    "-DNDEBUG",
+
+                    # Removal of unused code and data at link time (can this increase binary
+                    # size in some cases?).
+                    "-ffunction-sections",
+                    "-fdata-sections",
+                ],
+            ),
+            "%{opt_link_flags}": get_starlark_list(
+                [] if darwin else _add_linker_option_if_supported(
+                    repository_ctx,
+                    cc,
+                    "-Wl,--gc-sections",
+                    "-gc-sections",
+                ),
+            ),
+            "%{unfiltered_compile_flags}": get_starlark_list(
+                _get_no_canonical_prefixes_opt(repository_ctx, cc) + [
+                    # Make C++ compilation deterministic. Use linkstamping instead of these
+                    # compiler symbols.
+                    "-Wno-builtin-macro-redefined",
+                    "-D__DATE__=\\\"redacted\\\"",
+                    "-D__TIMESTAMP__=\\\"redacted\\\"",
+                    "-D__TIME__=\\\"redacted\\\"",
+                ],
+            ),
+            "%{dbg_compile_flags}": get_starlark_list(["-g"]),
+            "%{coverage_compile_flags}": coverage_compile_flags,
+            "%{coverage_link_flags}": coverage_link_flags,
+            "%{supports_start_end_lib}": "True" if gold_linker_path else "False",
+        },
+    )
diff --git a/cc/private/toolchain/unix_cc_toolchain_config.bzl b/cc/private/toolchain/unix_cc_toolchain_config.bzl
new file mode 100644
index 0000000..0999ae6
--- /dev/null
+++ b/cc/private/toolchain/unix_cc_toolchain_config.bzl
@@ -0,0 +1,1133 @@
+# Copyright 2019 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.
+
+"""A Starlark cc_toolchain configuration rule"""
+
+load(
+    "@rules_cc//cc/private/toolchain:cc_toolchain_config_lib.bzl",
+    "feature",
+    "feature_set",
+    "flag_group",
+    "flag_set",
+    "tool_path",
+    "variable_with_value",
+    "with_feature_set",
+)
+load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
+
+all_compile_actions = [
+    ACTION_NAMES.c_compile,
+    ACTION_NAMES.cpp_compile,
+    ACTION_NAMES.linkstamp_compile,
+    ACTION_NAMES.assemble,
+    ACTION_NAMES.preprocess_assemble,
+    ACTION_NAMES.cpp_header_parsing,
+    ACTION_NAMES.cpp_module_compile,
+    ACTION_NAMES.cpp_module_codegen,
+    ACTION_NAMES.clif_match,
+    ACTION_NAMES.lto_backend,
+]
+
+all_cpp_compile_actions = [
+    ACTION_NAMES.cpp_compile,
+    ACTION_NAMES.linkstamp_compile,
+    ACTION_NAMES.cpp_header_parsing,
+    ACTION_NAMES.cpp_module_compile,
+    ACTION_NAMES.cpp_module_codegen,
+    ACTION_NAMES.clif_match,
+]
+
+preprocessor_compile_actions = [
+    ACTION_NAMES.c_compile,
+    ACTION_NAMES.cpp_compile,
+    ACTION_NAMES.linkstamp_compile,
+    ACTION_NAMES.preprocess_assemble,
+    ACTION_NAMES.cpp_header_parsing,
+    ACTION_NAMES.cpp_module_compile,
+    ACTION_NAMES.clif_match,
+]
+
+codegen_compile_actions = [
+    ACTION_NAMES.c_compile,
+    ACTION_NAMES.cpp_compile,
+    ACTION_NAMES.linkstamp_compile,
+    ACTION_NAMES.assemble,
+    ACTION_NAMES.preprocess_assemble,
+    ACTION_NAMES.cpp_module_codegen,
+    ACTION_NAMES.lto_backend,
+]
+
+all_link_actions = [
+    ACTION_NAMES.cpp_link_executable,
+    ACTION_NAMES.cpp_link_dynamic_library,
+    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+]
+
+lto_index_actions = [
+    ACTION_NAMES.lto_index_for_executable,
+    ACTION_NAMES.lto_index_for_dynamic_library,
+    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
+]
+
+def _impl(ctx):
+    tool_paths = [
+        tool_path(name = name, path = path)
+        for name, path in ctx.attr.tool_paths.items()
+    ]
+    action_configs = []
+
+    supports_pic_feature = feature(
+        name = "supports_pic",
+        enabled = True,
+    )
+    supports_start_end_lib_feature = feature(
+        name = "supports_start_end_lib",
+        enabled = True,
+    )
+
+    default_compile_flags_feature = feature(
+        name = "default_compile_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = ([
+                    flag_group(
+                        flags = ctx.attr.compile_flags,
+                    ),
+                ] if ctx.attr.compile_flags else []),
+            ),
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = ([
+                    flag_group(
+                        flags = ctx.attr.dbg_compile_flags,
+                    ),
+                ] if ctx.attr.dbg_compile_flags else []),
+                with_features = [with_feature_set(features = ["dbg"])],
+            ),
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = ([
+                    flag_group(
+                        flags = ctx.attr.opt_compile_flags,
+                    ),
+                ] if ctx.attr.opt_compile_flags else []),
+                with_features = [with_feature_set(features = ["opt"])],
+            ),
+            flag_set(
+                actions = all_cpp_compile_actions + [ACTION_NAMES.lto_backend],
+                flag_groups = ([
+                    flag_group(
+                        flags = ctx.attr.cxx_flags,
+                    ),
+                ] if ctx.attr.cxx_flags else []),
+            ),
+        ],
+    )
+
+    default_link_flags_feature = feature(
+        name = "default_link_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = ([
+                    flag_group(
+                        flags = ctx.attr.link_flags,
+                    ),
+                ] if ctx.attr.link_flags else []),
+            ),
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = ([
+                    flag_group(
+                        flags = ctx.attr.opt_link_flags,
+                    ),
+                ] if ctx.attr.opt_link_flags else []),
+                with_features = [with_feature_set(features = ["opt"])],
+            ),
+        ],
+    )
+
+    dbg_feature = feature(name = "dbg")
+
+    opt_feature = feature(name = "opt")
+
+    sysroot_feature = feature(
+        name = "sysroot",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.linkstamp_compile,
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_header_parsing,
+                    ACTION_NAMES.cpp_module_compile,
+                    ACTION_NAMES.cpp_module_codegen,
+                    ACTION_NAMES.lto_backend,
+                    ACTION_NAMES.clif_match,
+                ] + all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = ["--sysroot=%{sysroot}"],
+                        expand_if_available = "sysroot",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    fdo_optimize_feature = feature(
+        name = "fdo_optimize",
+        flag_sets = [
+            flag_set(
+                actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-fprofile-use=%{fdo_profile_path}",
+                            "-fprofile-correction",
+                        ],
+                        expand_if_available = "fdo_profile_path",
+                    ),
+                ],
+            ),
+        ],
+        provides = ["profile"],
+    )
+
+    supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True)
+
+    user_compile_flags_feature = feature(
+        name = "user_compile_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = ["%{user_compile_flags}"],
+                        iterate_over = "user_compile_flags",
+                        expand_if_available = "user_compile_flags",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    unfiltered_compile_flags_feature = feature(
+        name = "unfiltered_compile_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = ([
+                    flag_group(
+                        flags = ctx.attr.unfiltered_compile_flags,
+                    ),
+                ] if ctx.attr.unfiltered_compile_flags else []),
+            ),
+        ],
+    )
+
+    library_search_directories_feature = feature(
+        name = "library_search_directories",
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = ["-L%{library_search_directories}"],
+                        iterate_over = "library_search_directories",
+                        expand_if_available = "library_search_directories",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    static_libgcc_feature = feature(
+        name = "static_libgcc",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.cpp_link_executable,
+                    ACTION_NAMES.cpp_link_dynamic_library,
+                    ACTION_NAMES.lto_index_for_executable,
+                    ACTION_NAMES.lto_index_for_dynamic_library,
+                ],
+                flag_groups = [flag_group(flags = ["-static-libgcc"])],
+                with_features = [
+                    with_feature_set(features = ["static_link_cpp_runtimes"]),
+                ],
+            ),
+        ],
+    )
+
+    pic_feature = feature(
+        name = "pic",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.assemble,
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.linkstamp_compile,
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_module_codegen,
+                    ACTION_NAMES.cpp_module_compile,
+                ],
+                flag_groups = [
+                    flag_group(flags = ["-fPIC"], expand_if_available = "pic"),
+                ],
+            ),
+        ],
+    )
+
+    per_object_debug_info_feature = feature(
+        name = "per_object_debug_info",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.assemble,
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_module_codegen,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["-gsplit-dwarf"],
+                        expand_if_available = "per_object_debug_info_file",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    preprocessor_defines_feature = feature(
+        name = "preprocessor_defines",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.linkstamp_compile,
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_header_parsing,
+                    ACTION_NAMES.cpp_module_compile,
+                    ACTION_NAMES.clif_match,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["-D%{preprocessor_defines}"],
+                        iterate_over = "preprocessor_defines",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    cs_fdo_optimize_feature = feature(
+        name = "cs_fdo_optimize",
+        flag_sets = [
+            flag_set(
+                actions = [ACTION_NAMES.lto_backend],
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-fprofile-use=%{fdo_profile_path}",
+                            "-Xclang-only=-Wno-profile-instr-unprofiled",
+                            "-Xclang-only=-Wno-profile-instr-out-of-date",
+                            "-fprofile-correction",
+                        ],
+                        expand_if_available = "fdo_profile_path",
+                    ),
+                ],
+            ),
+        ],
+        provides = ["csprofile"],
+    )
+
+    autofdo_feature = feature(
+        name = "autofdo",
+        flag_sets = [
+            flag_set(
+                actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-fauto-profile=%{fdo_profile_path}",
+                            "-fprofile-correction",
+                        ],
+                        expand_if_available = "fdo_profile_path",
+                    ),
+                ],
+            ),
+        ],
+        provides = ["profile"],
+    )
+
+    runtime_library_search_directories_feature = feature(
+        name = "runtime_library_search_directories",
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        iterate_over = "runtime_library_search_directories",
+                        flag_groups = [
+                            flag_group(
+                                flags = [
+                                    "-Wl,-rpath,$EXEC_ORIGIN/%{runtime_library_search_directories}",
+                                ],
+                                expand_if_true = "is_cc_test",
+                            ),
+                            flag_group(
+                                flags = [
+                                    "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
+                                ],
+                                expand_if_false = "is_cc_test",
+                            ),
+                        ],
+                        expand_if_available =
+                            "runtime_library_search_directories",
+                    ),
+                ],
+                with_features = [
+                    with_feature_set(features = ["static_link_cpp_runtimes"]),
+                ],
+            ),
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        iterate_over = "runtime_library_search_directories",
+                        flag_groups = [
+                            flag_group(
+                                flags = [
+                                    "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
+                                ],
+                            ),
+                        ],
+                        expand_if_available =
+                            "runtime_library_search_directories",
+                    ),
+                ],
+                with_features = [
+                    with_feature_set(
+                        not_features = ["static_link_cpp_runtimes"],
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    fission_support_feature = feature(
+        name = "fission_support",
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = ["-Wl,--gdb-index"],
+                        expand_if_available = "is_using_fission",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    shared_flag_feature = feature(
+        name = "shared_flag",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.cpp_link_dynamic_library,
+                    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+                    ACTION_NAMES.lto_index_for_dynamic_library,
+                    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
+                ],
+                flag_groups = [flag_group(flags = ["-shared"])],
+            ),
+        ],
+    )
+
+    random_seed_feature = feature(
+        name = "random_seed",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_module_codegen,
+                    ACTION_NAMES.cpp_module_compile,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["-frandom-seed=%{output_file}"],
+                        expand_if_available = "output_file",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    includes_feature = feature(
+        name = "includes",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.linkstamp_compile,
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_header_parsing,
+                    ACTION_NAMES.cpp_module_compile,
+                    ACTION_NAMES.clif_match,
+                    ACTION_NAMES.objc_compile,
+                    ACTION_NAMES.objcpp_compile,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["-include", "%{includes}"],
+                        iterate_over = "includes",
+                        expand_if_available = "includes",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    fdo_instrument_feature = feature(
+        name = "fdo_instrument",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                ] + all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-fprofile-generate=%{fdo_instrument_path}",
+                            "-fno-data-sections",
+                        ],
+                        expand_if_available = "fdo_instrument_path",
+                    ),
+                ],
+            ),
+        ],
+        provides = ["profile"],
+    )
+
+    cs_fdo_instrument_feature = feature(
+        name = "cs_fdo_instrument",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.lto_backend,
+                ] + all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-fcs-profile-generate=%{cs_fdo_instrument_path}",
+                        ],
+                        expand_if_available = "cs_fdo_instrument_path",
+                    ),
+                ],
+            ),
+        ],
+        provides = ["csprofile"],
+    )
+
+    include_paths_feature = feature(
+        name = "include_paths",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.linkstamp_compile,
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_header_parsing,
+                    ACTION_NAMES.cpp_module_compile,
+                    ACTION_NAMES.clif_match,
+                    ACTION_NAMES.objc_compile,
+                    ACTION_NAMES.objcpp_compile,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["-iquote", "%{quote_include_paths}"],
+                        iterate_over = "quote_include_paths",
+                    ),
+                    flag_group(
+                        flags = ["-I%{include_paths}"],
+                        iterate_over = "include_paths",
+                    ),
+                    flag_group(
+                        flags = ["-isystem", "%{system_include_paths}"],
+                        iterate_over = "system_include_paths",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    symbol_counts_feature = feature(
+        name = "symbol_counts",
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-Wl,--print-symbol-counts=%{symbol_counts_output}",
+                        ],
+                        expand_if_available = "symbol_counts_output",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    llvm_coverage_map_format_feature = feature(
+        name = "llvm_coverage_map_format",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_module_compile,
+                    ACTION_NAMES.objc_compile,
+                    ACTION_NAMES.objcpp_compile,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-fprofile-instr-generate",
+                            "-fcoverage-mapping",
+                        ],
+                    ),
+                ],
+            ),
+            flag_set(
+                actions = all_link_actions + lto_index_actions + [
+                    "objc-executable",
+                    "objc++-executable",
+                ],
+                flag_groups = [
+                    flag_group(flags = ["-fprofile-instr-generate"]),
+                ],
+            ),
+        ],
+        requires = [feature_set(features = ["coverage"])],
+        provides = ["profile"],
+    )
+
+    strip_debug_symbols_feature = feature(
+        name = "strip_debug_symbols",
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = ["-Wl,-S"],
+                        expand_if_available = "strip_debug_symbols",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    build_interface_libraries_feature = feature(
+        name = "build_interface_libraries",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.cpp_link_dynamic_library,
+                    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+                    ACTION_NAMES.lto_index_for_dynamic_library,
+                    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "%{generate_interface_library}",
+                            "%{interface_library_builder_path}",
+                            "%{interface_library_input_path}",
+                            "%{interface_library_output_path}",
+                        ],
+                        expand_if_available = "generate_interface_library",
+                    ),
+                ],
+                with_features = [
+                    with_feature_set(
+                        features = ["supports_interface_shared_libraries"],
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    libraries_to_link_feature = feature(
+        name = "libraries_to_link",
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        iterate_over = "libraries_to_link",
+                        flag_groups = [
+                            flag_group(
+                                flags = ["-Wl,--start-lib"],
+                                expand_if_equal = variable_with_value(
+                                    name = "libraries_to_link.type",
+                                    value = "object_file_group",
+                                ),
+                            ),
+                            flag_group(
+                                flags = ["-Wl,-whole-archive"],
+                                expand_if_true =
+                                    "libraries_to_link.is_whole_archive",
+                            ),
+                            flag_group(
+                                flags = ["%{libraries_to_link.object_files}"],
+                                iterate_over = "libraries_to_link.object_files",
+                                expand_if_equal = variable_with_value(
+                                    name = "libraries_to_link.type",
+                                    value = "object_file_group",
+                                ),
+                            ),
+                            flag_group(
+                                flags = ["%{libraries_to_link.name}"],
+                                expand_if_equal = variable_with_value(
+                                    name = "libraries_to_link.type",
+                                    value = "object_file",
+                                ),
+                            ),
+                            flag_group(
+                                flags = ["%{libraries_to_link.name}"],
+                                expand_if_equal = variable_with_value(
+                                    name = "libraries_to_link.type",
+                                    value = "interface_library",
+                                ),
+                            ),
+                            flag_group(
+                                flags = ["%{libraries_to_link.name}"],
+                                expand_if_equal = variable_with_value(
+                                    name = "libraries_to_link.type",
+                                    value = "static_library",
+                                ),
+                            ),
+                            flag_group(
+                                flags = ["-l%{libraries_to_link.name}"],
+                                expand_if_equal = variable_with_value(
+                                    name = "libraries_to_link.type",
+                                    value = "dynamic_library",
+                                ),
+                            ),
+                            flag_group(
+                                flags = ["-l:%{libraries_to_link.name}"],
+                                expand_if_equal = variable_with_value(
+                                    name = "libraries_to_link.type",
+                                    value = "versioned_dynamic_library",
+                                ),
+                            ),
+                            flag_group(
+                                flags = ["-Wl,-no-whole-archive"],
+                                expand_if_true = "libraries_to_link.is_whole_archive",
+                            ),
+                            flag_group(
+                                flags = ["-Wl,--end-lib"],
+                                expand_if_equal = variable_with_value(
+                                    name = "libraries_to_link.type",
+                                    value = "object_file_group",
+                                ),
+                            ),
+                        ],
+                        expand_if_available = "libraries_to_link",
+                    ),
+                    flag_group(
+                        flags = ["-Wl,@%{thinlto_param_file}"],
+                        expand_if_true = "thinlto_param_file",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    user_link_flags_feature = feature(
+        name = "user_link_flags",
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = ["%{user_link_flags}"],
+                        iterate_over = "user_link_flags",
+                        expand_if_available = "user_link_flags",
+                    ),
+                ] + ([flag_group(flags = ctx.attr.link_libs)] if ctx.attr.link_libs else []),
+            ),
+        ],
+    )
+
+    fdo_prefetch_hints_feature = feature(
+        name = "fdo_prefetch_hints",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.lto_backend,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-Xclang-only=-mllvm",
+                            "-Xclang-only=-prefetch-hints-file=%{fdo_prefetch_hints_path}",
+                        ],
+                        expand_if_available = "fdo_prefetch_hints_path",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    linkstamps_feature = feature(
+        name = "linkstamps",
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = ["%{linkstamp_paths}"],
+                        iterate_over = "linkstamp_paths",
+                        expand_if_available = "linkstamp_paths",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    gcc_coverage_map_format_feature = feature(
+        name = "gcc_coverage_map_format",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_module_compile,
+                    ACTION_NAMES.objc_compile,
+                    ACTION_NAMES.objcpp_compile,
+                    "objc-executable",
+                    "objc++-executable",
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["-fprofile-arcs", "-ftest-coverage"],
+                        expand_if_available = "gcov_gcno_file",
+                    ),
+                ],
+            ),
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [flag_group(flags = ["--coverage"])],
+            ),
+        ],
+        requires = [feature_set(features = ["coverage"])],
+        provides = ["profile"],
+    )
+
+    archiver_flags_feature = feature(
+        name = "archiver_flags",
+        flag_sets = [
+            flag_set(
+                actions = [ACTION_NAMES.cpp_link_static_library],
+                flag_groups = [
+                    flag_group(flags = ["rcsD"]),
+                    flag_group(
+                        flags = ["%{output_execpath}"],
+                        expand_if_available = "output_execpath",
+                    ),
+                ],
+            ),
+            flag_set(
+                actions = [ACTION_NAMES.cpp_link_static_library],
+                flag_groups = [
+                    flag_group(
+                        iterate_over = "libraries_to_link",
+                        flag_groups = [
+                            flag_group(
+                                flags = ["%{libraries_to_link.name}"],
+                                expand_if_equal = variable_with_value(
+                                    name = "libraries_to_link.type",
+                                    value = "object_file",
+                                ),
+                            ),
+                            flag_group(
+                                flags = ["%{libraries_to_link.object_files}"],
+                                iterate_over = "libraries_to_link.object_files",
+                                expand_if_equal = variable_with_value(
+                                    name = "libraries_to_link.type",
+                                    value = "object_file_group",
+                                ),
+                            ),
+                        ],
+                        expand_if_available = "libraries_to_link",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    force_pic_flags_feature = feature(
+        name = "force_pic_flags",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.cpp_link_executable,
+                    ACTION_NAMES.lto_index_for_executable,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["-pie"],
+                        expand_if_available = "force_pic",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    dependency_file_feature = feature(
+        name = "dependency_file",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.assemble,
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_module_compile,
+                    ACTION_NAMES.objc_compile,
+                    ACTION_NAMES.objcpp_compile,
+                    ACTION_NAMES.cpp_header_parsing,
+                    ACTION_NAMES.clif_match,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = ["-MD", "-MF", "%{dependency_file}"],
+                        expand_if_available = "dependency_file",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    dynamic_library_linker_tool_path = tool_paths
+    dynamic_library_linker_tool_feature = feature(
+        name = "dynamic_library_linker_tool",
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.cpp_link_dynamic_library,
+                    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+                    ACTION_NAMES.lto_index_for_dynamic_library,
+                    ACTION_NAMES.lto_index_for_nodeps_dynamic_library,
+                ],
+                flag_groups = [
+                    flag_group(
+                        flags = [" + cppLinkDynamicLibraryToolPath + "],
+                        expand_if_available = "generate_interface_library",
+                    ),
+                ],
+                with_features = [
+                    with_feature_set(
+                        features = ["supports_interface_shared_libraries"],
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    output_execpath_flags_feature = feature(
+        name = "output_execpath_flags",
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = ["-o", "%{output_execpath}"],
+                        expand_if_available = "output_execpath",
+                    ),
+                ],
+            ),
+        ],
+    )
+
+    # Note that we also set --coverage for c++-link-nodeps-dynamic-library. The
+    # generated code contains references to gcov symbols, and the dynamic linker
+    # can't resolve them unless the library is linked against gcov.
+    coverage_feature = feature(
+        name = "coverage",
+        provides = ["profile"],
+        flag_sets = [
+            flag_set(
+                actions = [
+                    ACTION_NAMES.preprocess_assemble,
+                    ACTION_NAMES.c_compile,
+                    ACTION_NAMES.cpp_compile,
+                    ACTION_NAMES.cpp_header_parsing,
+                    ACTION_NAMES.cpp_module_compile,
+                ],
+                flag_groups = ([
+                    flag_group(flags = ctx.attr.coverage_compile_flags),
+                ] if ctx.attr.coverage_compile_flags else []),
+            ),
+            flag_set(
+                actions = all_link_actions + lto_index_actions,
+                flag_groups = ([
+                    flag_group(flags = ctx.attr.coverage_link_flags),
+                ] if ctx.attr.coverage_link_flags else []),
+            ),
+        ],
+    )
+
+    is_linux = ctx.attr.target_libc != "macosx"
+
+    # TODO(#8303): Mac crosstool should also declare every feature.
+    if is_linux:
+        features = [
+            dependency_file_feature,
+            random_seed_feature,
+            pic_feature,
+            per_object_debug_info_feature,
+            preprocessor_defines_feature,
+            includes_feature,
+            include_paths_feature,
+            fdo_instrument_feature,
+            cs_fdo_instrument_feature,
+            cs_fdo_optimize_feature,
+            fdo_prefetch_hints_feature,
+            autofdo_feature,
+            build_interface_libraries_feature,
+            dynamic_library_linker_tool_feature,
+            symbol_counts_feature,
+            shared_flag_feature,
+            linkstamps_feature,
+            output_execpath_flags_feature,
+            runtime_library_search_directories_feature,
+            library_search_directories_feature,
+            archiver_flags_feature,
+            force_pic_flags_feature,
+            fission_support_feature,
+            strip_debug_symbols_feature,
+            coverage_feature,
+            supports_pic_feature,
+        ] + (
+            [
+                supports_start_end_lib_feature,
+            ] if ctx.attr.supports_start_end_lib else []
+        ) + [
+            default_compile_flags_feature,
+            default_link_flags_feature,
+            libraries_to_link_feature,
+            user_link_flags_feature,
+            static_libgcc_feature,
+            fdo_optimize_feature,
+            supports_dynamic_linker_feature,
+            dbg_feature,
+            opt_feature,
+            user_compile_flags_feature,
+            sysroot_feature,
+            unfiltered_compile_flags_feature,
+        ]
+    else:
+        features = [
+            supports_pic_feature,
+        ] + (
+            [
+                supports_start_end_lib_feature,
+            ] if ctx.attr.supports_start_end_lib else []
+        ) + [
+            coverage_feature,
+            default_compile_flags_feature,
+            default_link_flags_feature,
+            fdo_optimize_feature,
+            supports_dynamic_linker_feature,
+            dbg_feature,
+            opt_feature,
+            user_compile_flags_feature,
+            sysroot_feature,
+            unfiltered_compile_flags_feature,
+        ]
+
+    return cc_common.create_cc_toolchain_config_info(
+        ctx = ctx,
+        features = features,
+        action_configs = action_configs,
+        cxx_builtin_include_directories = ctx.attr.cxx_builtin_include_directories,
+        toolchain_identifier = ctx.attr.toolchain_identifier,
+        host_system_name = ctx.attr.host_system_name,
+        target_system_name = ctx.attr.target_system_name,
+        target_cpu = ctx.attr.cpu,
+        target_libc = ctx.attr.target_libc,
+        compiler = ctx.attr.compiler,
+        abi_version = ctx.attr.abi_version,
+        abi_libc_version = ctx.attr.abi_libc_version,
+        tool_paths = tool_paths,
+    )
+
+cc_toolchain_config = rule(
+    implementation = _impl,
+    attrs = {
+        "cpu": attr.string(mandatory = True),
+        "compiler": attr.string(mandatory = True),
+        "toolchain_identifier": attr.string(mandatory = True),
+        "host_system_name": attr.string(mandatory = True),
+        "target_system_name": attr.string(mandatory = True),
+        "target_libc": attr.string(mandatory = True),
+        "abi_version": attr.string(mandatory = True),
+        "abi_libc_version": attr.string(mandatory = True),
+        "cxx_builtin_include_directories": attr.string_list(),
+        "tool_paths": attr.string_dict(),
+        "compile_flags": attr.string_list(),
+        "dbg_compile_flags": attr.string_list(),
+        "opt_compile_flags": attr.string_list(),
+        "cxx_flags": attr.string_list(),
+        "link_flags": attr.string_list(),
+        "link_libs": attr.string_list(),
+        "opt_link_flags": attr.string_list(),
+        "unfiltered_compile_flags": attr.string_list(),
+        "coverage_compile_flags": attr.string_list(),
+        "coverage_link_flags": attr.string_list(),
+        "supports_start_end_lib": attr.bool(),
+    },
+    provides = [CcToolchainConfigInfo],
+)
diff --git a/cc/private/toolchain/vc_installation_error.bat.tpl b/cc/private/toolchain/vc_installation_error.bat.tpl
new file mode 100644
index 0000000..b796585
--- /dev/null
+++ b/cc/private/toolchain/vc_installation_error.bat.tpl
@@ -0,0 +1,24 @@
+:: Copyright 2017 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.
+
+@echo OFF
+
+echo. 1>&2
+echo The target you are compiling requires Visual C++ build tools. 1>&2
+echo Bazel couldn't find a valid Visual C++ build tools installation on your machine. 1>&2
+%{vc_error_message}
+echo Please check your installation following https://docs.bazel.build/versions/master/windows.html#using 1>&2
+echo. 1>&2
+
+exit /b 1
diff --git a/cc/private/toolchain/windows_cc_configure.bzl b/cc/private/toolchain/windows_cc_configure.bzl
new file mode 100644
index 0000000..a151beb
--- /dev/null
+++ b/cc/private/toolchain/windows_cc_configure.bzl
@@ -0,0 +1,692 @@
+# pylint: disable=g-bad-file-header
+# Copyright 2016 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.
+"""Configuring the C++ toolchain on Windows."""
+
+load(
+    "@rules_cc//cc/private/toolchain:lib_cc_configure.bzl",
+    "auto_configure_fail",
+    "auto_configure_warning",
+    "auto_configure_warning_maybe",
+    "escape_string",
+    "execute",
+    "resolve_labels",
+)
+
+def _get_path_env_var(repository_ctx, name):
+    """Returns a path from an environment variable.
+
+    Removes quotes, replaces '/' with '\', and strips trailing '\'s."""
+    if name in repository_ctx.os.environ:
+        value = repository_ctx.os.environ[name]
+        if value[0] == "\"":
+            if len(value) == 1 or value[-1] != "\"":
+                auto_configure_fail("'%s' environment variable has no trailing quote" % name)
+            value = value[1:-1]
+        if "/" in value:
+            value = value.replace("/", "\\")
+        if value[-1] == "\\":
+            value = value.rstrip("\\")
+        return value
+    else:
+        return None
+
+def _get_temp_env(repository_ctx):
+    """Returns the value of TMP, or TEMP, or if both undefined then C:\\Windows."""
+    tmp = _get_path_env_var(repository_ctx, "TMP")
+    if not tmp:
+        tmp = _get_path_env_var(repository_ctx, "TEMP")
+    if not tmp:
+        tmp = "C:\\Windows\\Temp"
+        auto_configure_warning(
+            "neither 'TMP' nor 'TEMP' environment variables are set, using '%s' as default" % tmp,
+        )
+    return tmp
+
+def _get_escaped_windows_msys_starlark_content(repository_ctx, use_mingw = False):
+    """Return the content of msys cc toolchain rule."""
+    msys_root = ""
+    bazel_sh = _get_path_env_var(repository_ctx, "BAZEL_SH")
+    if bazel_sh:
+        bazel_sh = bazel_sh.replace("\\", "/").lower()
+        tokens = bazel_sh.rsplit("/", 1)
+        if tokens[0].endswith("/usr/bin"):
+            msys_root = tokens[0][:len(tokens[0]) - len("usr/bin")]
+        elif tokens[0].endswith("/bin"):
+            msys_root = tokens[0][:len(tokens[0]) - len("bin")]
+
+    prefix = "mingw64" if use_mingw else "usr"
+    tool_path_prefix = escape_string(msys_root) + prefix
+    tool_bin_path = tool_path_prefix + "/bin"
+    tool_path = {}
+
+    for tool in ["ar", "compat-ld", "cpp", "dwp", "gcc", "gcov", "ld", "nm", "objcopy", "objdump", "strip"]:
+        if msys_root:
+            tool_path[tool] = tool_bin_path + "/" + tool
+        else:
+            tool_path[tool] = "msys_gcc_installation_error.bat"
+    tool_paths = ",\n        ".join(['"%s": "%s"' % (k, v) for k, v in tool_path.items()])
+    include_directories = ('        "%s/",\n        ' % tool_path_prefix) if msys_root else ""
+    return tool_paths, tool_bin_path, include_directories
+
+def _get_system_root(repository_ctx):
+    """Get System root path on Windows, default is C:\\Windows. Doesn't %-escape the result."""
+    systemroot = _get_path_env_var(repository_ctx, "SYSTEMROOT")
+    if not systemroot:
+        systemroot = "C:\\Windows"
+        auto_configure_warning_maybe(
+            repository_ctx,
+            "SYSTEMROOT is not set, using default SYSTEMROOT=C:\\Windows",
+        )
+    return escape_string(systemroot)
+
+def _add_system_root(repository_ctx, env):
+    """Running VCVARSALL.BAT and VCVARSQUERYREGISTRY.BAT need %SYSTEMROOT%\\\\system32 in PATH."""
+    if "PATH" not in env:
+        env["PATH"] = ""
+    env["PATH"] = env["PATH"] + ";" + _get_system_root(repository_ctx) + "\\system32"
+    return env
+
+def find_vc_path(repository_ctx):
+    """Find Visual C++ build tools install path. Doesn't %-escape the result."""
+
+    # 1. Check if BAZEL_VC or BAZEL_VS is already set by user.
+    bazel_vc = _get_path_env_var(repository_ctx, "BAZEL_VC")
+    if bazel_vc:
+        if repository_ctx.path(bazel_vc).exists:
+            return bazel_vc
+        else:
+            auto_configure_warning_maybe(
+                repository_ctx,
+                "%BAZEL_VC% is set to non-existent path, ignoring.",
+            )
+
+    bazel_vs = _get_path_env_var(repository_ctx, "BAZEL_VS")
+    if bazel_vs:
+        if repository_ctx.path(bazel_vs).exists:
+            bazel_vc = bazel_vs + "\\VC"
+            if repository_ctx.path(bazel_vc).exists:
+                return bazel_vc
+            else:
+                auto_configure_warning_maybe(
+                    repository_ctx,
+                    "No 'VC' directory found under %BAZEL_VS%, ignoring.",
+                )
+        else:
+            auto_configure_warning_maybe(
+                repository_ctx,
+                "%BAZEL_VS% is set to non-existent path, ignoring.",
+            )
+
+    auto_configure_warning_maybe(
+        repository_ctx,
+        "Neither %BAZEL_VC% nor %BAZEL_VS% are set, start looking for the latest Visual C++" +
+        " installed.",
+    )
+
+    # 2. Check if VS%VS_VERSION%COMNTOOLS is set, if true then try to find and use
+    # vcvarsqueryregistry.bat / VsDevCmd.bat to detect VC++.
+    auto_configure_warning_maybe(repository_ctx, "Looking for VS%VERSION%COMNTOOLS environment variables, " +
+                                                 "eg. VS140COMNTOOLS")
+    for vscommontools_env, script in [
+        ("VS160COMNTOOLS", "VsDevCmd.bat"),
+        ("VS150COMNTOOLS", "VsDevCmd.bat"),
+        ("VS140COMNTOOLS", "vcvarsqueryregistry.bat"),
+        ("VS120COMNTOOLS", "vcvarsqueryregistry.bat"),
+        ("VS110COMNTOOLS", "vcvarsqueryregistry.bat"),
+        ("VS100COMNTOOLS", "vcvarsqueryregistry.bat"),
+        ("VS90COMNTOOLS", "vcvarsqueryregistry.bat"),
+    ]:
+        if vscommontools_env not in repository_ctx.os.environ:
+            continue
+        script = _get_path_env_var(repository_ctx, vscommontools_env) + "\\" + script
+        if not repository_ctx.path(script).exists:
+            continue
+        repository_ctx.file(
+            "get_vc_dir.bat",
+            "@echo off\n" +
+            "call \"" + script + "\"\n" +
+            "echo %VCINSTALLDIR%",
+            True,
+        )
+        env = _add_system_root(repository_ctx, repository_ctx.os.environ)
+        vc_dir = execute(repository_ctx, ["./get_vc_dir.bat"], environment = env)
+
+        auto_configure_warning_maybe(repository_ctx, "Visual C++ build tools found at %s" % vc_dir)
+        return vc_dir
+
+    # 3. User might have purged all environment variables. If so, look for Visual C++ in registry.
+    # Works for Visual Studio 2017 and older. (Does not work for Visual Studio 2019 Preview.)
+    # TODO(laszlocsomor): check if "16.0" also has this registry key, after VS 2019 is released.
+    auto_configure_warning_maybe(repository_ctx, "Looking for Visual C++ through registry")
+    reg_binary = _get_system_root(repository_ctx) + "\\system32\\reg.exe"
+    vc_dir = None
+    for key, suffix in (("VC7", ""), ("VS7", "\\VC")):
+        for version in ["15.0", "14.0", "12.0", "11.0", "10.0", "9.0", "8.0"]:
+            if vc_dir:
+                break
+            result = repository_ctx.execute([reg_binary, "query", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\" + key, "/v", version])
+            auto_configure_warning_maybe(repository_ctx, "registry query result for VC %s:\n\nSTDOUT(start)\n%s\nSTDOUT(end)\nSTDERR(start):\n%s\nSTDERR(end)\n" %
+                                                         (version, result.stdout, result.stderr))
+            if not result.stderr:
+                for line in result.stdout.split("\n"):
+                    line = line.strip()
+                    if line.startswith(version) and line.find("REG_SZ") != -1:
+                        vc_dir = line[line.find("REG_SZ") + len("REG_SZ"):].strip() + suffix
+    if vc_dir:
+        auto_configure_warning_maybe(repository_ctx, "Visual C++ build tools found at %s" % vc_dir)
+        return vc_dir
+
+    # 4. Check default directories for VC installation
+    auto_configure_warning_maybe(repository_ctx, "Looking for default Visual C++ installation directory")
+    program_files_dir = _get_path_env_var(repository_ctx, "PROGRAMFILES(X86)")
+    if not program_files_dir:
+        program_files_dir = "C:\\Program Files (x86)"
+        auto_configure_warning_maybe(
+            repository_ctx,
+            "'PROGRAMFILES(X86)' environment variable is not set, using '%s' as default" % program_files_dir,
+        )
+    for path in [
+        "Microsoft Visual Studio\\2019\\Preview\\VC",
+        "Microsoft Visual Studio\\2019\\BuildTools\\VC",
+        "Microsoft Visual Studio\\2019\\Community\\VC",
+        "Microsoft Visual Studio\\2019\\Professional\\VC",
+        "Microsoft Visual Studio\\2019\\Enterprise\\VC",
+        "Microsoft Visual Studio\\2017\\BuildTools\\VC",
+        "Microsoft Visual Studio\\2017\\Community\\VC",
+        "Microsoft Visual Studio\\2017\\Professional\\VC",
+        "Microsoft Visual Studio\\2017\\Enterprise\\VC",
+        "Microsoft Visual Studio 14.0\\VC",
+    ]:
+        path = program_files_dir + "\\" + path
+        if repository_ctx.path(path).exists:
+            vc_dir = path
+            break
+
+    if not vc_dir:
+        auto_configure_warning_maybe(repository_ctx, "Visual C++ build tools not found.")
+        return None
+    auto_configure_warning_maybe(repository_ctx, "Visual C++ build tools found at %s" % vc_dir)
+    return vc_dir
+
+def _is_vs_2017_or_2019(vc_path):
+    """Check if the installed VS version is Visual Studio 2017."""
+
+    # In VS 2017 and 2019, the location of VC is like:
+    # C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\
+    # In VS 2015 or older version, it is like:
+    # C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\
+    return vc_path.find("2017") != -1 or vc_path.find("2019") != -1
+
+def _find_vcvars_bat_script(repository_ctx, vc_path):
+    """Find batch script to set up environment variables for VC. Doesn't %-escape the result."""
+    if _is_vs_2017_or_2019(vc_path):
+        vcvars_script = vc_path + "\\Auxiliary\\Build\\VCVARSALL.BAT"
+    else:
+        vcvars_script = vc_path + "\\VCVARSALL.BAT"
+
+    if not repository_ctx.path(vcvars_script).exists:
+        return None
+
+    return vcvars_script
+
+def _is_support_vcvars_ver(vc_full_version):
+    """-vcvars_ver option is supported from version 14.11.25503 (VS 2017 version 15.3)."""
+    version = [int(i) for i in vc_full_version.split(".")]
+    min_version = [14, 11, 25503]
+    return version >= min_version
+
+def _is_support_winsdk_selection(repository_ctx, vc_path):
+    """Windows SDK selection is supported with VC 2017 / 2019 or with full VS 2015 installation."""
+    if _is_vs_2017_or_2019(vc_path):
+        return True
+
+    # By checking the source code of VCVARSALL.BAT in VC 2015, we know that
+    # when devenv.exe or wdexpress.exe exists, VCVARSALL.BAT supports Windows SDK selection.
+    vc_common_ide = repository_ctx.path(vc_path).dirname.get_child("Common7").get_child("IDE")
+    for tool in ["devenv.exe", "wdexpress.exe"]:
+        if vc_common_ide.get_child(tool).exists:
+            return True
+    return False
+
+def setup_vc_env_vars(repository_ctx, vc_path, envvars = [], allow_empty = False, escape = True):
+    """Get environment variables set by VCVARSALL.BAT script. Doesn't %-escape the result!
+
+    Args:
+        repository_ctx: the repository_ctx object
+        vc_path: Visual C++ root directory
+        envvars: list of envvars to retrieve; default is ["PATH", "INCLUDE", "LIB", "WINDOWSSDKDIR"]
+        allow_empty: allow unset envvars; if False then report errors for those
+        escape: if True, escape "\" as "\\" and "%" as "%%" in the envvar values
+
+    Returns:
+        dictionary of the envvars
+    """
+    if not envvars:
+        envvars = ["PATH", "INCLUDE", "LIB", "WINDOWSSDKDIR"]
+
+    vcvars_script = _find_vcvars_bat_script(repository_ctx, vc_path)
+    if not vcvars_script:
+        auto_configure_fail("Cannot find VCVARSALL.BAT script under %s" % vc_path)
+
+    # Getting Windows SDK version set by user.
+    # Only supports VC 2017 & 2019 and VC 2015 with full VS installation.
+    winsdk_version = _get_winsdk_full_version(repository_ctx)
+    if winsdk_version and not _is_support_winsdk_selection(repository_ctx, vc_path):
+        auto_configure_warning(("BAZEL_WINSDK_FULL_VERSION=%s is ignored, " +
+                                "because standalone Visual C++ Build Tools 2015 doesn't support specifying Windows " +
+                                "SDK version, please install the full VS 2015 or use VC 2017/2019.") % winsdk_version)
+        winsdk_version = ""
+
+    # Get VC version set by user. Only supports VC 2017 & 2019.
+    vcvars_ver = ""
+    if _is_vs_2017_or_2019(vc_path):
+        full_version = _get_vc_full_version(repository_ctx, vc_path)
+
+        # Because VCVARSALL.BAT is from the latest VC installed, so we check if the latest
+        # version supports -vcvars_ver or not.
+        if _is_support_vcvars_ver(_get_latest_subversion(repository_ctx, vc_path)):
+            vcvars_ver = "-vcvars_ver=" + full_version
+
+    cmd = "\"%s\" amd64 %s %s" % (vcvars_script, winsdk_version, vcvars_ver)
+    print_envvars = ",".join(["{k}=%{k}%".format(k = k) for k in envvars])
+    repository_ctx.file(
+        "get_env.bat",
+        "@echo off\n" +
+        ("call %s > NUL \n" % cmd) + ("echo %s \n" % print_envvars),
+        True,
+    )
+    env = _add_system_root(repository_ctx, {k: "" for k in envvars})
+    envs = execute(repository_ctx, ["./get_env.bat"], environment = env).split(",")
+    env_map = {}
+    for env in envs:
+        key, value = env.split("=", 1)
+        env_map[key] = escape_string(value.replace("\\", "\\\\")) if escape else value
+    if not allow_empty:
+        _check_env_vars(env_map, cmd, expected = envvars)
+    return env_map
+
+def _check_env_vars(env_map, cmd, expected):
+    for env in expected:
+        if not env_map.get(env):
+            auto_configure_fail(
+                "Setting up VC environment variables failed, %s is not set by the following command:\n    %s" % (env, cmd),
+            )
+
+def _get_latest_subversion(repository_ctx, vc_path):
+    """Get the latest subversion of a VS 2017/2019 installation.
+
+    For VS 2017 & 2019, there could be multiple versions of VC build tools.
+    The directories are like:
+      <vc_path>\\Tools\\MSVC\\14.10.24930\\bin\\HostX64\\x64
+      <vc_path>\\Tools\\MSVC\\14.16.27023\\bin\\HostX64\\x64
+    This function should return 14.16.27023 in this case."""
+    versions = [path.basename for path in repository_ctx.path(vc_path + "\\Tools\\MSVC").readdir()]
+    if len(versions) < 1:
+        auto_configure_warning_maybe(repository_ctx, "Cannot find any VC installation under BAZEL_VC(%s)" % vc_path)
+        return None
+
+    # Parse the version string into integers, then sort the integers to prevent textual sorting.
+    version_list = []
+    for version in versions:
+        parts = [int(i) for i in version.split(".")]
+        version_list.append((parts, version))
+
+    version_list = sorted(version_list)
+    latest_version = version_list[-1][1]
+
+    auto_configure_warning_maybe(repository_ctx, "Found the following VC verisons:\n%s\n\nChoosing the latest version = %s" % ("\n".join(versions), latest_version))
+    return latest_version
+
+def _get_vc_full_version(repository_ctx, vc_path):
+    """Return the value of BAZEL_VC_FULL_VERSION if defined, otherwise the latest version."""
+    if "BAZEL_VC_FULL_VERSION" in repository_ctx.os.environ:
+        return repository_ctx.os.environ["BAZEL_VC_FULL_VERSION"]
+    return _get_latest_subversion(repository_ctx, vc_path)
+
+def _get_winsdk_full_version(repository_ctx):
+    """Return the value of BAZEL_WINSDK_FULL_VERSION if defined, otherwise an empty string."""
+    return repository_ctx.os.environ.get("BAZEL_WINSDK_FULL_VERSION", default = "")
+
+def find_msvc_tool(repository_ctx, vc_path, tool):
+    """Find the exact path of a specific build tool in MSVC. Doesn't %-escape the result."""
+    tool_path = None
+    if _is_vs_2017_or_2019(vc_path):
+        full_version = _get_vc_full_version(repository_ctx, vc_path)
+        if full_version:
+            tool_path = "%s\\Tools\\MSVC\\%s\\bin\\HostX64\\x64\\%s" % (vc_path, full_version, tool)
+    else:
+        # For VS 2015 and older version, the tools are under:
+        # C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64
+        tool_path = vc_path + "\\bin\\amd64\\" + tool
+
+    if not tool_path or not repository_ctx.path(tool_path).exists:
+        return None
+
+    return tool_path.replace("\\", "/")
+
+def _find_missing_vc_tools(repository_ctx, vc_path):
+    """Check if any required tool is missing under given VC path."""
+    missing_tools = []
+    if not _find_vcvars_bat_script(repository_ctx, vc_path):
+        missing_tools.append("VCVARSALL.BAT")
+
+    for tool in ["cl.exe", "link.exe", "lib.exe", "ml64.exe"]:
+        if not find_msvc_tool(repository_ctx, vc_path, tool):
+            missing_tools.append(tool)
+
+    return missing_tools
+
+def _is_support_debug_fastlink(repository_ctx, linker):
+    """Run linker alone to see if it supports /DEBUG:FASTLINK."""
+    if _use_clang_cl(repository_ctx):
+        # LLVM's lld-link.exe doesn't support /DEBUG:FASTLINK.
+        return False
+    result = execute(repository_ctx, [linker], expect_failure = True)
+    return result.find("/DEBUG[:{FASTLINK|FULL|NONE}]") != -1
+
+def find_llvm_path(repository_ctx):
+    """Find LLVM install path."""
+
+    # 1. Check if BAZEL_LLVM is already set by user.
+    bazel_llvm = _get_path_env_var(repository_ctx, "BAZEL_LLVM")
+    if bazel_llvm:
+        return bazel_llvm
+
+    auto_configure_warning_maybe(repository_ctx, "'BAZEL_LLVM' is not set, " +
+                                                 "start looking for LLVM installation on machine.")
+
+    # 2. Look for LLVM installation through registry.
+    auto_configure_warning_maybe(repository_ctx, "Looking for LLVM installation through registry")
+    reg_binary = _get_system_root(repository_ctx) + "\\system32\\reg.exe"
+    llvm_dir = None
+    result = repository_ctx.execute([reg_binary, "query", "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\LLVM\\LLVM"])
+    auto_configure_warning_maybe(repository_ctx, "registry query result for LLVM:\n\nSTDOUT(start)\n%s\nSTDOUT(end)\nSTDERR(start):\n%s\nSTDERR(end)\n" %
+                                                 (result.stdout, result.stderr))
+    if not result.stderr:
+        for line in result.stdout.split("\n"):
+            line = line.strip()
+            if line.startswith("(Default)") and line.find("REG_SZ") != -1:
+                llvm_dir = line[line.find("REG_SZ") + len("REG_SZ"):].strip()
+    if llvm_dir:
+        auto_configure_warning_maybe(repository_ctx, "LLVM installation found at %s" % llvm_dir)
+        return llvm_dir
+
+    # 3. Check default directories for LLVM installation
+    auto_configure_warning_maybe(repository_ctx, "Looking for default LLVM installation directory")
+    program_files_dir = _get_path_env_var(repository_ctx, "PROGRAMFILES")
+    if not program_files_dir:
+        program_files_dir = "C:\\Program Files"
+        auto_configure_warning_maybe(
+            repository_ctx,
+            "'PROGRAMFILES' environment variable is not set, using '%s' as default" % program_files_dir,
+        )
+    path = program_files_dir + "\\LLVM"
+    if repository_ctx.path(path).exists:
+        llvm_dir = path
+
+    if not llvm_dir:
+        auto_configure_warning_maybe(repository_ctx, "LLVM installation not found.")
+        return None
+    auto_configure_warning_maybe(repository_ctx, "LLVM installation found at %s" % llvm_dir)
+    return llvm_dir
+
+def find_llvm_tool(repository_ctx, llvm_path, tool):
+    """Find the exact path of a specific build tool in LLVM. Doesn't %-escape the result."""
+    tool_path = llvm_path + "\\bin\\" + tool
+
+    if not repository_ctx.path(tool_path).exists:
+        return None
+
+    return tool_path.replace("\\", "/")
+
+def _use_clang_cl(repository_ctx):
+    """Returns True if USE_CLANG_CL is set to 1."""
+    return repository_ctx.os.environ.get("USE_CLANG_CL", default = "0") == "1"
+
+def _find_missing_llvm_tools(repository_ctx, llvm_path):
+    """Check if any required tool is missing under given LLVM path."""
+    missing_tools = []
+    for tool in ["clang-cl.exe", "lld-link.exe", "llvm-lib.exe"]:
+        if not find_llvm_tool(repository_ctx, llvm_path, tool):
+            missing_tools.append(tool)
+
+    return missing_tools
+
+def _get_clang_version(repository_ctx, clang_cl):
+    result = repository_ctx.execute([clang_cl, "-v"])
+    if result.return_code != 0:
+        auto_configure_fail("Failed to get clang version by running \"%s -v\"" % clang_cl)
+
+    # Stderr should look like "clang version X.X.X ..."
+    return result.stderr.strip().split(" ")[2]
+
+def _get_msys_mingw_vars(repository_ctx):
+    """Get the variables we need to populate the msys/mingw toolchains."""
+    tool_paths, tool_bin_path, inc_dir_msys = _get_escaped_windows_msys_starlark_content(repository_ctx)
+    tool_paths_mingw, tool_bin_path_mingw, inc_dir_mingw = _get_escaped_windows_msys_starlark_content(repository_ctx, use_mingw = True)
+    msys_mingw_vars = {
+        "%{cxx_builtin_include_directories}": inc_dir_msys,
+        "%{mingw_cxx_builtin_include_directories}": inc_dir_mingw,
+        "%{tool_paths}": tool_paths,
+        "%{mingw_tool_paths}": tool_paths_mingw,
+        "%{tool_bin_path}": tool_bin_path,
+        "%{mingw_tool_bin_path}": tool_bin_path_mingw,
+    }
+    return msys_mingw_vars
+
+def _get_msvc_vars(repository_ctx, paths):
+    """Get the variables we need to populate the MSVC toolchains."""
+    msvc_vars = dict()
+    vc_path = find_vc_path(repository_ctx)
+    missing_tools = None
+    if not vc_path:
+        repository_ctx.template(
+            "vc_installation_error.bat",
+            paths["@rules_cc//cc/private/toolchain:vc_installation_error.bat.tpl"],
+            {"%{vc_error_message}": ""},
+        )
+    else:
+        missing_tools = _find_missing_vc_tools(repository_ctx, vc_path)
+        if missing_tools:
+            message = "\r\n".join([
+                "echo. 1>&2",
+                "echo Visual C++ build tools seems to be installed at %s 1>&2" % vc_path,
+                "echo But Bazel can't find the following tools: 1>&2",
+                "echo     %s 1>&2" % ", ".join(missing_tools),
+                "echo. 1>&2",
+            ])
+            repository_ctx.template(
+                "vc_installation_error.bat",
+                paths["@rules_cc//cc/private/toolchain:vc_installation_error.bat.tpl"],
+                {"%{vc_error_message}": message},
+            )
+
+    if not vc_path or missing_tools:
+        msvc_vars = {
+            "%{msvc_env_tmp}": "msvc_not_found",
+            "%{msvc_env_path}": "msvc_not_found",
+            "%{msvc_env_include}": "msvc_not_found",
+            "%{msvc_env_lib}": "msvc_not_found",
+            "%{msvc_cl_path}": "vc_installation_error.bat",
+            "%{msvc_ml_path}": "vc_installation_error.bat",
+            "%{msvc_link_path}": "vc_installation_error.bat",
+            "%{msvc_lib_path}": "vc_installation_error.bat",
+            "%{dbg_mode_debug_flag}": "/DEBUG",
+            "%{fastbuild_mode_debug_flag}": "/DEBUG",
+            "%{msvc_cxx_builtin_include_directories}": "",
+        }
+        return msvc_vars
+
+    env = setup_vc_env_vars(repository_ctx, vc_path)
+    escaped_paths = escape_string(env["PATH"])
+    escaped_include_paths = escape_string(env["INCLUDE"])
+    escaped_lib_paths = escape_string(env["LIB"])
+    escaped_tmp_dir = escape_string(_get_temp_env(repository_ctx).replace("\\", "\\\\"))
+
+    llvm_path = ""
+    if _use_clang_cl(repository_ctx):
+        llvm_path = find_llvm_path(repository_ctx)
+        if not llvm_path:
+            auto_configure_fail("\nUSE_CLANG_CL is set to 1, but Bazel cannot find Clang installation on your system.\n" +
+                                "Please install Clang via http://releases.llvm.org/download.html\n")
+        cl_path = find_llvm_tool(repository_ctx, llvm_path, "clang-cl.exe")
+        link_path = find_llvm_tool(repository_ctx, llvm_path, "lld-link.exe")
+        if not link_path:
+            link_path = find_msvc_tool(repository_ctx, vc_path, "link.exe")
+        lib_path = find_llvm_tool(repository_ctx, llvm_path, "llvm-lib.exe")
+        if not lib_path:
+            lib_path = find_msvc_tool(repository_ctx, vc_path, "lib.exe")
+    else:
+        cl_path = find_msvc_tool(repository_ctx, vc_path, "cl.exe")
+        link_path = find_msvc_tool(repository_ctx, vc_path, "link.exe")
+        lib_path = find_msvc_tool(repository_ctx, vc_path, "lib.exe")
+
+    msvc_ml_path = find_msvc_tool(repository_ctx, vc_path, "ml64.exe")
+    escaped_cxx_include_directories = []
+
+    for path in escaped_include_paths.split(";"):
+        if path:
+            escaped_cxx_include_directories.append("\"%s\"" % path)
+    if llvm_path:
+        clang_version = _get_clang_version(repository_ctx, cl_path)
+        clang_dir = llvm_path + "\\lib\\clang\\" + clang_version
+        clang_include_path = (clang_dir + "\\include").replace("\\", "\\\\")
+        escaped_cxx_include_directories.append("\"%s\"" % clang_include_path)
+        clang_lib_path = (clang_dir + "\\lib\\windows").replace("\\", "\\\\")
+        escaped_lib_paths = escaped_lib_paths + ";" + clang_lib_path
+
+    support_debug_fastlink = _is_support_debug_fastlink(repository_ctx, link_path)
+
+    msvc_vars = {
+        "%{msvc_env_tmp}": escaped_tmp_dir,
+        "%{msvc_env_path}": escaped_paths,
+        "%{msvc_env_include}": escaped_include_paths,
+        "%{msvc_env_lib}": escaped_lib_paths,
+        "%{msvc_cl_path}": cl_path,
+        "%{msvc_ml_path}": msvc_ml_path,
+        "%{msvc_link_path}": link_path,
+        "%{msvc_lib_path}": lib_path,
+        "%{dbg_mode_debug_flag}": "/DEBUG:FULL" if support_debug_fastlink else "/DEBUG",
+        "%{fastbuild_mode_debug_flag}": "/DEBUG:FASTLINK" if support_debug_fastlink else "/DEBUG",
+        "%{msvc_cxx_builtin_include_directories}": "        " + ",\n        ".join(escaped_cxx_include_directories),
+    }
+    return msvc_vars
+
+def _get_clang_cl_vars(repository_ctx, paths, msvc_vars):
+    """Get the variables we need to populate the clang-cl toolchains."""
+    llvm_path = find_llvm_path(repository_ctx)
+    error_script = None
+    if msvc_vars["%{msvc_cl_path}"] == "vc_installation_error.bat":
+        error_script = "vc_installation_error.bat"
+    elif not llvm_path:
+        repository_ctx.template(
+            "clang_installation_error.bat",
+            paths["@rules_cc//cc/private/toolchain:clang_installation_error.bat.tpl"],
+            {"%{clang_error_message}": ""},
+        )
+        error_script = "clang_installation_error.bat"
+    else:
+        missing_tools = _find_missing_llvm_tools(repository_ctx, llvm_path)
+        if missing_tools:
+            message = "\r\n".join([
+                "echo. 1>&2",
+                "echo LLVM/Clang seems to be installed at %s 1>&2" % llvm_path,
+                "echo But Bazel can't find the following tools: 1>&2",
+                "echo     %s 1>&2" % ", ".join(missing_tools),
+                "echo. 1>&2",
+            ])
+            repository_ctx.template(
+                "clang_installation_error.bat",
+                paths["@rules_cc//cc/private/toolchain:clang_installation_error.bat.tpl"],
+                {"%{clang_error_message}": message},
+            )
+            error_script = "clang_installation_error.bat"
+
+    if error_script:
+        clang_cl_vars = {
+            "%{clang_cl_env_tmp}": "clang_cl_not_found",
+            "%{clang_cl_env_path}": "clang_cl_not_found",
+            "%{clang_cl_env_include}": "clang_cl_not_found",
+            "%{clang_cl_env_lib}": "clang_cl_not_found",
+            "%{clang_cl_cl_path}": error_script,
+            "%{clang_cl_link_path}": error_script,
+            "%{clang_cl_lib_path}": error_script,
+            "%{clang_cl_ml_path}": error_script,
+            "%{clang_cl_dbg_mode_debug_flag}": "/DEBUG",
+            "%{clang_cl_fastbuild_mode_debug_flag}": "/DEBUG",
+            "%{clang_cl_cxx_builtin_include_directories}": "",
+        }
+        return clang_cl_vars
+
+    clang_cl_path = find_llvm_tool(repository_ctx, llvm_path, "clang-cl.exe")
+    lld_link_path = find_llvm_tool(repository_ctx, llvm_path, "lld-link.exe")
+    llvm_lib_path = find_llvm_tool(repository_ctx, llvm_path, "llvm-lib.exe")
+
+    clang_version = _get_clang_version(repository_ctx, clang_cl_path)
+    clang_dir = llvm_path + "\\lib\\clang\\" + clang_version
+    clang_include_path = (clang_dir + "\\include").replace("\\", "\\\\")
+    clang_lib_path = (clang_dir + "\\lib\\windows").replace("\\", "\\\\")
+
+    clang_cl_vars = {
+        "%{clang_cl_env_tmp}": msvc_vars["%{msvc_env_tmp}"],
+        "%{clang_cl_env_path}": msvc_vars["%{msvc_env_path}"],
+        "%{clang_cl_env_include}": msvc_vars["%{msvc_env_include}"] + ";" + clang_include_path,
+        "%{clang_cl_env_lib}": msvc_vars["%{msvc_env_lib}"] + ";" + clang_lib_path,
+        "%{clang_cl_cxx_builtin_include_directories}": msvc_vars["%{msvc_cxx_builtin_include_directories}"] + (",\n        \"%s\"" % clang_include_path),
+        "%{clang_cl_cl_path}": clang_cl_path,
+        "%{clang_cl_link_path}": lld_link_path,
+        "%{clang_cl_lib_path}": llvm_lib_path,
+        "%{clang_cl_ml_path}": msvc_vars["%{msvc_ml_path}"],
+        # LLVM's lld-link.exe doesn't support /DEBUG:FASTLINK.
+        "%{clang_cl_dbg_mode_debug_flag}": "/DEBUG",
+        "%{clang_cl_fastbuild_mode_debug_flag}": "/DEBUG",
+    }
+    return clang_cl_vars
+
+def configure_windows_toolchain(repository_ctx):
+    """Configure C++ toolchain on Windows."""
+    paths = resolve_labels(repository_ctx, [
+        "@rules_cc//cc/private/toolchain:BUILD.windows.tpl",
+        "@rules_cc//cc/private/toolchain:windows_cc_toolchain_config.bzl",
+        "@rules_cc//cc/private/toolchain:armeabi_cc_toolchain_config.bzl",
+        "@rules_cc//cc/private/toolchain:vc_installation_error.bat.tpl",
+        "@rules_cc//cc/private/toolchain:msys_gcc_installation_error.bat",
+        "@rules_cc//cc/private/toolchain:clang_installation_error.bat.tpl",
+    ])
+
+    repository_ctx.symlink(
+        paths["@rules_cc//cc/private/toolchain:windows_cc_toolchain_config.bzl"],
+        "windows_cc_toolchain_config.bzl",
+    )
+    repository_ctx.symlink(
+        paths["@rules_cc//cc/private/toolchain:armeabi_cc_toolchain_config.bzl"],
+        "armeabi_cc_toolchain_config.bzl",
+    )
+    repository_ctx.symlink(
+        paths["@rules_cc//cc/private/toolchain:msys_gcc_installation_error.bat"],
+        "msys_gcc_installation_error.bat",
+    )
+
+    template_vars = dict()
+    msvc_vars = _get_msvc_vars(repository_ctx, paths)
+    template_vars.update(msvc_vars)
+    template_vars.update(_get_clang_cl_vars(repository_ctx, paths, msvc_vars))
+    template_vars.update(_get_msys_mingw_vars(repository_ctx))
+
+    repository_ctx.template(
+        "BUILD",
+        paths["@rules_cc//cc/private/toolchain:BUILD.windows.tpl"],
+        template_vars,
+    )
diff --git a/cc/private/toolchain/windows_cc_toolchain_config.bzl b/cc/private/toolchain/windows_cc_toolchain_config.bzl
new file mode 100644
index 0000000..6c02b5c
--- /dev/null
+++ b/cc/private/toolchain/windows_cc_toolchain_config.bzl
@@ -0,0 +1,1342 @@
+# Copyright 2019 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.
+
+"""A Starlark cc_toolchain configuration rule for Windows"""
+
+load(
+    "@rules_cc//cc/private/toolchain:cc_toolchain_config_lib.bzl",
+    "action_config",
+    "artifact_name_pattern",
+    "env_entry",
+    "env_set",
+    "feature",
+    "feature_set",
+    "flag_group",
+    "flag_set",
+    "tool",
+    "tool_path",
+    "variable_with_value",
+    "with_feature_set",
+)
+load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
+
+all_compile_actions = [
+    ACTION_NAMES.c_compile,
+    ACTION_NAMES.cpp_compile,
+    ACTION_NAMES.linkstamp_compile,
+    ACTION_NAMES.assemble,
+    ACTION_NAMES.preprocess_assemble,
+    ACTION_NAMES.cpp_header_parsing,
+    ACTION_NAMES.cpp_module_compile,
+    ACTION_NAMES.cpp_module_codegen,
+    ACTION_NAMES.clif_match,
+    ACTION_NAMES.lto_backend,
+]
+
+all_cpp_compile_actions = [
+    ACTION_NAMES.cpp_compile,
+    ACTION_NAMES.linkstamp_compile,
+    ACTION_NAMES.cpp_header_parsing,
+    ACTION_NAMES.cpp_module_compile,
+    ACTION_NAMES.cpp_module_codegen,
+    ACTION_NAMES.clif_match,
+]
+
+preprocessor_compile_actions = [
+    ACTION_NAMES.c_compile,
+    ACTION_NAMES.cpp_compile,
+    ACTION_NAMES.linkstamp_compile,
+    ACTION_NAMES.preprocess_assemble,
+    ACTION_NAMES.cpp_header_parsing,
+    ACTION_NAMES.cpp_module_compile,
+    ACTION_NAMES.clif_match,
+]
+
+codegen_compile_actions = [
+    ACTION_NAMES.c_compile,
+    ACTION_NAMES.cpp_compile,
+    ACTION_NAMES.linkstamp_compile,
+    ACTION_NAMES.assemble,
+    ACTION_NAMES.preprocess_assemble,
+    ACTION_NAMES.cpp_module_codegen,
+    ACTION_NAMES.lto_backend,
+]
+
+all_link_actions = [
+    ACTION_NAMES.cpp_link_executable,
+    ACTION_NAMES.cpp_link_dynamic_library,
+    ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+]
+
+def _use_msvc_toolchain(ctx):
+    return ctx.attr.cpu == "x64_windows" and (ctx.attr.compiler == "msvc-cl" or ctx.attr.compiler == "clang-cl")
+
+def _impl(ctx):
+    if _use_msvc_toolchain(ctx):
+        artifact_name_patterns = [
+            artifact_name_pattern(
+                category_name = "object_file",
+                prefix = "",
+                extension = ".obj",
+            ),
+            artifact_name_pattern(
+                category_name = "static_library",
+                prefix = "",
+                extension = ".lib",
+            ),
+            artifact_name_pattern(
+                category_name = "alwayslink_static_library",
+                prefix = "",
+                extension = ".lo.lib",
+            ),
+            artifact_name_pattern(
+                category_name = "executable",
+                prefix = "",
+                extension = ".exe",
+            ),
+            artifact_name_pattern(
+                category_name = "dynamic_library",
+                prefix = "",
+                extension = ".dll",
+            ),
+            artifact_name_pattern(
+                category_name = "interface_library",
+                prefix = "",
+                extension = ".if.lib",
+            ),
+        ]
+    else:
+        artifact_name_patterns = [
+            artifact_name_pattern(
+                category_name = "executable",
+                prefix = "",
+                extension = ".exe",
+            ),
+        ]
+
+    if _use_msvc_toolchain(ctx):
+        cpp_link_nodeps_dynamic_library_action = action_config(
+            action_name = ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+            implies = [
+                "nologo",
+                "shared_flag",
+                "linkstamps",
+                "output_execpath_flags",
+                "input_param_flags",
+                "user_link_flags",
+                "default_link_flags",
+                "linker_subsystem_flag",
+                "linker_param_file",
+                "msvc_env",
+                "no_stripping",
+                "has_configured_linker_path",
+                "def_file",
+            ],
+            tools = [tool(path = ctx.attr.msvc_link_path)],
+        )
+
+        cpp_link_static_library_action = action_config(
+            action_name = ACTION_NAMES.cpp_link_static_library,
+            implies = [
+                "nologo",
+                "archiver_flags",
+                "input_param_flags",
+                "linker_param_file",
+                "msvc_env",
+            ],
+            tools = [tool(path = ctx.attr.msvc_lib_path)],
+        )
+
+        assemble_action = action_config(
+            action_name = ACTION_NAMES.assemble,
+            implies = [
+                "compiler_input_flags",
+                "compiler_output_flags",
+                "nologo",
+                "msvc_env",
+                "sysroot",
+            ],
+            tools = [tool(path = ctx.attr.msvc_ml_path)],
+        )
+
+        preprocess_assemble_action = action_config(
+            action_name = ACTION_NAMES.preprocess_assemble,
+            implies = [
+                "compiler_input_flags",
+                "compiler_output_flags",
+                "nologo",
+                "msvc_env",
+                "sysroot",
+            ],
+            tools = [tool(path = ctx.attr.msvc_ml_path)],
+        )
+
+        c_compile_action = action_config(
+            action_name = ACTION_NAMES.c_compile,
+            implies = [
+                "compiler_input_flags",
+                "compiler_output_flags",
+                "default_compile_flags",
+                "nologo",
+                "msvc_env",
+                "parse_showincludes",
+                "user_compile_flags",
+                "sysroot",
+                "unfiltered_compile_flags",
+            ],
+            tools = [tool(path = ctx.attr.msvc_cl_path)],
+        )
+
+        cpp_compile_action = action_config(
+            action_name = ACTION_NAMES.cpp_compile,
+            implies = [
+                "compiler_input_flags",
+                "compiler_output_flags",
+                "default_compile_flags",
+                "nologo",
+                "msvc_env",
+                "parse_showincludes",
+                "user_compile_flags",
+                "sysroot",
+                "unfiltered_compile_flags",
+            ],
+            tools = [tool(path = ctx.attr.msvc_cl_path)],
+        )
+
+        cpp_link_executable_action = action_config(
+            action_name = ACTION_NAMES.cpp_link_executable,
+            implies = [
+                "nologo",
+                "linkstamps",
+                "output_execpath_flags",
+                "input_param_flags",
+                "user_link_flags",
+                "default_link_flags",
+                "linker_subsystem_flag",
+                "linker_param_file",
+                "msvc_env",
+                "no_stripping",
+            ],
+            tools = [tool(path = ctx.attr.msvc_link_path)],
+        )
+
+        cpp_link_dynamic_library_action = action_config(
+            action_name = ACTION_NAMES.cpp_link_dynamic_library,
+            implies = [
+                "nologo",
+                "shared_flag",
+                "linkstamps",
+                "output_execpath_flags",
+                "input_param_flags",
+                "user_link_flags",
+                "default_link_flags",
+                "linker_subsystem_flag",
+                "linker_param_file",
+                "msvc_env",
+                "no_stripping",
+                "has_configured_linker_path",
+                "def_file",
+            ],
+            tools = [tool(path = ctx.attr.msvc_link_path)],
+        )
+
+        action_configs = [
+            assemble_action,
+            preprocess_assemble_action,
+            c_compile_action,
+            cpp_compile_action,
+            cpp_link_executable_action,
+            cpp_link_dynamic_library_action,
+            cpp_link_nodeps_dynamic_library_action,
+            cpp_link_static_library_action,
+        ]
+    else:
+        action_configs = []
+
+    if _use_msvc_toolchain(ctx):
+        msvc_link_env_feature = feature(
+            name = "msvc_link_env",
+            env_sets = [
+                env_set(
+                    actions = all_link_actions +
+                              [ACTION_NAMES.cpp_link_static_library],
+                    env_entries = [env_entry(key = "LIB", value = ctx.attr.msvc_env_lib)],
+                ),
+            ],
+        )
+
+        shared_flag_feature = feature(
+            name = "shared_flag",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.cpp_link_dynamic_library,
+                        ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+                    ],
+                    flag_groups = [flag_group(flags = ["/DLL"])],
+                ),
+            ],
+        )
+
+        determinism_feature = feature(
+            name = "determinism",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "/wd4117",
+                                "-D__DATE__=\"redacted\"",
+                                "-D__TIMESTAMP__=\"redacted\"",
+                                "-D__TIME__=\"redacted\"",
+                            ] + (["-Wno-builtin-macro-redefined"] if ctx.attr.compiler == "clang-cl" else []),
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        sysroot_feature = feature(
+            name = "sysroot",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                        ACTION_NAMES.cpp_link_executable,
+                        ACTION_NAMES.cpp_link_dynamic_library,
+                        ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["--sysroot=%{sysroot}"],
+                            iterate_over = "sysroot",
+                            expand_if_available = "sysroot",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        unfiltered_compile_flags_feature = feature(
+            name = "unfiltered_compile_flags",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["%{unfiltered_compile_flags}"],
+                            iterate_over = "unfiltered_compile_flags",
+                            expand_if_available = "unfiltered_compile_flags",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        compiler_param_file_feature = feature(
+            name = "compiler_param_file",
+        )
+
+        copy_dynamic_libraries_to_binary_feature = feature(
+            name = "copy_dynamic_libraries_to_binary",
+        )
+
+        input_param_flags_feature = feature(
+            name = "input_param_flags",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.cpp_link_dynamic_library,
+                        ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["/IMPLIB:%{interface_library_output_path}"],
+                            expand_if_available = "interface_library_output_path",
+                        ),
+                    ],
+                ),
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = ["%{libopts}"],
+                            iterate_over = "libopts",
+                            expand_if_available = "libopts",
+                        ),
+                    ],
+                ),
+                flag_set(
+                    actions = all_link_actions +
+                              [ACTION_NAMES.cpp_link_static_library],
+                    flag_groups = [
+                        flag_group(
+                            iterate_over = "libraries_to_link",
+                            flag_groups = [
+                                flag_group(
+                                    iterate_over = "libraries_to_link.object_files",
+                                    flag_groups = [flag_group(flags = ["%{libraries_to_link.object_files}"])],
+                                    expand_if_equal = variable_with_value(
+                                        name = "libraries_to_link.type",
+                                        value = "object_file_group",
+                                    ),
+                                ),
+                                flag_group(
+                                    flag_groups = [flag_group(flags = ["%{libraries_to_link.name}"])],
+                                    expand_if_equal = variable_with_value(
+                                        name = "libraries_to_link.type",
+                                        value = "object_file",
+                                    ),
+                                ),
+                                flag_group(
+                                    flag_groups = [flag_group(flags = ["%{libraries_to_link.name}"])],
+                                    expand_if_equal = variable_with_value(
+                                        name = "libraries_to_link.type",
+                                        value = "interface_library",
+                                    ),
+                                ),
+                                flag_group(
+                                    flag_groups = [
+                                        flag_group(
+                                            flags = ["%{libraries_to_link.name}"],
+                                            expand_if_false = "libraries_to_link.is_whole_archive",
+                                        ),
+                                        flag_group(
+                                            flags = ["/WHOLEARCHIVE:%{libraries_to_link.name}"],
+                                            expand_if_true = "libraries_to_link.is_whole_archive",
+                                        ),
+                                    ],
+                                    expand_if_equal = variable_with_value(
+                                        name = "libraries_to_link.type",
+                                        value = "static_library",
+                                    ),
+                                ),
+                            ],
+                            expand_if_available = "libraries_to_link",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        fastbuild_feature = feature(
+            name = "fastbuild",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/Od", "/Z7"])],
+                ),
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = [ctx.attr.fastbuild_mode_debug_flag, "/INCREMENTAL:NO"],
+                        ),
+                    ],
+                ),
+            ],
+            implies = ["generate_pdb_file"],
+        )
+
+        user_compile_flags_feature = feature(
+            name = "user_compile_flags",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["%{user_compile_flags}"],
+                            iterate_over = "user_compile_flags",
+                            expand_if_available = "user_compile_flags",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        archiver_flags_feature = feature(
+            name = "archiver_flags",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.cpp_link_static_library],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["/OUT:%{output_execpath}"],
+                            expand_if_available = "output_execpath",
+                        ),
+                        flag_group(
+                            flags = ["/MACHINE:X64"],
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        default_link_flags_feature = feature(
+            name = "default_link_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ctx.attr.default_link_flags)],
+                ),
+            ],
+        )
+
+        static_link_msvcrt_feature = feature(name = "static_link_msvcrt")
+
+        dynamic_link_msvcrt_debug_feature = feature(
+            name = "dynamic_link_msvcrt_debug",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/MDd"])],
+                ),
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrtd.lib"])],
+                ),
+            ],
+            requires = [feature_set(features = ["dbg"])],
+        )
+
+        dbg_feature = feature(
+            name = "dbg",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/Od", "/Z7"])],
+                ),
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = [ctx.attr.dbg_mode_debug_flag, "/INCREMENTAL:NO"],
+                        ),
+                    ],
+                ),
+            ],
+            implies = ["generate_pdb_file"],
+        )
+
+        opt_feature = feature(
+            name = "opt",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/O2"])],
+                ),
+            ],
+            implies = ["frame_pointer"],
+        )
+
+        supports_interface_shared_libraries_feature = feature(
+            name = "supports_interface_shared_libraries",
+            enabled = True,
+        )
+
+        user_link_flags_feature = feature(
+            name = "user_link_flags",
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = ["%{user_link_flags}"],
+                            iterate_over = "user_link_flags",
+                            expand_if_available = "user_link_flags",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        default_compile_flags_feature = feature(
+            name = "default_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.linkstamp_compile,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                        ACTION_NAMES.lto_backend,
+                        ACTION_NAMES.clif_match,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = [
+                                "/DCOMPILER_MSVC",
+                                "/DNOMINMAX",
+                                "/D_WIN32_WINNT=0x0601",
+                                "/D_CRT_SECURE_NO_DEPRECATE",
+                                "/D_CRT_SECURE_NO_WARNINGS",
+                                "/bigobj",
+                                "/Zm500",
+                                "/EHsc",
+                                "/wd4351",
+                                "/wd4291",
+                                "/wd4250",
+                                "/wd4996",
+                            ],
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        msvc_compile_env_feature = feature(
+            name = "msvc_compile_env",
+            env_sets = [
+                env_set(
+                    actions = [
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                    ],
+                    env_entries = [env_entry(key = "INCLUDE", value = ctx.attr.msvc_env_include)],
+                ),
+            ],
+        )
+
+        preprocessor_defines_feature = feature(
+            name = "preprocessor_defines",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["/D%{preprocessor_defines}"],
+                            iterate_over = "preprocessor_defines",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        generate_pdb_file_feature = feature(
+            name = "generate_pdb_file",
+            requires = [
+                feature_set(features = ["dbg"]),
+                feature_set(features = ["fastbuild"]),
+            ],
+        )
+
+        output_execpath_flags_feature = feature(
+            name = "output_execpath_flags",
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = ["/OUT:%{output_execpath}"],
+                            expand_if_available = "output_execpath",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        dynamic_link_msvcrt_no_debug_feature = feature(
+            name = "dynamic_link_msvcrt_no_debug",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/MD"])],
+                ),
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrt.lib"])],
+                ),
+            ],
+            requires = [
+                feature_set(features = ["fastbuild"]),
+                feature_set(features = ["opt"]),
+            ],
+        )
+
+        disable_assertions_feature = feature(
+            name = "disable_assertions",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/DNDEBUG"])],
+                    with_features = [with_feature_set(features = ["opt"])],
+                ),
+            ],
+        )
+
+        has_configured_linker_path_feature = feature(name = "has_configured_linker_path")
+
+        supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True)
+
+        no_stripping_feature = feature(name = "no_stripping")
+
+        linker_param_file_feature = feature(
+            name = "linker_param_file",
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions +
+                              [ACTION_NAMES.cpp_link_static_library],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["@%{linker_param_file}"],
+                            expand_if_available = "linker_param_file",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        ignore_noisy_warnings_feature = feature(
+            name = "ignore_noisy_warnings",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.cpp_link_static_library],
+                    flag_groups = [flag_group(flags = ["/ignore:4221"])],
+                ),
+            ],
+        )
+
+        no_legacy_features_feature = feature(name = "no_legacy_features")
+
+        parse_showincludes_feature = feature(
+            name = "parse_showincludes",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                    ],
+                    flag_groups = [flag_group(flags = ["/showIncludes"])],
+                ),
+            ],
+        )
+
+        static_link_msvcrt_no_debug_feature = feature(
+            name = "static_link_msvcrt_no_debug",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/MT"])],
+                ),
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmt.lib"])],
+                ),
+            ],
+            requires = [
+                feature_set(features = ["fastbuild"]),
+                feature_set(features = ["opt"]),
+            ],
+        )
+
+        treat_warnings_as_errors_feature = feature(
+            name = "treat_warnings_as_errors",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/WX"])],
+                ),
+            ],
+        )
+
+        windows_export_all_symbols_feature = feature(name = "windows_export_all_symbols")
+
+        no_windows_export_all_symbols_feature = feature(name = "no_windows_export_all_symbols")
+
+        include_paths_feature = feature(
+            name = "include_paths",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["/I%{quote_include_paths}"],
+                            iterate_over = "quote_include_paths",
+                        ),
+                        flag_group(
+                            flags = ["/I%{include_paths}"],
+                            iterate_over = "include_paths",
+                        ),
+                        flag_group(
+                            flags = ["/I%{system_include_paths}"],
+                            iterate_over = "system_include_paths",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        linkstamps_feature = feature(
+            name = "linkstamps",
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = ["%{linkstamp_paths}"],
+                            iterate_over = "linkstamp_paths",
+                            expand_if_available = "linkstamp_paths",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        targets_windows_feature = feature(
+            name = "targets_windows",
+            enabled = True,
+            implies = ["copy_dynamic_libraries_to_binary"],
+        )
+
+        linker_subsystem_flag_feature = feature(
+            name = "linker_subsystem_flag",
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["/SUBSYSTEM:CONSOLE"])],
+                ),
+            ],
+        )
+
+        static_link_msvcrt_debug_feature = feature(
+            name = "static_link_msvcrt_debug",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/MTd"])],
+                ),
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmtd.lib"])],
+                ),
+            ],
+            requires = [feature_set(features = ["dbg"])],
+        )
+
+        frame_pointer_feature = feature(
+            name = "frame_pointer",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/Oy-"])],
+                ),
+            ],
+        )
+
+        compiler_output_flags_feature = feature(
+            name = "compiler_output_flags",
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.assemble],
+                    flag_groups = [
+                        flag_group(
+                            flag_groups = [
+                                flag_group(
+                                    flags = ["/Fo%{output_file}", "/Zi"],
+                                    expand_if_available = "output_file",
+                                    expand_if_not_available = "output_assembly_file",
+                                ),
+                            ],
+                            expand_if_not_available = "output_preprocess_file",
+                        ),
+                    ],
+                ),
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flag_groups = [
+                                flag_group(
+                                    flags = ["/Fo%{output_file}"],
+                                    expand_if_not_available = "output_preprocess_file",
+                                ),
+                            ],
+                            expand_if_available = "output_file",
+                            expand_if_not_available = "output_assembly_file",
+                        ),
+                        flag_group(
+                            flag_groups = [
+                                flag_group(
+                                    flags = ["/Fa%{output_file}"],
+                                    expand_if_available = "output_assembly_file",
+                                ),
+                            ],
+                            expand_if_available = "output_file",
+                        ),
+                        flag_group(
+                            flag_groups = [
+                                flag_group(
+                                    flags = ["/P", "/Fi%{output_file}"],
+                                    expand_if_available = "output_preprocess_file",
+                                ),
+                            ],
+                            expand_if_available = "output_file",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        nologo_feature = feature(
+            name = "nologo",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.cpp_link_executable,
+                        ACTION_NAMES.cpp_link_dynamic_library,
+                        ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+                        ACTION_NAMES.cpp_link_static_library,
+                    ],
+                    flag_groups = [flag_group(flags = ["/nologo"])],
+                ),
+            ],
+        )
+
+        smaller_binary_feature = feature(
+            name = "smaller_binary",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                    flag_groups = [flag_group(flags = ["/Gy", "/Gw"])],
+                    with_features = [with_feature_set(features = ["opt"])],
+                ),
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["/OPT:ICF", "/OPT:REF"])],
+                    with_features = [with_feature_set(features = ["opt"])],
+                ),
+            ],
+        )
+
+        compiler_input_flags_feature = feature(
+            name = "compiler_input_flags",
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                    ],
+                    flag_groups = [
+                        flag_group(
+                            flags = ["/c", "%{source_file}"],
+                            expand_if_available = "source_file",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        def_file_feature = feature(
+            name = "def_file",
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [
+                        flag_group(
+                            flags = ["/DEF:%{def_file_path}", "/ignore:4070"],
+                            expand_if_available = "def_file_path",
+                        ),
+                    ],
+                ),
+            ],
+        )
+
+        msvc_env_feature = feature(
+            name = "msvc_env",
+            env_sets = [
+                env_set(
+                    actions = [
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.cpp_link_executable,
+                        ACTION_NAMES.cpp_link_dynamic_library,
+                        ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+                        ACTION_NAMES.cpp_link_static_library,
+                    ],
+                    env_entries = [
+                        env_entry(key = "PATH", value = ctx.attr.msvc_env_path),
+                        env_entry(key = "TMP", value = ctx.attr.msvc_env_tmp),
+                        env_entry(key = "TEMP", value = ctx.attr.msvc_env_tmp),
+                    ],
+                ),
+            ],
+            implies = ["msvc_compile_env", "msvc_link_env"],
+        )
+        features = [
+            no_legacy_features_feature,
+            nologo_feature,
+            has_configured_linker_path_feature,
+            no_stripping_feature,
+            targets_windows_feature,
+            copy_dynamic_libraries_to_binary_feature,
+            default_compile_flags_feature,
+            msvc_env_feature,
+            msvc_compile_env_feature,
+            msvc_link_env_feature,
+            include_paths_feature,
+            preprocessor_defines_feature,
+            parse_showincludes_feature,
+            generate_pdb_file_feature,
+            shared_flag_feature,
+            linkstamps_feature,
+            output_execpath_flags_feature,
+            archiver_flags_feature,
+            input_param_flags_feature,
+            linker_subsystem_flag_feature,
+            user_link_flags_feature,
+            default_link_flags_feature,
+            linker_param_file_feature,
+            static_link_msvcrt_feature,
+            static_link_msvcrt_no_debug_feature,
+            dynamic_link_msvcrt_no_debug_feature,
+            static_link_msvcrt_debug_feature,
+            dynamic_link_msvcrt_debug_feature,
+            dbg_feature,
+            fastbuild_feature,
+            opt_feature,
+            frame_pointer_feature,
+            disable_assertions_feature,
+            determinism_feature,
+            treat_warnings_as_errors_feature,
+            smaller_binary_feature,
+            ignore_noisy_warnings_feature,
+            user_compile_flags_feature,
+            sysroot_feature,
+            unfiltered_compile_flags_feature,
+            compiler_param_file_feature,
+            compiler_output_flags_feature,
+            compiler_input_flags_feature,
+            def_file_feature,
+            windows_export_all_symbols_feature,
+            no_windows_export_all_symbols_feature,
+            supports_dynamic_linker_feature,
+            supports_interface_shared_libraries_feature,
+        ]
+    else:
+        targets_windows_feature = feature(
+            name = "targets_windows",
+            implies = ["copy_dynamic_libraries_to_binary"],
+            enabled = True,
+        )
+
+        copy_dynamic_libraries_to_binary_feature = feature(name = "copy_dynamic_libraries_to_binary")
+
+        gcc_env_feature = feature(
+            name = "gcc_env",
+            enabled = True,
+            env_sets = [
+                env_set(
+                    actions = [
+                        ACTION_NAMES.c_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.assemble,
+                        ACTION_NAMES.preprocess_assemble,
+                        ACTION_NAMES.cpp_link_executable,
+                        ACTION_NAMES.cpp_link_dynamic_library,
+                        ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+                        ACTION_NAMES.cpp_link_static_library,
+                    ],
+                    env_entries = [
+                        env_entry(key = "PATH", value = ctx.attr.tool_bin_path),
+                    ],
+                ),
+            ],
+        )
+
+        default_compile_flags_feature = feature(
+            name = "default_compile_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = [
+                        ACTION_NAMES.linkstamp_compile,
+                        ACTION_NAMES.cpp_compile,
+                        ACTION_NAMES.cpp_header_parsing,
+                        ACTION_NAMES.cpp_module_compile,
+                        ACTION_NAMES.cpp_module_codegen,
+                        ACTION_NAMES.lto_backend,
+                        ACTION_NAMES.clif_match,
+                    ],
+                    flag_groups = [flag_group(flags = ["-std=gnu++0x"])],
+                ),
+            ],
+        )
+
+        default_link_flags_feature = feature(
+            name = "default_link_flags",
+            enabled = True,
+            flag_sets = [
+                flag_set(
+                    actions = all_link_actions,
+                    flag_groups = [flag_group(flags = ["-lstdc++"])],
+                ),
+            ],
+        )
+
+        supports_dynamic_linker_feature = feature(
+            name = "supports_dynamic_linker",
+            enabled = True,
+        )
+
+        if ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "mingw-gcc":
+            compiler_param_file_feature = feature(
+                name = "compiler_param_file",
+            )
+
+            features = [
+                targets_windows_feature,
+                copy_dynamic_libraries_to_binary_feature,
+                gcc_env_feature,
+                default_compile_flags_feature,
+                compiler_param_file_feature,
+                default_link_flags_feature,
+                supports_dynamic_linker_feature,
+            ]
+        else:
+            supports_pic_feature = feature(
+                name = "supports_pic",
+                enabled = True,
+            )
+            supports_start_end_lib_feature = feature(
+                name = "supports_start_end_lib",
+                enabled = True,
+            )
+
+            dbg_feature = feature(name = "dbg")
+
+            opt_feature = feature(name = "opt")
+
+            sysroot_feature = feature(
+                name = "sysroot",
+                enabled = True,
+                flag_sets = [
+                    flag_set(
+                        actions = [
+                            ACTION_NAMES.preprocess_assemble,
+                            ACTION_NAMES.linkstamp_compile,
+                            ACTION_NAMES.c_compile,
+                            ACTION_NAMES.cpp_compile,
+                            ACTION_NAMES.cpp_header_parsing,
+                            ACTION_NAMES.cpp_module_compile,
+                            ACTION_NAMES.cpp_module_codegen,
+                            ACTION_NAMES.lto_backend,
+                            ACTION_NAMES.clif_match,
+                            ACTION_NAMES.cpp_link_executable,
+                            ACTION_NAMES.cpp_link_dynamic_library,
+                            ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+                        ],
+                        flag_groups = [
+                            flag_group(
+                                flags = ["--sysroot=%{sysroot}"],
+                                expand_if_available = "sysroot",
+                            ),
+                        ],
+                    ),
+                ],
+            )
+
+            fdo_optimize_feature = feature(
+                name = "fdo_optimize",
+                flag_sets = [
+                    flag_set(
+                        actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
+                        flag_groups = [
+                            flag_group(
+                                flags = [
+                                    "-fprofile-use=%{fdo_profile_path}",
+                                    "-fprofile-correction",
+                                ],
+                                expand_if_available = "fdo_profile_path",
+                            ),
+                        ],
+                    ),
+                ],
+                provides = ["profile"],
+            )
+
+            user_compile_flags_feature = feature(
+                name = "user_compile_flags",
+                enabled = True,
+                flag_sets = [
+                    flag_set(
+                        actions = [
+                            ACTION_NAMES.assemble,
+                            ACTION_NAMES.preprocess_assemble,
+                            ACTION_NAMES.linkstamp_compile,
+                            ACTION_NAMES.c_compile,
+                            ACTION_NAMES.cpp_compile,
+                            ACTION_NAMES.cpp_header_parsing,
+                            ACTION_NAMES.cpp_module_compile,
+                            ACTION_NAMES.cpp_module_codegen,
+                            ACTION_NAMES.lto_backend,
+                            ACTION_NAMES.clif_match,
+                        ],
+                        flag_groups = [
+                            flag_group(
+                                flags = ["%{user_compile_flags}"],
+                                iterate_over = "user_compile_flags",
+                                expand_if_available = "user_compile_flags",
+                            ),
+                        ],
+                    ),
+                ],
+            )
+
+            features = [
+                targets_windows_feature,
+                copy_dynamic_libraries_to_binary_feature,
+                gcc_env_feature,
+                supports_pic_feature,
+                default_compile_flags_feature,
+                default_link_flags_feature,
+                fdo_optimize_feature,
+                supports_dynamic_linker_feature,
+                dbg_feature,
+                opt_feature,
+                user_compile_flags_feature,
+                sysroot_feature,
+            ]
+
+    tool_paths = [
+        tool_path(name = name, path = path)
+        for name, path in ctx.attr.tool_paths.items()
+    ]
+
+    return cc_common.create_cc_toolchain_config_info(
+        ctx = ctx,
+        features = features,
+        action_configs = action_configs,
+        artifact_name_patterns = artifact_name_patterns,
+        cxx_builtin_include_directories = ctx.attr.cxx_builtin_include_directories,
+        toolchain_identifier = ctx.attr.toolchain_identifier,
+        host_system_name = ctx.attr.host_system_name,
+        target_system_name = ctx.attr.target_system_name,
+        target_cpu = ctx.attr.cpu,
+        target_libc = ctx.attr.target_libc,
+        compiler = ctx.attr.compiler,
+        abi_version = ctx.attr.abi_version,
+        abi_libc_version = ctx.attr.abi_libc_version,
+        tool_paths = tool_paths,
+    )
+
+cc_toolchain_config = rule(
+    implementation = _impl,
+    attrs = {
+        "cpu": attr.string(mandatory = True),
+        "compiler": attr.string(),
+        "toolchain_identifier": attr.string(),
+        "host_system_name": attr.string(),
+        "target_system_name": attr.string(),
+        "target_libc": attr.string(),
+        "abi_version": attr.string(),
+        "abi_libc_version": attr.string(),
+        "tool_paths": attr.string_dict(),
+        "cxx_builtin_include_directories": attr.string_list(),
+        "default_link_flags": attr.string_list(default = []),
+        "msvc_env_tmp": attr.string(default = "msvc_not_found"),
+        "msvc_env_path": attr.string(default = "msvc_not_found"),
+        "msvc_env_include": attr.string(default = "msvc_not_found"),
+        "msvc_env_lib": attr.string(default = "msvc_not_found"),
+        "msvc_cl_path": attr.string(default = "vc_installation_error.bat"),
+        "msvc_ml_path": attr.string(default = "vc_installation_error.bat"),
+        "msvc_link_path": attr.string(default = "vc_installation_error.bat"),
+        "msvc_lib_path": attr.string(default = "vc_installation_error.bat"),
+        "dbg_mode_debug_flag": attr.string(),
+        "fastbuild_mode_debug_flag": attr.string(),
+        "tool_bin_path": attr.string(default = "not_found"),
+    },
+    provides = [CcToolchainConfigInfo],
+)
diff --git a/cc/toolchain_utils.bzl b/cc/toolchain_utils.bzl
new file mode 100644
index 0000000..dc97993
--- /dev/null
+++ b/cc/toolchain_utils.bzl
@@ -0,0 +1,48 @@
+# pylint: disable=g-bad-file-header
+# Copyright 2016 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.
+
+"""
+Finds the c++ toolchain.
+
+Returns the toolchain if enabled, and falls back to a toolchain constructed from
+the CppConfiguration.
+"""
+
+def find_cpp_toolchain(ctx):
+    """
+    Finds the c++ toolchain.
+
+    If the c++ toolchain is in use, returns it.  Otherwise, returns a c++
+    toolchain derived from legacy toolchain selection.
+
+    Args:
+      ctx: The rule context for which to find a toolchain.
+
+    Returns:
+      A CcToolchainProvider.
+    """
+
+    # Check the incompatible flag for toolchain resolution.
+    if hasattr(cc_common, "is_cc_toolchain_resolution_enabled_do_not_use") and cc_common.is_cc_toolchain_resolution_enabled_do_not_use(ctx = ctx):
+        if "@rules_cc//cc:toolchain_type" in ctx.toolchains:
+            return ctx.toolchains["@rules_cc//cc:toolchain_type"]
+        fail("In order to use find_cpp_toolchain, you must include the '@rules_cc//cc:toolchain_type' in the toolchains argument to your rule.")
+
+    # Fall back to the legacy implicit attribute lookup.
+    if hasattr(ctx.attr, "_cc_toolchain"):
+        return ctx.attr._cc_toolchain[cc_common.CcToolchainInfo]
+
+    # We didn't find anything.
+    fail("In order to use find_cpp_toolchain, you must define the '_cc_toolchain' attribute on your rule or aspect.")
diff --git a/examples/my_c_archive/my_c_archive.bzl b/examples/my_c_archive/my_c_archive.bzl
index 5d333c4..baf6d25 100644
--- a/examples/my_c_archive/my_c_archive.bzl
+++ b/examples/my_c_archive/my_c_archive.bzl
@@ -14,7 +14,7 @@
 
 """Example showing how to create a rule that rules_cc can depend on."""
 
-load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
+load("@rules_cc//cc:toolchain_utils.bzl", "find_cpp_toolchain")
 load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "CPP_LINK_STATIC_LIBRARY_ACTION_NAME")
 load("//examples/my_c_compile:my_c_compile.bzl", "MyCCompileInfo")
 
diff --git a/examples/my_c_compile/my_c_compile.bzl b/examples/my_c_compile/my_c_compile.bzl
index fe58db8..5dacfbc 100644
--- a/examples/my_c_compile/my_c_compile.bzl
+++ b/examples/my_c_compile/my_c_compile.bzl
@@ -14,7 +14,7 @@
 
 """Example showing how to create a rule that just compiles C sources."""
 
-load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
+load("@rules_cc//cc:toolchain_utils.bzl", "find_cpp_toolchain")
 load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "C_COMPILE_ACTION_NAME")
 
 MyCCompileInfo = provider(doc = "", fields = ["object"])
diff --git a/examples/write_cc_toolchain_cpu/write_cc_toolchain_cpu.bzl b/examples/write_cc_toolchain_cpu/write_cc_toolchain_cpu.bzl
index e1d253f..9aebf6e 100644
--- a/examples/write_cc_toolchain_cpu/write_cc_toolchain_cpu.bzl
+++ b/examples/write_cc_toolchain_cpu/write_cc_toolchain_cpu.bzl
@@ -14,7 +14,7 @@
 
 """Example showing how to get CcToolchainInfo in a custom rule."""
 
-load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
+load("@rules_cc//cc:toolchain_utils.bzl", "find_cpp_toolchain")
 
 def _write_cc_toolchain_cpu_impl(ctx):
     cc_toolchain = find_cpp_toolchain(ctx)