diff --git a/.bazelrc b/.bazelrc index d8130669d9fb..4a2c465678a7 100644 --- a/.bazelrc +++ b/.bazelrc @@ -16,13 +16,18 @@ build --host_crosstool_top=@bazel_cc_toolchain # https://github.com/bazelbuild/bazel/issues/13315 build --incompatible_dont_enable_host_nonhost_crosstool_features=false +# Default dynamic linking to off. While this can help build performance in some +# edge cases with very large linked executables and a slow linker, between using +# fast linkers on all platforms (LLD and the Apple linker), as well as having +# relatively few such executables, shared objects simply waste too much space in +# our builds. +build --dynamic_mode=off + # Completely disable Bazel's automatic stripping of debug information. Removing # that information causes unhelpful backtraces from unittest failures and other # crashes. Optimized builds already avoid using debug information by default. build --strip=never -build:force_local_bootstrap --repo_env=CARBON_FORCE_LOCAL_BOOTSTRAP_BUILD=1 - # Configuration for enabling Address Sanitizer. Note that this is enabled by # default for fastbuild. The config is provided to enable ASan even in # optimized or other build configurations. diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 11febbf70a30..b4c6874e1c9d 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -58,11 +58,47 @@ jobs: go get github.com/bazelbuild/bazelisk echo "$(go env GOPATH)/bin" >> $GITHUB_PATH - # Print the various tool versions to help in debugging. - - name: Print tool versions + # Setup to the latest LLVM and Clang release on Linux runners. + # + # Ideally we would use the pre-installed versions in the image, but the + # debian packages for LLVM-12 are broken due to several bugs: + # https://bugs.llvm.org/show_bug.cgi?id=43604 + # https://bugs.llvm.org/show_bug.cgi?id=46321 + # + # For now, we rely on Homebrew to manage installing a correctly built + # toolchain. We also take some care to be as resilient as possible to + # issues fetching and installing the toolchain. + - name: Setup LLVM and Clang on Ubuntu + if: matrix.os == 'ubuntu-latest' run: | + brew update + brew install --force-bottle --only-dependencies llvm + brew install --force-bottle --force --verbose llvm + brew info llvm + brew config + echo "$(brew --prefix llvm)/bin" >> $GITHUB_PATH + + # Just add the Homebrew installed LLVM to the path on macOS, the image has + # LLVM-12 pre-installed. + - name: Setup LLVM and Clang on macOS + if: matrix.os == 'macos-latest' + run: | + echo "$(brew --prefix llvm)/bin" >> $GITHUB_PATH + + # Print the various tool paths and versions to help in debugging. + - name: Print tool debugging info + run: | + echo $PATH + which bazelisk bazelisk --version + which python python --version + which clang + clang --version + which clang++ + clang++ --version + which clang-format + clang-format --version # Make the date available to subsequent steps. - name: Get date diff --git a/WORKSPACE b/WORKSPACE index b84a4921ddae..07441933073c 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -21,18 +21,10 @@ pip_install( requirements = "//github_tools:requirements.txt", ) -# Bootstrap a Clang and LLVM toolchain. -load("//bazel/cc_toolchains:clang_bootstrap.bzl", "bootstrap_clang_toolchain") - -bootstrap_clang_toolchain(name = "bootstrap_clang_toolchain") - # Configure the bootstrapped Clang and LLVM toolchain for Bazel. load("//bazel/cc_toolchains:clang_configuration.bzl", "configure_clang_toolchain") -configure_clang_toolchain( - name = "bazel_cc_toolchain", - clang = "@bootstrap_clang_toolchain//:bin/clang", -) +configure_clang_toolchain(name = "bazel_cc_toolchain") local_repository( name = "llvm_bazel", diff --git a/bazel-clang-toolchain b/bazel-clang-toolchain deleted file mode 120000 index 527bc7f3f50a..000000000000 --- a/bazel-clang-toolchain +++ /dev/null @@ -1 +0,0 @@ -bazel-out/../../../external/bootstrap_clang_toolchain \ No newline at end of file diff --git a/bazel/cc_toolchains/clang_bootstrap.bzl b/bazel/cc_toolchains/clang_bootstrap.bzl deleted file mode 100644 index d9511ab11f2d..000000000000 --- a/bazel/cc_toolchains/clang_bootstrap.bzl +++ /dev/null @@ -1,280 +0,0 @@ -# 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. -""" - -FORCE_LOCAL_BOOTSTRAP_ENV = "CARBON_FORCE_LOCAL_BOOTSTRAP_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 _local_cmake_build_clang_toolchain(repository_ctx): - """Locally build the LLVM toolchain with CMake and Ninja. - - This is used as a fallback for when we can't download a prebuilt set of - binaries and libraries for a particular platform. - """ - 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, - ) - -def _download_prebuilt_toolchain(repository_ctx): - """Downloads and extracts an LLVM build for the current platform. - - Returns `True` when a toolchain can be successfully downloaded. - """ - repository_ctx.report_progress("Checking for a downloadable toolchain...") - os = repository_ctx.os.name - if os == "linux": - url = "https://github.com/mmdriley/llvm-builds/releases/download/r32/llvm-linux.tar.xz" - sha256 = "db9f2698aa84935efca3402bdebada127de16f6746adbe54d4cdb7e3b8fec5f3" - elif os == "mac os x": - url = "https://github.com/mmdriley/llvm-builds/releases/download/r32/llvm-macos.tar.xz" - sha256 = "937b81c235977ed2b265baf656f30b7a03c33b6299090d91beb72c2b41846673" - elif os.startswith("windows"): - url = "https://github.com/mmdriley/llvm-builds/releases/download/r32/llvm-windows.tar.xz" - sha256 = "b6b015f9f2fcfb79381004e6a3ae925df4fb827cf7e07f3d5b0b66210fddd172" - else: - print(("No prebuilt LLVM toolcahin to download for {}, falling back " + - "to a local build. This may be very slow!").format(os)) - return False - - repository_ctx.report_progress("Downloading and extracting a toolchain...") - repository_ctx.download_and_extract(url, sha256 = sha256) - return True - -def _bootstrap_clang_toolchain_impl(repository_ctx): - """Bootstrap a fresh Clang and LLVM toolchain for use. - - This will first try to download a pre-built archive of the LLVM toolchain - if one is available. - - Otherwise will locally build the toolchain using CMake out of the LLVM - submodule. - """ - force_local_build = False - if FORCE_LOCAL_BOOTSTRAP_ENV in repository_ctx.os.environ: - print("Forcing a local bootstrap build. This may be very slow!") - force_local_build = True - - if force_local_build or not _download_prebuilt_toolchain(repository_ctx): - # Fallback to a local build. - _local_cmake_build_clang_toolchain(repository_ctx) - - # Create a BUILD file to mark the package. The files are usually used - # without Bazel labels, but the export allows dependencies; for example, to - # use clang-tidy. - repository_ctx.file("BUILD", 'exports_files(glob(["bin/*"]))') - -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", FORCE_LOCAL_BOOTSTRAP_ENV], -) diff --git a/bazel/cc_toolchains/clang_cc_toolchain_config.bzl b/bazel/cc_toolchains/clang_cc_toolchain_config.bzl index eb10105ca1f0..93635d3f4148 100644 --- a/bazel/cc_toolchains/clang_cc_toolchain_config.bzl +++ b/bazel/cc_toolchains/clang_cc_toolchain_config.bzl @@ -272,6 +272,8 @@ def _impl(ctx): actions = codegen_compile_actions, flag_groups = [flag_group(flags = [ "-O1", + "-mllvm", + "-fast-isel", ])], )], ) @@ -444,10 +446,14 @@ def _impl(ctx): # We don't need the recovery behavior of UBSan as we expect # builds to be clean. Not recoverying is a bit cheaper. "-fno-sanitize-recover=undefined", + # Don't embed the full path name for files. This limits the size + # and combined with line numbers is unlikely to result in many + # ambiguities. + "-fsanitize-undefined-strip-path-components=-1", # Force some expensive UBSan checks to the cheaper trap mode. # The dedicated debugging message is unlikely to be critical for # these. - "-fsanitize-trap=alignment,null,return,unreachable", + "-fsanitize-trap=alignment,bool,null,return,unreachable", # Needed due to clang AST issues, such as in # clang/AST/Redeclarable.h line 199. "-fno-sanitize=vptr", @@ -484,17 +490,24 @@ def _impl(ctx): flag_group( flags = [ "-fuse-ld=lld", - "-Wl,-no-as-needed", - # Force the C++ standard library to be statically - # linked. This works even with libc++ despite the - # name, however we have to manually link the ABI - # library and libunwind. + "-stdlib=libc++", + "-unwindlib=libunwind", + # Force the C++ standard library and runtime + # libraries to be statically linked. This works even + # with libc++ and libunwind despite the names, + # provided libc++ is built with two CMake options: + # - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON` + # - `-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY` + # These are both required because of PR43604 + # (impacting at least Debian packages of libc++) and + # PR46321 (impacting most other packages). + # We recommend using Homebrew's LLVM install on + # Linux. "-static-libstdc++", - # Force static linking with libc++abi as well. - "-l:libc++abi.a", + "-static-libgcc", # Link with Clang's runtime library. This is always # linked statically. - #"-rtlib=compiler-rt", + "-rtlib=compiler-rt", # Explicitly add LLVM libs to the search path to # preempt the detected GCC installation's library # paths. Those might have a system installed libc++ @@ -734,10 +747,10 @@ def _impl(ctx): # Next, add the features based on the target platform. Here too the # features are order sensitive. We also setup the sysroot here. - if (ctx.attr.target_cpu == "k8"): + if ctx.attr.target_cpu == "k8": features += [linux_flags_feature] sysroot = None - elif (ctx.attr.target_cpu == "darwin"): + elif ctx.attr.target_cpu in ["darwin", "darwin_arm64"]: sysroot = sysroot_dir else: fail("Unsupported target platform!") diff --git a/bazel/cc_toolchains/clang_configuration.bzl b/bazel/cc_toolchains/clang_configuration.bzl index 64a1b2c6679b..11c24dffcf62 100644 --- a/bazel/cc_toolchains/clang_configuration.bzl +++ b/bazel/cc_toolchains/clang_configuration.bzl @@ -17,6 +17,30 @@ def _run(repository_ctx, cmd): return exec_result +def _detect_system_clang(repository_ctx): + """Detects whether the 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. This should point at the `clang` executable to use. + cc = repository_ctx.os.environ.get("CC") + if cc: + version_output = _run(repository_ctx, [cc, "--version"]).stdout + if not "clang" in version_output: + fail("The `CC` environment variable is not a Clang compiler.") + return repository_ctx.path(cc) + + # Try looking on the path. We check for the specific versioned name and then the normal name. + system_clang = repository_ctx.which("clang-12") + if not system_clang: + system_clang = repository_ctx.which("clang") + if not system_clang: + fail("Unable to find a `clang` executable on the system path.") + + return system_clang + def _compute_clang_resource_dir(repository_ctx, clang): """Runs the `clang` binary to get its resource dir.""" output = _run( @@ -88,15 +112,14 @@ def _configure_clang_toolchain_impl(repository_ctx): "cc_toolchain_config.bzl", ) - # Run the bootstrapped clang to detect relevant features for the toolchain. - clang = repository_ctx.path(repository_ctx.attr.clang) - if clang.basename != "clang": - fail("The provided Clang binary must be `clang`, but is `%s` (%s)" % - (clang.basename, str(clang))) + # Find a Clang C++ compiler, and where it lives. We need to walk symlinks + # here as the other LLVM tools may not be symlinked into the PATH even if + # `clang` is. We also insist on finding the basename of `clang++` as that is + # important for C vs. C++ compiles. + clang = _detect_system_clang(repository_ctx) + clang = clang.realpath.dirname.get_child("clang++") - # Adjust this to the "clang++" binary to ensure we get the correct behavior - # when configuring it. - clang = repository_ctx.path(str(clang) + "++") + # Compute the various directories used by Clang. resource_dir = _compute_clang_resource_dir(repository_ctx, clang) sysroot_dir = None if repository_ctx.os.name.lower().startswith("mac os"): @@ -124,6 +147,7 @@ def _configure_clang_toolchain_impl(repository_ctx): configure_clang_toolchain = repository_rule( implementation = _configure_clang_toolchain_impl, configure = True, + local = True, attrs = { "_clang_toolchain_build": attr.label( default = Label("//bazel/cc_toolchains:clang_toolchain.BUILD"), @@ -141,11 +165,6 @@ configure_clang_toolchain = repository_rule( ), allow_single_file = True, ), - # This must point at the `clang` binary inside a full LLVM toolchain - # installation. - "clang": attr.label( - allow_single_file = True, - mandatory = True, - ), }, + environ = ["CC"], ) diff --git a/bazel/cc_toolchains/clang_toolchain.BUILD b/bazel/cc_toolchains/clang_toolchain.BUILD index 9e27b3832e2f..dc45b926983d 100644 --- a/bazel/cc_toolchains/clang_toolchain.BUILD +++ b/bazel/cc_toolchains/clang_toolchain.BUILD @@ -21,6 +21,7 @@ cc_toolchain_suite( name = "bazel_cc_toolchain", toolchains = { "darwin": ":cc-compiler-darwin", + "darwin_arm64": ":cc-compiler-darwin-arm64", "k8": ":cc-compiler-k8", }, ) @@ -64,3 +65,23 @@ cc_toolchain_config( name = "local-darwin", target_cpu = "darwin", ) + +cc_toolchain( + name = "cc-compiler-darwin-arm64", + 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, + toolchain_config = ":local-darwin-arm64", + toolchain_identifier = "local-darwin-arm64", +) + +cc_toolchain_config( + name = "local-darwin-arm64", + target_cpu = "darwin_arm64", +) diff --git a/compile_flags.txt b/compile_flags.txt index d81c00223333..b9d01a5d249c 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -76,11 +76,7 @@ bazel-execroot/external/llvm-project/llvm/utils/unittest/googletest/include -isystem bazel-bin/external/llvm-project/llvm/utils/unittest/googletest/include -std=c++17 --nostdinc++ --isystem -bazel-clang-toolchain/include/c++/v1 --isystem -bazel-clang-toolchain/lib/clang/12.0.0/include +-stdlib=libc++ -no-canonical-prefixes -Wno-builtin-macro-redefined -D__DATE__="redacted" diff --git a/docs/project/contribution_tools.md b/docs/project/contribution_tools.md index 33768f64b93b..19dc383caa45 100644 --- a/docs/project/contribution_tools.md +++ b/docs/project/contribution_tools.md @@ -25,7 +25,7 @@ contributions. - [Bazel and Bazelisk](#bazel-and-bazelisk) - [buildifier](#buildifier) - [Clang and LLVM](#clang-and-llvm) - - [Ninja](#ninja) + - [Manual installations (not recommended)](#manual-installations-not-recommended) - [pre-commit](#pre-commit) - [Optional tools](#optional-tools) - [Carbon-maintained](#carbon-maintained) @@ -188,23 +188,52 @@ Our recommended way of installing is: ### Clang and LLVM [Clang](https://clang.llvm.org/) and [LLVM](https://llvm.org/) are used to -compile and link Carbon, and are provided through git submodules. A complete -toolchain will be built and cached as part of standard `bazel` execution. This -can be very slow on less powerful computers or laptops (30 minutes to an hour). -However, it should only happen when either Bazel or LLVM's submodule is updated, -which we try to minimize. If you need to force a rebuild of the toolchain, you -can use `bazel sync --configure`. - -### Ninja - -[Ninja](https://ninja-build.org/) is used to build Clang and LLVM. +compile and link Carbon as part of its build. Their source code are also +provided through git submodules for incorporation into Carbon or Carbon tools as +libraries. While the source submodule tracks upstream LLVM, the project expects +the LLVM 12 release (or newer) to be installed with Clang and other tools in +your `PATH` for use in building Carbon itself. Our recommended way of installing is: ```bash -brew install ninja +brew install llvm ``` +`llvm` is keg-only; bear in mind this requires updating `PATH` for it because +it's not part of the standard Homebrew path. Read the output of `brew install` +for the necessary path changes, or add something to your `PATH` like: + +```bash +export PATH="$(brew --prefix llvm)/bin:${PATH}" +``` + +Carbon expects the `PATH` to include the installed tooling. If set, `CC` should +also point at `clang`. Our build environment will detect the `clang` binary +using `CC` then `PATH`, and will expect the rest of the LLVM toolchain to be +available in the same directory as `clang`. However, various scripts and tools +assume that the LLVM toolchain will be in `PATH`, particularly for tools like +`clang-format` and `clang-tidy`. + +> TODO: We'd like to use `apt`, but standard LLVM Debian packages are not +> configured correctly for our needs. We are currently aware of two libc++ +> issues, [43604](https://bugs.llvm.org/show_bug.cgi?id=43604) and +> [46321](https://bugs.llvm.org/show_bug.cgi?id=46321). + +#### Manual installations (not recommended) + +You can also build and install `LLVM` yourself if you prefer. The essential +CMake options to pass in order for this to work reliably include: + +``` +-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra;lld +-DLLVM_ENABLE_RUNTIMES=compiler-rt;libcxx;libcxxabi;libunwind +-DRUNTIMES_CMAKE_ARGS=-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF;-DCMAKE_POSITION_INDEPENDENT_CODE=ON;-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON;-DLIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY=OFF;-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY=ON;-DLIBCXX_USE_COMPILER_RT=ON;-DLIBCXXABI_USE_COMPILER_RT=ON;-DLIBCXXABI_USE_LLVM_UNWINDER=ON +``` + +However, we primarily test against the Homebrew installation, so if building +LLVM and Clang yourself you may hit some issues. + ### pre-commit We use [pre-commit](https://pre-commit.com) to run diff --git a/migrate_cpp/BUILD b/migrate_cpp/BUILD index 2f936103e748..4e042d7fc86e 100644 --- a/migrate_cpp/BUILD +++ b/migrate_cpp/BUILD @@ -10,7 +10,6 @@ py_binary( data = [ ":clang_tidy.yaml", "//migrate_cpp/cpp_refactoring", - "@bootstrap_clang_toolchain//:bin/clang-tidy", ], python_version = "PY3", ) diff --git a/migrate_cpp/migrate_cpp.py b/migrate_cpp/migrate_cpp.py index 1746b8134517..fb3d6bdbb987 100644 --- a/migrate_cpp/migrate_cpp.py +++ b/migrate_cpp/migrate_cpp.py @@ -12,7 +12,6 @@ import os import subprocess import sys -_CLANG_TIDY = "../external/bootstrap_clang_toolchain/bin/clang-tidy" _CPP_REFACTORING = "./cpp_refactoring/cpp_refactoring" _H_EXTS = {".h", ".hpp"} _CPP_EXTS = {".c", ".cc", ".cpp", ".cxx"} @@ -73,11 +72,10 @@ class _Workflow(object): def _clang_tidy(self): """Runs clang-tidy to fix C++ files in a directory.""" self._print_header("Running clang-tidy...") - clang_tidy = self._data_file(_CLANG_TIDY) with open(self._data_file("clang_tidy.yaml")) as f: config = f.read() subprocess.run( - [clang_tidy, "--fix", "--config", config] + self._cpp_files + ["clang-tidy", "--fix", "--config", config] + self._cpp_files ) def _cpp_refactoring(self): diff --git a/scripts/create_compdb.py b/scripts/create_compdb.py index 627f28fc722c..f4ecd21c7573 100755 --- a/scripts/create_compdb.py +++ b/scripts/create_compdb.py @@ -57,7 +57,7 @@ except FileNotFoundError: # Prepend the `clang` executable path to the arguments that looks into our # downloaded Clang toolchain. -arguments = [str(Path("bazel-clang-toolchain/bin/clang"))] + arguments +arguments = ["clang++"] + arguments print("Building compilation database...")