mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:40:11 +01:00
Per chandlerc's comment: First, this builds inside the Bazel tree rather than in the source repository. This ensures we start in a clean directory each time the repository rule is run again. We don't need to detect an existing build with this, and it will only be rebuilt when the workspace file or the repository rule implementation is changed. This can be forced by using: ``` bazel sync --configure ``` Second, we use an implicit dependency on the `WORKSPACE` file to locate the workspace directory automatically, and the `HEAD` file from the `llvm-project` submodule to trigger a rebuild if the submodule is updated. Third, teach the CMake script to try to use a system-installed `clang` if installed and not overridden by the `CC` environment variable. This is very different from the prior logic -- this is only used with the CMake build, and so should work with any system C++ compiler that can build Clang and LLVM. Lastly, this tweaks the CMake options to tune this build given that we now fully control it and it will only be used in this context. This still results in a 1.5gb build for me. =/ But its as small as I can make it really. It's a frustrating long list, but I couldn't find a more brief way of representing this. Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
235 lines
8.8 KiB
Python
235 lines
8.8 KiB
Python
# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
# Exceptions. See /LICENSE for license information.
|
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
"""Starlark rules to bootstrap Clang (and LLVM).
|
|
|
|
These rules are loaded as part of the `WORKSPACE`, and used by
|
|
`clang_configuration.bzl`. The llvm-project submodule is used for the build.
|
|
"""
|
|
|
|
def _run(
|
|
repository_ctx,
|
|
cmd,
|
|
timeout = 10,
|
|
environment = {},
|
|
quiet = True):
|
|
"""Runs the provided `cmd`, checks for failure, and returns the result."""
|
|
exec_result = repository_ctx.execute(
|
|
cmd,
|
|
timeout = timeout,
|
|
environment = environment,
|
|
quiet = quiet,
|
|
)
|
|
if exec_result.return_code != 0:
|
|
fail("Unable to run command successfully: %s" % str(cmd))
|
|
|
|
return exec_result
|
|
|
|
def _detect_system_clang(repository_ctx):
|
|
"""Detects whether a system-provided clang can be used.
|
|
|
|
Returns a tuple of (is_clang, environment).
|
|
"""
|
|
|
|
# If the user provides an explicit `CC` environment variable, use that as
|
|
# the compiler.
|
|
cc = repository_ctx.os.environ.get("CC")
|
|
cxx = repository_ctx.os.environ.get("CXX")
|
|
if cc or cxx:
|
|
version_output = _run(repository_ctx, [cc, "--version"]).stdout
|
|
return "clang" in version_output, {}
|
|
|
|
# If we can build our Clang toolchain using a system-installed Clang, try
|
|
# to do so.
|
|
system_clang = repository_ctx.which("clang")
|
|
if system_clang:
|
|
return True, {
|
|
"CC": str(system_clang),
|
|
"CXX": str(system_clang) + "++",
|
|
}
|
|
return False, {}
|
|
|
|
def _get_cmake_defines(repository_ctx, is_clang):
|
|
"""Returns a long list of cmake defines for the bootstrap."""
|
|
modules_setting = "OFF"
|
|
if is_clang:
|
|
modules_setting = "ON"
|
|
|
|
static_link_cxx = "ON"
|
|
unstable_libcxx_abi = "ON"
|
|
if repository_ctx.os.name.lower().startswith("mac os"):
|
|
# macOS doesn't support the static C++ standard library linking. Turn
|
|
# it off here, and disable the unstable libc++ ABI as we will also be
|
|
# unable to use it later on.
|
|
static_link_cxx = "OFF"
|
|
unstable_libcxx_abi = "OFF"
|
|
|
|
return [
|
|
"-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra;lld;libcxx;libcxxabi;compiler-rt;libunwind",
|
|
"-DCMAKE_BUILD_TYPE=Release",
|
|
"-DLLVM_ENABLE_ASSERTIONS=OFF",
|
|
"-DLLVM_ENABLE_MODULES=" + modules_setting,
|
|
"-DLLVM_STATIC_LINK_CXX_STDLIB=" + static_link_cxx,
|
|
"-DLLVM_TARGETS_TO_BUILD=AArch64;X86",
|
|
"-DLIBCXX_ABI_UNSTABLE=" + unstable_libcxx_abi,
|
|
"-DLIBCXX_ENABLE_ASSERTIONS=OFF",
|
|
"-DLIBCXXABI_ENABLE_ASSERTIONS=OFF",
|
|
|
|
# Disable components of the build that we don't use while building Carbon.
|
|
"-DCLANG_ENABLE_ARCMT=OFF",
|
|
"-DCLANG_INCLUDE_TESTS=OFF",
|
|
"-DCLANG_TOOL_APINOTES_TEST_BUILD=OFF",
|
|
"-DCLANG_TOOL_ARCMT_TEST_BUILD=OFF",
|
|
"-DCLANG_TOOL_CLANG_CHECK_BUILD=OFF",
|
|
"-DCLANG_TOOL_CLANG_DIFF_BUILD=OFF",
|
|
"-DCLANG_TOOL_CLANG_EXTDEF_MAPPING_BUILD=OFF",
|
|
"-DCLANG_TOOL_CLANG_FUZZER_BUILD=OFF",
|
|
"-DCLANG_TOOL_CLANG_IMPORT_TEST_BUILD=OFF",
|
|
"-DCLANG_TOOL_CLANG_OFFLOAD_BUNDLER_BUILD=OFF",
|
|
"-DCLANG_TOOL_CLANG_OFFLOAD_WRAPPER_BUILD=OFF",
|
|
"-DCLANG_TOOL_CLANG_SCAN_DEPS_BUILD=OFF",
|
|
"-DCLANG_TOOL_CLANG_SHLIB_BUILD=OFF",
|
|
"-DCLANG_TOOL_C_ARCMT_TEST_BUILD=OFF",
|
|
"-DCLANG_TOOL_C_INDEX_TEST_BUILD=OFF",
|
|
"-DCLANG_TOOL_DIAGTOOL_BUILD=OFF",
|
|
"-DCLANG_TOOL_LIBCLANG_BUILD=OFF",
|
|
"-DCLANG_TOOL_SCAN_BUILD_BUILD=OFF",
|
|
"-DCLANG_TOOL_SCAN_VIEW_BUILD=OFF",
|
|
"-DLLVM_BUILD_UTILS=OFF",
|
|
"-DLLVM_ENABLE_BINDINGS=OFF",
|
|
"-DLLVM_ENABLE_LIBXML2=OFF",
|
|
"-DLLVM_ENABLE_OCAMLDOC=OFF",
|
|
"-DLLVM_INCLUDE_BENCHMARKS=OFF",
|
|
"-DLLVM_INCLUDE_DOCS=OFF",
|
|
"-DLLVM_INCLUDE_EXAMPLES=OFF",
|
|
"-DLLVM_INCLUDE_GO_TESTS=OFF",
|
|
"-DLLVM_INCLUDE_TESTS=OFF",
|
|
"-DLLVM_INCLUDE_UTILS=OFF",
|
|
"-DLLVM_TOOL_BUGPOINT_BUILD=OFF",
|
|
"-DLLVM_TOOL_BUGPOINT_PASSES_BUILD=OFF",
|
|
"-DLLVM_TOOL_DSYMUTIL_BUILD=OFF",
|
|
"-DLLVM_TOOL_GOLD_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLC_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLI_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_AS_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_BCANALYZER_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_CAT_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_CFI_VERIFY_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_CONFIG_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_CVTRES_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_CXXDUMP_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_CXXFILT_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_CXXMAP_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_C_TEST_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_DIFF_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_DWARFDUMP_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_ELFABI_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_EXEGESIS_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_EXTRACT_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_GO_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_GSYMUTIL_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_IFS_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_ISEL_FUZZER_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_ITANIUM_DEMANGLE_FUZZER_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_JITLINK_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_JITLISTENER_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_LIBTOOL_DARWIN_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_LINK_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_LIPO_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_LTO2_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_LTO_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_MCA_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_MC_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_ML_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_MICROSOFT_DEMANGLE_FUZZER_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_MT_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_OPT_FUZZER_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_PDBUTIL_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_PROFDATA_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_PROFGEN_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_RC_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_READOBJ_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_REDUCE_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_RTDYLD_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_SHLIB_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_SIZE_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_SPECIAL_CASE_LIST_FUZZER_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_SPLIT_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_STRESS_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_STRINGS_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_XRAY_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_YAML_NUMERIC_PARSER_FUZZER_BUILD=OFF",
|
|
"-DLLVM_TOOL_LLVM_YAML_PARSER_FUZZER_BUILD=OFF",
|
|
"-DLLVM_TOOL_LTO_BUILD=OFF",
|
|
"-DLLVM_TOOL_OBJ2YAML_BUILD=OFF",
|
|
"-DLLVM_TOOL_OPT_BUILD=OFF",
|
|
"-DLLVM_TOOL_OPT_VIEWER_BUILD=OFF",
|
|
"-DLLVM_TOOL_REMARKS_SHLIB_BUILD=OFF",
|
|
"-DLLVM_TOOL_SPLIT_FILE_BUILD=OFF",
|
|
"-DLLVM_TOOL_VERIFY_USELISTORDER_BUILD=OFF",
|
|
"-DLLVM_TOOL_YAML2OBJ_BUILD=OFF",
|
|
]
|
|
|
|
def _bootstrap_clang_toolchain_impl(repository_ctx):
|
|
"""Returns the path a bootstrapped Clang executable.
|
|
|
|
This bootstraps Clang and the rest of the LLVM toolchain from the LLVM
|
|
submodule.
|
|
"""
|
|
repository_ctx.report_progress("Configuring Clang toolchain bootstrap...")
|
|
is_clang, environment = _detect_system_clang(repository_ctx)
|
|
|
|
cmake = repository_ctx.which("cmake")
|
|
if not cmake:
|
|
fail("`cmake` not found: is it installed?")
|
|
ninja = repository_ctx.which("ninja")
|
|
if not ninja:
|
|
fail("`ninja` not found: is it installed?")
|
|
|
|
workspace_dir = repository_ctx.path(repository_ctx.attr._workspace).dirname
|
|
llvm_dir = repository_ctx.path("%s/third_party/llvm-project/llvm" %
|
|
workspace_dir)
|
|
|
|
repository_ctx.report_progress(
|
|
"Running CMake for the Clang toolchain build...",
|
|
)
|
|
cmake_args = [cmake, "-G", "Ninja", str(llvm_dir)]
|
|
cmake_args += _get_cmake_defines(repository_ctx, is_clang)
|
|
_run(
|
|
repository_ctx,
|
|
cmake_args,
|
|
timeout = 600,
|
|
environment = environment,
|
|
# This is very slow, so print output as a form of progress.
|
|
quiet = False,
|
|
)
|
|
|
|
# Run ninja for the final build.
|
|
repository_ctx.report_progress("Building the Clang toolchain...")
|
|
_run(
|
|
repository_ctx,
|
|
[ninja],
|
|
timeout = 10800,
|
|
# This is very slow, so print output as a form of progress.
|
|
quiet = False,
|
|
)
|
|
|
|
# Create an empty BUILD file to mark the package. The files are used without
|
|
# Bazel labels directly pointing at them.
|
|
repository_ctx.file("BUILD", content = "")
|
|
|
|
bootstrap_clang_toolchain = repository_rule(
|
|
implementation = _bootstrap_clang_toolchain_impl,
|
|
configure = True,
|
|
attrs = {
|
|
# We use a label pointing at the workspace file to compute the
|
|
# workspace directory.
|
|
"_workspace": attr.label(
|
|
default = Label("//:WORKSPACE"),
|
|
allow_single_file = True,
|
|
),
|
|
},
|
|
environ = ["CC", "CXX"],
|
|
)
|