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

Change-Id: Ie1ff8ed3b3948cca1d1b6227097c95e5a048de86
git-subtree-dir: third_party/bazel-toolchain
git-subtree-split: a912bb381b36437be0eeb22de11f0ea198450b4e
Signed-off-by: Brian Silverman <bsilver16834@gmail.com>
diff --git a/toolchain/internal/configure.bzl b/toolchain/internal/configure.bzl
new file mode 100644
index 0000000..3aba341
--- /dev/null
+++ b/toolchain/internal/configure.bzl
@@ -0,0 +1,376 @@
+# Copyright 2018 The Bazel Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load(
+    "//toolchain/internal:common.bzl",
+    _arch = "arch",
+    _canonical_dir_path = "canonical_dir_path",
+    _check_os_arch_keys = "check_os_arch_keys",
+    _host_tool_features = "host_tool_features",
+    _host_tools = "host_tools",
+    _os = "os",
+    _os_arch_pair = "os_arch_pair",
+    _os_bzl = "os_bzl",
+    _pkg_path_from_label = "pkg_path_from_label",
+    _supported_targets = "SUPPORTED_TARGETS",
+)
+load(
+    "//toolchain/internal:sysroot.bzl",
+    _default_sysroot_path = "default_sysroot_path",
+    _sysroot_path = "sysroot_path",
+)
+
+def _include_dirs_str(rctx, key):
+    dirs = rctx.attr.cxx_builtin_include_directories.get(key)
+    if not dirs:
+        return ""
+    return ("\n" + 12 * " ").join(["\"%s\"," % d for d in dirs])
+
+def llvm_config_impl(rctx):
+    _check_os_arch_keys(rctx.attr.toolchain_roots)
+    _check_os_arch_keys(rctx.attr.sysroot)
+    _check_os_arch_keys(rctx.attr.cxx_builtin_include_directories)
+
+    os = _os(rctx)
+    if os == "windows":
+        rctx.file("BUILD.bazel")
+        rctx.file("toolchains.bzl", """\
+def llvm_register_toolchains():
+    pass
+""")
+        return
+    arch = _arch(rctx)
+
+    key = _os_arch_pair(os, arch)
+    toolchain_root = rctx.attr.toolchain_roots.get(key)
+    if not toolchain_root:
+        toolchain_root = rctx.attr.toolchain_roots.get("")
+    if not toolchain_root:
+        fail("LLVM toolchain root missing for ({}, {})", os, arch)
+
+    # Check if the toolchain root is an absolute path.
+    use_absolute_paths = rctx.attr.absolute_paths
+    if toolchain_root[0] == "/" and (len(toolchain_root) == 1 or toolchain_root[1] != "/"):
+        use_absolute_paths = True
+
+    if use_absolute_paths:
+        llvm_repo_label = Label(toolchain_root + ":BUILD.bazel")  # Exact target does not matter.
+        llvm_repo_path = _canonical_dir_path(str(rctx.path(llvm_repo_label).dirname))
+        config_repo_path = _canonical_dir_path(str(rctx.path("")))
+        toolchain_path_prefix = llvm_repo_path
+        tools_path_prefix = llvm_repo_path
+        wrapper_bin_prefix = config_repo_path
+    else:
+        llvm_repo_path = _pkg_path_from_label(Label(toolchain_root + ":BUILD.bazel"))
+        config_repo_path = "external/%s/" % rctx.name
+
+        # tools can only be defined in a subdirectory of config_repo_path,
+        # because their paths are relative to the package defining
+        # cc_toolchain, and cannot contain '..'.
+        # https://github.com/bazelbuild/bazel/issues/7746.  To work around
+        # this, we symlink the llvm repo under the package so all tools (except
+        # clang) can be called with normalized relative paths. For clang
+        # however, using a path with symlinks interferes with the header file
+        # inclusion validation checks, because clang frontend will infer the
+        # InstalledDir to be the symlinked path, and will look for header files
+        # in the symlinked path, but that seems to fail the inclusion
+        # validation check. So we always use a cc_wrapper (which is called
+        # through a normalized relative path), and then call clang with the not
+        # symlinked path from the wrapper.
+        rctx.symlink("../../" + llvm_repo_path, "llvm")
+        toolchain_path_prefix = llvm_repo_path
+        tools_path_prefix = "llvm/"
+        wrapper_bin_prefix = ""
+
+    default_sysroot_path = _default_sysroot_path(rctx, os)
+
+    workspace_name = rctx.name
+    toolchain_info = struct(
+        os = os,
+        arch = arch,
+        toolchain_root = toolchain_root,
+        toolchain_path_prefix = toolchain_path_prefix,
+        tools_path_prefix = tools_path_prefix,
+        wrapper_bin_prefix = wrapper_bin_prefix,
+        additional_include_dirs_dict = rctx.attr.cxx_builtin_include_directories,
+        sysroot_dict = rctx.attr.sysroot,
+        default_sysroot_path = default_sysroot_path,
+        llvm_version = rctx.attr.llvm_version,
+    )
+    host_tools_info = dict([
+        pair
+        for (key, tool_path, features) in [
+            # This is used for macOS hosts:
+            ("libtool", "/usr/bin/libtool", [_host_tool_features.SUPPORTS_ARG_FILE]),
+            # This is used with old (pre 7) LLVM versions:
+            ("strip", "/usr/bin/strip", []),
+            # This is used when lld doesn't support the target platform (i.e.
+            # Mach-O for macOS):
+            ("ld", "/usr/bin/ld", []),
+        ]
+        for pair in _host_tools.get_tool_info(rctx, tool_path, features, key).items()
+    ])
+    cc_toolchains_str, toolchain_labels_str = _cc_toolchains_str(
+        workspace_name,
+        toolchain_info,
+        use_absolute_paths,
+        host_tools_info,
+    )
+
+    # Convenience macro to register all generated toolchains.
+    rctx.template(
+        "toolchains.bzl",
+        Label("//toolchain:toolchains.bzl.tpl"),
+        {
+            "%{toolchain_labels}": toolchain_labels_str,
+        },
+    )
+
+    # BUILD file with all the generated toolchain definitions.
+    rctx.template(
+        "BUILD.bazel",
+        Label("//toolchain:BUILD.toolchain.tpl"),
+        {
+            "%{cc_toolchains}": cc_toolchains_str,
+            "%{cc_toolchain_config_bzl}": str(rctx.attr._cc_toolchain_config_bzl),
+        },
+    )
+
+    # CC wrapper script; see comments near the definition of `wrapper_bin_prefix`.
+    if os == "darwin":
+        cc_wrapper_tpl = "//toolchain:osx_cc_wrapper.sh.tpl"
+    else:
+        cc_wrapper_tpl = "//toolchain:cc_wrapper.sh.tpl"
+    rctx.template(
+        "bin/cc_wrapper.sh",
+        Label(cc_wrapper_tpl),
+        {
+            "%{toolchain_path_prefix}": toolchain_path_prefix,
+        },
+    )
+
+    # libtool wrapper; used if the host libtool doesn't support arg files:
+    rctx.template(
+        "bin/host_libtool_wrapper.sh",
+        Label("//toolchain:host_libtool_wrapper.sh.tpl"),
+        {
+            "%{libtool_path}": "/usr/bin/libtool",
+        },
+    )
+
+def _cc_toolchains_str(
+        workspace_name,
+        toolchain_info,
+        use_absolute_paths,
+        host_tools_info):
+    # Since all the toolchains rely on downloading the right LLVM toolchain for
+    # the host architecture, we don't need to explicitly specify
+    # `exec_compatible_with` attribute. If the host and execution platform are
+    # not the same, then host auto-detection based LLVM download does not work
+    # and the user has to explicitly specify the distribution of LLVM they
+    # want.
+
+    # Note that for cross-compiling, the toolchain configuration will need
+    # appropriate sysroots. A recommended approach is to configure two
+    # `llvm_toolchain` repos, one without sysroots (for easy single platform
+    # builds) and register this one, and one with sysroots and provide
+    # `--extra_toolchains` flag when cross-compiling.
+
+    cc_toolchains_str = ""
+    toolchain_names = []
+    for (target_os, target_arch) in _supported_targets:
+        suffix = "{}-{}".format(target_arch, target_os)
+        cc_toolchain_str = _cc_toolchain_str(
+            suffix,
+            target_os,
+            target_arch,
+            toolchain_info,
+            use_absolute_paths,
+            host_tools_info,
+        )
+        if cc_toolchain_str:
+            cc_toolchains_str = cc_toolchains_str + cc_toolchain_str
+            toolchain_name = "@{}//:cc-toolchain-{}".format(workspace_name, suffix)
+            toolchain_names.append(toolchain_name)
+
+    sep = ",\n" + " " * 8  # 2 tabs with tabstop=4.
+    toolchain_labels_str = sep.join(["\"{}\"".format(d) for d in toolchain_names])
+    return cc_toolchains_str, toolchain_labels_str
+
+def _cc_toolchain_str(
+        suffix,
+        target_os,
+        target_arch,
+        toolchain_info,
+        use_absolute_paths,
+        host_tools_info):
+    host_os = toolchain_info.os
+    host_arch = toolchain_info.arch
+
+    host_os_bzl = _os_bzl(host_os)
+    target_os_bzl = _os_bzl(target_os)
+
+    sysroot_path, sysroot = _sysroot_path(
+        toolchain_info.sysroot_dict,
+        target_os,
+        target_arch,
+    )
+    if not sysroot_path:
+        if host_os == target_os and host_arch == target_arch:
+            # For darwin -> darwin, we can use the macOS SDK path.
+            sysroot_path = toolchain_info.default_sysroot_path
+        else:
+            # We are trying to cross-compile without a sysroot, let's bail.
+            # TODO: Are there situations where we can continue?
+            return ""
+
+    extra_files_str = ", \":llvm\", \":wrapper-files\""
+
+    additional_include_dirs = toolchain_info.additional_include_dirs_dict.get(_os_arch_pair(target_os, target_arch))
+    additional_include_dirs_str = "[]"
+    if additional_include_dirs:
+        additional_include_dirs_str = "[{}]".format(
+            ", ".join(["\"{}\"".format(d) for d in additional_include_dirs]),
+        )
+
+    sysroot_label_str = "\"%s\"" % str(sysroot) if sysroot else ""
+
+    # `struct` isn't allowed in `BUILD` files so we JSON encode + decode to turn
+    # them into `dict`s.
+    host_tools_info = json.decode(json.encode(host_tools_info))
+
+    template = """
+# CC toolchain for cc-clang-{suffix}.
+
+cc_toolchain_config(
+    name = "local-{suffix}",
+    host_arch = "{host_arch}",
+    host_os = "{host_os}",
+    target_arch = "{target_arch}",
+    target_os = "{target_os}",
+    toolchain_path_prefix = "{toolchain_path_prefix}",
+    tools_path_prefix = "{tools_path_prefix}",
+    wrapper_bin_prefix = "{wrapper_bin_prefix}",
+    sysroot_path = "{sysroot_path}",
+    additional_include_dirs = {additional_include_dirs_str},
+    llvm_version = "{llvm_version}",
+    host_tools_info = {host_tools_info},
+)
+
+toolchain(
+    name = "cc-toolchain-{suffix}",
+    exec_compatible_with = [
+        "@platforms//cpu:{host_arch}",
+        "@platforms//os:{host_os_bzl}",
+    ],
+    target_compatible_with = [
+        "@platforms//cpu:{target_arch}",
+        "@platforms//os:{target_os_bzl}",
+    ],
+    toolchain = ":cc-clang-{suffix}",
+    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+)
+"""
+
+    if use_absolute_paths:
+        template = template + """
+cc_toolchain(
+    name = "cc-clang-{suffix}",
+    all_files = ":empty",
+    compiler_files = ":empty",
+    dwp_files = ":empty",
+    linker_files = ":empty",
+    objcopy_files = ":empty",
+    strip_files = ":empty",
+    toolchain_config = "local-{suffix}",
+)
+"""
+    else:
+        template = template + """
+filegroup(
+    name = "sysroot-components-{suffix}",
+    srcs = [{sysroot_label_str}],
+)
+
+filegroup(
+    name = "compiler-components-{suffix}",
+    srcs = [
+        "{toolchain_root}:clang",
+        "{toolchain_root}:include",
+        ":sysroot-components-{suffix}",
+    ],
+)
+
+filegroup(
+    name = "linker-components-{suffix}",
+    srcs = [
+        "{toolchain_root}:clang",
+        "{toolchain_root}:ld",
+        "{toolchain_root}:ar",
+        "{toolchain_root}:lib",
+        ":sysroot-components-{suffix}",
+    ],
+)
+
+filegroup(
+    name = "all-components-{suffix}",
+    srcs = [
+        "{toolchain_root}:bin",
+        ":compiler-components-{suffix}",
+        ":linker-components-{suffix}",
+    ],
+)
+
+filegroup(name = "all-files-{suffix}", srcs = [":all-components-{suffix}"{extra_files_str}])
+filegroup(name = "archiver-files-{suffix}", srcs = ["{toolchain_root}:ar"{extra_files_str}])
+filegroup(name = "assembler-files-{suffix}", srcs = ["{toolchain_root}:as"{extra_files_str}])
+filegroup(name = "compiler-files-{suffix}", srcs = [":compiler-components-{suffix}"{extra_files_str}])
+filegroup(name = "dwp-files-{suffix}", srcs = ["{toolchain_root}:dwp"{extra_files_str}])
+filegroup(name = "linker-files-{suffix}", srcs = [":linker-components-{suffix}"{extra_files_str}])
+filegroup(name = "objcopy-files-{suffix}", srcs = ["{toolchain_root}:objcopy"{extra_files_str}])
+filegroup(name = "strip-files-{suffix}", srcs = ["{toolchain_root}:strip"{extra_files_str}])
+
+cc_toolchain(
+    name = "cc-clang-{suffix}",
+    all_files = "all-files-{suffix}",
+    ar_files = "archiver-files-{suffix}",
+    as_files = "assembler-files-{suffix}",
+    compiler_files = "compiler-files-{suffix}",
+    dwp_files = "dwp-files-{suffix}",
+    linker_files = "linker-files-{suffix}",
+    objcopy_files = "objcopy-files-{suffix}",
+    strip_files = "strip-files-{suffix}",
+    toolchain_config = "local-{suffix}",
+)
+"""
+
+    return template.format(
+        suffix = suffix,
+        target_os = target_os,
+        target_arch = target_arch,
+        host_os = host_os,
+        host_arch = host_arch,
+        target_os_bzl = target_os_bzl,
+        host_os_bzl = host_os_bzl,
+        toolchain_root = toolchain_info.toolchain_root,
+        toolchain_path_prefix = toolchain_info.toolchain_path_prefix,
+        tools_path_prefix = toolchain_info.tools_path_prefix,
+        wrapper_bin_prefix = toolchain_info.wrapper_bin_prefix,
+        additional_include_dirs_str = additional_include_dirs_str,
+        sysroot_label_str = sysroot_label_str,
+        sysroot_path = sysroot_path,
+        llvm_version = toolchain_info.llvm_version,
+        extra_files_str = extra_files_str,
+        host_tools_info = host_tools_info,
+    )