# 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 # # Build rules supporting the install data tree for the Carbon toolchain. # # This populates a synthetic Carbon toolchain installation rooted at this # package in the output tree. # # We use a `toolchain_files` rule organize the files in in the installation and # handle cases where we need to symlink existing files or build outputs # into the correct location. # # This package also includes the logic for building Carbon's runtimes, and Bazel # `cc_toolchain`s for using the installation as a C++ toolchain in Bazel. This # allows multi-stage bootstrapping to occur entirely within Bazel. Note that the # specific stage will be in a _configuration specific_ output tree, but always # rooted under the install package. # # Last but ont least, we provide rules to build packages of the installation in # conventional layouts for directly extracting and using a binary build. The # packaged installation includes custom Bazel files to handle a pre-built and # installed toolchain in the same way as these handle the just-built toolchain. load( "@llvm-project//:vars.bzl", "LLVM_VERSION_MAJOR", ) load( "@llvm-project//compiler-rt:compiler-rt.bzl", "builtins_copts", "crt_copts", ) load("@llvm-project//libcxx:libcxx_library.bzl", "libcxx_and_abi_copts") load("@llvm-project//libunwind:libunwind_library.bzl", "libunwind_copts") load("@rules_python//python:defs.bzl", "py_test") load("//bazel/cc_rules:defs.bzl", "cc_binary", "cc_library", "cc_test") load( "//bazel/cc_toolchains:carbon_bootstrapping.bzl", "carbon_bootstrapped_cc_toolchain", "filegroup_with_stage", "gen_cc_toolchain_paths_with_stage", ) load("//bazel/manifest:defs.bzl", "manifest") load( "//toolchain/base:runtimes_build_info.bzl", "generate_runtimes_build_vars", ) load("//toolchain/runtimes:carbon_runtimes.bzl", "carbon_runtimes_config") load("bazel/make_include_copts.bzl", "make_include_copts") load( "install_filegroups.bzl", "filtered_toolchain_files", "toolchain_files", "toolchain_llvm_binaries", "toolchain_pkg_filegroup", ) load("pkg_helpers.bzl", "pkg_naming_variables", "pkg_tar_and_test") package(default_visibility = ["//visibility:public"]) config_setting( name = "is_runtimes_build", flag_values = {"//:runtimes_build": "True"}, ) config_setting( name = "not_runtimes_build", flag_values = {"//:runtimes_build": "False"}, ) config_setting( name = "is_bootstrap_stage_0", flag_values = {"//:bootstrap_stage": "0"}, ) config_setting( name = "is_bootstrap_stage_1", flag_values = {"//:bootstrap_stage": "1"}, ) config_setting( name = "is_bootstrap_stage_2", flag_values = {"//:bootstrap_stage": "2"}, ) cc_library( name = "busybox_info", srcs = ["busybox_info.cpp"], hdrs = ["busybox_info.h"], deps = [ "//common:error", "//common:exe_path", "//common:filesystem", "@llvm-project//llvm:Support", ], ) cc_test( name = "busybox_info_test", size = "small", srcs = ["busybox_info_test.cpp"], deps = [ ":busybox_info", "//common:check", "//common:filesystem", "//testing/base:gtest_main", "@googletest//:gtest", "@llvm-project//llvm:Support", ], ) # This target doesn't include prelude libraries. To get a target that has the # prelude available, use //toolchain. cc_binary( name = "carbon-busybox", srcs = ["busybox_main.cpp"], deps = [ ":busybox_info", "//common:all_llvm_targets", "//common:bazel_working_dir", "//common:error", "//common:exe_path", "//common:init_llvm", "//common:version_stamp", "//toolchain/base:install_paths", "//toolchain/base:llvm_tools_def", "//toolchain/driver", "@llvm-project//clang:driver", "@llvm-project//llvm:Support", ], ) toolchain_files( name = "install_marker", srcs = ["carbon_install.txt"], ) toolchain_llvm_binaries( name = "llvm_bins", carbon_binary = ":carbon-busybox", ) toolchain_files( name = "core", srcs = ["//core:prelude"], prefix = "core/", ) toolchain_files( name = "clang_builtin_hdrs", srcs = ["@llvm-project//clang:builtin_headers_gen"], prefix = "llvm/lib/clang/{0}/include/".format(LLVM_VERSION_MAJOR), remove_prefix = "staging/include/", ) toolchain_files( name = "fuzzer_runtime_hdrs", srcs = ["@llvm-project//compiler-rt:fuzzer_installed_hdrs"], prefix = "llvm/lib/clang/{0}/include/".format(LLVM_VERSION_MAJOR), remove_prefix = "include/", ) toolchain_files( name = "profile_runtime_hdrs", srcs = ["@llvm-project//compiler-rt:profile_installed_hdrs"], prefix = "llvm/lib/clang/{0}/include/".format(LLVM_VERSION_MAJOR), remove_prefix = "include/", ) toolchain_files( name = "sanitizer_runtime_hdrs", srcs = ["@llvm-project//compiler-rt:sanitizer_installed_hdrs"], prefix = "llvm/lib/clang/{0}/include/".format(LLVM_VERSION_MAJOR), remove_prefix = "include/", ) filegroup( name = "clang_hdrs", srcs = [ ":clang_builtin_hdrs", ":fuzzer_runtime_hdrs", ":profile_runtime_hdrs", ":sanitizer_runtime_hdrs", ], ) filtered_toolchain_files( name = "builtins_srcs", prefix = "runtimes/builtins/", remove_prefix = "lib/builtins/", srcs_groups = [ "@llvm-project//compiler-rt:builtins_aarch64_srcs", "@llvm-project//compiler-rt:builtins_aarch64_textual_srcs", "@llvm-project//compiler-rt:builtins_crtbegin_src", "@llvm-project//compiler-rt:builtins_crtend_src", "@llvm-project//compiler-rt:builtins_i386_srcs", "@llvm-project//compiler-rt:builtins_i386_textual_srcs", "@llvm-project//compiler-rt:builtins_x86_64_srcs", "@llvm-project//compiler-rt:builtins_x86_64_textual_srcs", ], ) toolchain_files( name = "libcxx_basic_hdrs", srcs = ["@llvm-project//libcxx:libcxx_hdrs"], prefix = "runtimes/libcxx/include/", remove_prefix = "include/", ) toolchain_files( name = "libcxx_gen_hdrs", srcs = ["//toolchain/runtimes:libcxx_gen_files"], prefix = "runtimes/libcxx/include/", remove_prefix = "staging_libcxx/include/", ) filegroup( name = "libcxx_hdrs", srcs = [ ":libcxx_basic_hdrs", ":libcxx_gen_hdrs", ], ) filtered_toolchain_files( name = "libcxx_srcs", prefix = "runtimes/libcxx/src/", remove_prefix = "src/", srcs_groups = [ "@llvm-project//libcxx:libcxx_linux_srcs", "@llvm-project//libcxx:libcxx_macos_srcs", "@llvm-project//libcxx:libcxx_win32_srcs", ], ) toolchain_files( name = "libcxxabi_hdrs", srcs = ["@llvm-project//libcxxabi:libcxxabi_hdrs"], prefix = "runtimes/libcxxabi/include/", remove_prefix = "include/", ) toolchain_files( name = "libcxxabi_srcs", srcs = ["@llvm-project//libcxxabi:libcxxabi_srcs"], prefix = "runtimes/libcxxabi/src/", remove_prefix = "src/", ) toolchain_files( name = "libcxxabi_textual_srcs", srcs = ["@llvm-project//libcxxabi:libcxxabi_textual_srcs"], prefix = "runtimes/libcxxabi/src/", remove_prefix = "src/", ) toolchain_files( name = "libc_internal_libcxx_hdrs", srcs = ["@llvm-project//libc:libcxx_shared_headers_hdrs"], prefix = "runtimes/libc/internal/", ) toolchain_files( name = "libunwind_hdrs", srcs = ["@llvm-project//libunwind:libunwind_hdrs"], prefix = "runtimes/libunwind/include/", remove_prefix = "include/", ) toolchain_files( name = "libunwind_srcs", srcs = ["@llvm-project//libunwind:libunwind_srcs"], prefix = "runtimes/libunwind/src/", remove_prefix = "src/", ) filegroup( name = "cc_toolchain_all_files", srcs = [ ":carbon-busybox", ":clang_hdrs", ":core", ":install_marker", ":libcxx_hdrs", ":libcxxabi_hdrs", ":libunwind_hdrs", ":llvm_bins", ], ) # The toolchain configuration starlark needs to switch from referencing the # `carbon_runtimes.bzl` starlark in the toolchain layout to the `bazel` tree # within the installation. # # TODO: Maybe we should move the `carbon_runtimes.bzl` to the same directory as # the other starlark so we can use relative load lines and avoid this? genrule( name = "carbon_cc_toolchain_config_for_install", srcs = ["//bazel/cc_toolchains:carbon_cc_toolchain_config.bzl"], outs = ["carbon_cc_toolchain_config.bzl"], cmd = "sed 's|//toolchain/runtimes:carbon_runtimes.bzl|//bazel:carbon_runtimes.bzl|' $< > $@", ) toolchain_files( name = "bazel_common_srcs", srcs = [ ":carbon_cc_toolchain_config_for_install", "//bazel/cc_toolchains:installed_cc_toolchain_starlark", ], prefix = "bazel/", ) toolchain_files( name = "bazel_install_srcs", srcs = [ "bazel/carbon_clang_variables.bzl", "bazel/carbon_detected_variables.tpl.bzl", "bazel/carbon_toolchain.bzl", "bazel/make_include_copts.bzl", ], ) toolchain_files( name = "carbon_runtimes_bzl_installed", srcs = ["//toolchain/runtimes:carbon_runtimes.bzl"], prefix = "bazel/", ) toolchain_files( name = "bazel_build_and_module", srcs = [ "bazel/empty.BUILD", "bazel/install.BUILD", "bazel/install.MODULE.bazel", ], remove_prefix = "bazel/", renames = { "empty.BUILD": "bazel/BUILD.bazel", "install.BUILD": "BUILD.bazel", "install.MODULE.bazel": "MODULE.bazel", }, ) # Generate a Starlark file with all the build variables needed for our runtimes. generate_runtimes_build_vars( name = "bazel/runtimes_build_vars.bzl", ) filegroup( name = "installed_bazel_files", srcs = [ ":bazel_build_and_module", ":bazel_common_srcs", ":bazel_install_srcs", ":carbon_runtimes_bzl_installed", # Note that we have to put this here and not in one of the # `toolchain_files` because it is a generated file. "bazel/runtimes_build_vars.bzl", ], ) filegroup( name = "all_data_files", srcs = [ ":builtins_all_srcs", ":clang_hdrs", ":core", ":install_marker", ":installed_bazel_files", ":libc_internal_libcxx_hdrs", ":libcxx_all_srcs", ":libcxx_hdrs", ":libcxxabi_hdrs", ":libcxxabi_srcs", ":libcxxabi_textual_srcs", ":libunwind_hdrs", ":libunwind_srcs", ], ) # A list of clang's installed builtin header files. # This is consumed by //toolchain/testing:file_test. manifest( name = "clang_headers_manifest.txt", srcs = [":clang_hdrs"], strip_package_dir = True, ) filegroup( name = "all_digest_files", srcs = [ ":all_data_files", ":carbon-busybox", ], ) manifest( name = "install_digest_manifest.txt", srcs = [":all_digest_files"], ) cc_binary( name = "make-installation-digest", srcs = ["make_installation_digest.cpp"], deps = [ "//common:bazel_working_dir", "//common:error", "//common:exe_path", "//common:filesystem", "//common:init_llvm", "//common:map", "//common:vlog", "@llvm-project//llvm:Support", ], ) genrule( name = "gen_digest", srcs = [ ":all_digest_files", "install_digest_manifest.txt", ], outs = ["install_digest.txt"], cmd = "{0} {1} $@".format( "$(location :make-installation-digest)", "$(location install_digest_manifest.txt)", ), tools = [":make-installation-digest"], ) filegroup( name = "install_data", srcs = [ "install_digest.txt", ":all_digest_files", ":llvm_bins", ], ) manifest( name = "install_data_manifest.txt", srcs = [":install_data"], ) cc_library( name = "builtins_internal", hdrs_check = "strict", textual_hdrs = select({ "@platforms//cpu:aarch64": [":builtins_aarch64_textual_srcs"], "@platforms//cpu:i386": [":builtins_i386_textual_srcs"], "@platforms//cpu:x86_64": [":builtins_x86_64_textual_srcs"], "//conditions:default": [], }), ) cc_library( name = "builtins", srcs = select({ "@platforms//cpu:aarch64": [":builtins_aarch64_srcs"], "@platforms//cpu:i386": [":builtins_i386_srcs"], "@platforms//cpu:x86_64": [":builtins_x86_64_srcs"], "//conditions:default": [], }), copts = builtins_copts + make_include_copts([ "runtimes/builtins", ]) + [ # TODO: Remove this once we are building sanitizer runtime libraries. "-fno-sanitize=all", ], hdrs_check = "strict", target_compatible_with = select({ ":is_runtimes_build": [], "//conditions:default": ["@platforms//:incompatible"], }), deps = [":builtins_internal"], ) filegroup( name = "builtins_archive", srcs = [":builtins"], output_group = "archive", ) cc_library( name = "libunwind", srcs = [":libunwind_srcs"], hdrs = [":libunwind_hdrs"], copts = libunwind_copts + [ # We disable all warnings as upstream isn't clean with the common # warning flags Carbon uses by default. "-w", # TODO: Remove this once we are building sanitizer runtime libraries. "-fno-sanitize=all", ], hdrs_check = "strict", includes = ["runtimes/libunwind/include"], linkstatic = 1, target_compatible_with = select({ ":is_runtimes_build": [], "//conditions:default": ["@platforms//:incompatible"], }), ) filegroup( name = "libunwind_archive", srcs = [":libunwind"], output_group = "archive", ) cc_library( name = "libcxxabi_internal", hdrs_check = "strict", target_compatible_with = select({ ":is_runtimes_build": [], "//conditions:default": ["@platforms//:incompatible"], }), textual_hdrs = [":libcxxabi_textual_srcs"], ) cc_library( name = "libc_internal_libcxx", hdrs = [":libc_internal_libcxx_hdrs"], hdrs_check = "strict", target_compatible_with = select({ ":is_runtimes_build": [], "//conditions:default": ["@platforms//:incompatible"], }), ) cc_library( name = "libcxx", srcs = select({ "@platforms//os:macos": [":libcxx_macos_srcs"], "@platforms//os:windows": [":libcxx_win32_srcs"], "//conditions:default": [":libcxx_linux_srcs"], }) + [":libcxxabi_srcs"], hdrs = [ ":libcxx_hdrs", ":libcxxabi_hdrs", ], copts = libcxx_and_abi_copts + make_include_copts([ "runtimes/libcxx/src", "runtimes/libc/internal", ]) + [ # We disable all warnings as upstream isn't clean with the common # warning flags Carbon uses by default. "-w", # TODO: Remove this once we are building sanitizer runtime libraries. "-fno-sanitize=all", ], hdrs_check = "strict", includes = [ "runtimes/libcxx/include", "runtimes/libcxxabi/include", ], target_compatible_with = select({ ":is_runtimes_build": [], "//conditions:default": ["@platforms//:incompatible"], }), deps = [ ":libc_internal_libcxx", ":libcxxabi_internal", ], ) filegroup( name = "libcxx_archive", srcs = [":libcxx"], output_group = "archive", ) carbon_runtimes_config( name = "runtimes_cfg", builtins_archive = ":builtins_archive", clang_hdrs_prefix = "llvm/lib/clang/{0}/include/".format(LLVM_VERSION_MAJOR), crt_copts = crt_copts + [ # Disable all sanitizers for CRT objects. "-fno-sanitize=all", ], crtbegin_src = select({ "@platforms//os:linux": ":builtins_crtbegin_src", "//conditions:default": None, }), crtend_src = select({ "@platforms//os:linux": ":builtins_crtend_src", "//conditions:default": None, }), darwin_os_suffix = select({ # TODO: Add support for tvOS, watchOS, and iOS variants with the # relevant Bazel constraints. ":is_macos_arm64": "osx", ":is_macos_x86_64": "osx", "//conditions:default": None, }), libcxx_archive = ":libcxx_archive", libunwind_archive = ":libunwind_archive", target_triple = select({ # TODO: Add other triples (and if needed, constraints) so that we can # build the correct Clang resource-dir structure for each. ":is_freebsd_x86_64": "x86_64-unknown-freebsd", ":is_linux_aarch64": "aarch64-unknown-linux-gnu", ":is_linux_x86_64": "x86_64-unknown-linux-gnu", # Note that Darwin OSes are handled by the `darwin_os_suffix` attribute. "//conditions:default": None, }), ) platforms = { "freebsd": ["x86_64"], "linux": [ "aarch64", "x86_64", ], "macos": [ "arm64", "x86_64", ], } [ config_setting( name = "is_{0}_{1}".format(os, cpu), constraint_values = [ "@platforms//os:{}".format(os), "@platforms//cpu:{}".format(cpu), ], ) for os, cpus in platforms.items() for cpu in cpus ] carbon_bootstrapped_cc_toolchain( name = "carbon_stage1", all_hdrs = [ ":clang_hdrs", ":libunwind_hdrs", ":libcxx_hdrs", ":libcxxabi_hdrs", ], base_files = [ ":install_marker", ":carbon-busybox", ":llvm_bins", ], build_stage = 1, clang_hdrs = [":clang_hdrs"], platforms = platforms, runtimes_cfg = ":runtimes_cfg", ) carbon_bootstrapped_cc_toolchain( name = "carbon_stage2", all_hdrs = [ ":clang_hdrs", ":libunwind_hdrs", ":libcxx_hdrs", ":libcxxabi_hdrs", ], base_files = [ ":install_marker", ":carbon-busybox", ":llvm_bins", ], base_stage = 1, build_stage = 2, clang_hdrs = [":clang_hdrs"], platforms = platforms, runtimes_cfg = ":runtimes_cfg", tags = ["manual"], ) pkg_naming_variables( name = "packaging_variables", ) toolchain_pkg_filegroup( name = "stage1_pkg_data", srcs = [ "install_digest.txt", ":all_data_files", ], carbon_busybox = ":carbon-busybox", ) # We build both a compressed and uncompressed tar file with the same code here. # This lets us use the tar file in testing as it is fast to create, but ship the # compressed version as a release. # # For manual tests, the tar rules are `carbon_toolchain_tar` and # `carbon_toolchain_tar_gz`. pkg_tar_and_test( name = "carbon_toolchain", srcs = [":stage1_pkg_data"], install_data_manifest = ":install_data_manifest.txt", package_dir = "carbon_toolchain-$(version)", package_file_name_base = "carbon_toolchain-$(version)", package_variables = ":packaging_variables", stamp = -1, # Allow `--stamp` builds to produce file timestamps. ) filegroup_with_stage( name = "stage2_pkg_files", srcs = [ ":all_data_files", ":gen_digest", ], stage = 1, tags = ["manual"], ) filegroup_with_stage( name = "stage2_busybox", srcs = [":carbon-busybox"], stage = 1, tags = ["manual"], ) toolchain_pkg_filegroup( name = "stage2_pkg_data", srcs = [":stage2_pkg_files"], carbon_busybox = ":stage2_busybox", tags = ["manual"], ) pkg_tar_and_test( name = "carbon_bootstrapped_toolchain", srcs = [":stage2_pkg_data"], install_data_manifest = ":install_data_manifest.txt", package_dir = "carbon_toolchain-$(version)", package_file_name_base = "carbon_bootstrapped_toolchain-$(version)", package_variables = ":packaging_variables", stamp = -1, # Allow `--stamp` builds to produce file timestamps. tags = ["manual"], ) filegroup( name = "built_runtimes", srcs = [":carbon_stage1_runtimes"], ) py_test( name = "install_test", size = "large", srcs = ["install_test.py"], data = [ ":built_runtimes", ":carbon-busybox", ":install_data", ], deps = ["@bazel_tools//tools/python/runfiles"], ) # Generate paths file for stage 1 toolchain. gen_cc_toolchain_paths_with_stage( name = "gen_cc_tools_paths_stage1", stage = 1, ) # Test that stage 1 toolchain's Make variables expand correctly. py_test( name = "cc_tools_stage1_test", srcs = ["cc_tools_wrapper_test.py"], args = ["$(location :gen_cc_tools_paths_stage1)"], data = [":gen_cc_tools_paths_stage1"], main = "cc_tools_wrapper_test.py", deps = ["//bazel/cc_toolchains:cc_tools_test_lib"], ) # Generate paths file for stage 2 toolchain. gen_cc_toolchain_paths_with_stage( name = "gen_cc_tools_paths_stage2", stage = 2, tags = ["manual"], ) # Test that stage 2 toolchain's Make variables expand correctly. py_test( name = "cc_tools_stage2_test", srcs = ["cc_tools_wrapper_test.py"], args = ["$(location :gen_cc_tools_paths_stage2)"], data = [":gen_cc_tools_paths_stage2"], main = "cc_tools_wrapper_test.py", tags = ["manual"], deps = ["//bazel/cc_toolchains:cc_tools_test_lib"], )