| # Copyright (C) 2019 The Android Open Source Project |
| # |
| # 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. |
| """Handles generation of config.toml for the rustc build.""" |
| |
| import argparse |
| import os |
| from pathlib import Path |
| import subprocess |
| import sys |
| from typing import Any, Tuple, Union |
| |
| import build_platform |
| from paths import * |
| from utils import instantiate_template, instantiate_template_file, instantiate_template_exec |
| |
| # |
| # Constants |
| # |
| |
| HOST_TARGETS_DEFAULT: list[str] = [ |
| "x86_64-unknown-linux-gnu", |
| "i686-unknown-linux-gnu", |
| "x86_64-unknown-linux-musl", |
| "i686-unknown-linux-musl", |
| "x86_64-pc-windows-gnu", |
| ] |
| |
| BARE_TARGETS_DEFAULT: list[str] = [ |
| "aarch64-unknown-none", |
| "armv7a-none-eabi", |
| "riscv32i-unknown-none-elf", |
| "riscv32imc-unknown-none-elf", |
| |
| # Added for b/301288222 |
| "x86_64-unknown-uefi", |
| "i686-unknown-uefi", |
| "aarch64-unknown-uefi", |
| ] |
| |
| DEVICE_TARGET_AND_ARCH: dict[str, str] = { |
| "aarch64-linux-android": "aarch64", |
| "armv7-linux-androideabi": "arm", |
| "x86_64-linux-android": "x86_64", |
| "i686-linux-android": "i386", |
| } |
| |
| # rustc replaces these triples with other targets when invoking clang. To |
| # avoid confusion we won't emit `--target=<triple>` flags into the compiler and |
| # linker wrappers. |
| RUSTC_TRANSLATED_TRIPLES: list[str] = [ |
| "x86_64-unknown-uefi", |
| "i686-unknown-uefi", |
| "aarch64-unknown-uefi", |
| ] |
| |
| DEVICE_TARGETS_DEFAULT: list[str] = list(DEVICE_TARGET_AND_ARCH.keys()) |
| |
| ANDROID_TARGET_VERSION: str = "31" |
| |
| _CMD = ".cmd" if build_platform.is_windows() else "" |
| BARE_CC_WRAPPER_TEMPLATE: Path = TEMPLATES_PATH / f"bare_cc_wrapper{_CMD}.template" |
| BARE_LINKER_WRAPPER_TEMPLATE: Path = TEMPLATES_PATH / f"bare_linker_wrapper{_CMD}.template" |
| BARE_TARGET_TEMPLATE: Path = TEMPLATES_PATH / "bare_target.template" |
| CONFIG_TOML_TEMPLATE: Path = TEMPLATES_PATH / "config.toml.template" |
| DEVICE_CC_WRAPPER_TEMPLATE: Path = TEMPLATES_PATH / f"device_cc_wrapper{_CMD}.template" |
| DEVICE_LINKER_WRAPPER_TEMPLATE: Path = TEMPLATES_PATH / f"device_linker_wrapper{_CMD}.template" |
| DEVICE_TARGET_TEMPLATE: Path = TEMPLATES_PATH / "device_target.template" |
| HOST_CC_WRAPPER_TEMPLATE: Path = TEMPLATES_PATH / f"host_cc_wrapper{_CMD}.template" |
| HOST_CXX_WRAPPER_TEMPLATE: Path = TEMPLATES_PATH / f"host_cxx_wrapper{_CMD}.template" |
| HOST_LINKER_WRAPPER_TEMPLATE: Path = TEMPLATES_PATH / f"host_linker_wrapper{_CMD}.template" |
| HOST_TARGET_TEMPLATE: Path = TEMPLATES_PATH / "host_target.template" |
| |
| # |
| # Helper functions |
| # |
| |
| def vp_counters_flags(num_counters: int) -> str: |
| return f"-mllvm -vp-counters-per-site={num_counters}" |
| |
| |
| def apply_target_flags(target: str, cc_flags: list[str], cxx_flags: list[str], ld_flags: list[str], android_version: str = "", escape: bool = True) -> Tuple[str, str, str]: |
| if target in RUSTC_TRANSLATED_TRIPLES: |
| target_flag = [] |
| else: |
| target_flag = [f"--target={target}{android_version}"] |
| |
| cc_flags_str = " ".join( |
| target_flag + |
| TARGET_COMMON_FLAGS.get(target, []) + |
| TARGET_CC_FLAGS.get(target, []) + |
| cc_flags) |
| |
| cxx_flags_str = " ".join( |
| target_flag + |
| TARGET_COMMON_FLAGS.get(target, []) + |
| TARGET_CC_FLAGS.get(target, []) + |
| TARGET_CXX_FLAGS.get(target, []) + |
| cxx_flags) |
| |
| ld_flags_str = " ".join( |
| target_flag + |
| TARGET_COMMON_FLAGS.get(target, []) + |
| TARGET_LD_FLAGS.get(target, []) + |
| ld_flags) |
| |
| if escape: |
| cc_flags_str = cc_flags_str.replace("$", "\\$") |
| cxx_flags_str = cxx_flags_str.replace("$", "\\$") |
| ld_flags_str = ld_flags_str.replace("$", "\\$") |
| |
| return (cc_flags_str, cxx_flags_str, ld_flags_str) |
| |
| |
| def darwin_sysroot() -> str: |
| if build_platform.is_darwin(): |
| # Apple removed the normal sysroot at / on Mojave+, so we need |
| # to go hunt for it on OSX |
| # On pre-Mojave, this command will output the empty string. |
| output = subprocess.check_output( |
| ["xcrun", "--sdk", "macosx", "--show-sdk-path"]) |
| return output.rstrip().decode("utf-8") |
| return "" |
| |
| |
| def print_flags(target: str, cc_flags: str, cxx_flags: str, ld_flags: str) -> None: |
| print(f"Compiler/linker flags for {target}") |
| print(f"CC Flags: {cc_flags}") |
| if cxx_flags: |
| print(f"CXX Flags: {cxx_flags}") |
| print(f"LD Flags: {ld_flags}\n") |
| |
| |
| def get_wrapper_paths(target: str) -> Tuple[Path, Path, Path]: |
| return ( |
| OUT_PATH_WRAPPERS / f"clang-{target}{_CMD}", |
| OUT_PATH_WRAPPERS / f"clang++-{target}{_CMD}", |
| OUT_PATH_WRAPPERS / f"linker-{target}{_CMD}", |
| ) |
| |
| # |
| # Target configuration |
| # |
| |
| def host_config(target: str, cc_flags: list[str], cxx_flags: list[str], ld_flags: list[str], env: dict[str, str]) -> str: |
| cc_wrapper_name, cxx_wrapper_name, ld_wrapper_name = get_wrapper_paths(target) |
| cc_flags_str, cxx_flags_str, ld_flags_str = apply_target_flags(target, cc_flags, cxx_flags, ld_flags) |
| print_flags(target, cc_flags_str, cxx_flags_str, ld_flags_str) |
| |
| envified_target = target.replace("-", "_") |
| env[f"CC_{envified_target}"] = cc_wrapper_name.as_posix() |
| env[f"CXX_{envified_target}"] = cxx_wrapper_name.as_posix() |
| env[f"LD_{envified_target}"] = ld_wrapper_name.as_posix() |
| env[f"RANLIB_{envified_target}"] = RANLIB_PATH.as_posix() |
| |
| instantiate_template_exec( |
| HOST_CC_WRAPPER_TEMPLATE, |
| cc_wrapper_name, |
| real_cc=CC_PATH, |
| cc_flags=cc_flags_str) |
| |
| instantiate_template_exec( |
| HOST_CXX_WRAPPER_TEMPLATE, |
| cxx_wrapper_name, |
| real_cxx=CXX_PATH, |
| cxx_flags=cxx_flags_str) |
| |
| instantiate_template_exec( |
| HOST_LINKER_WRAPPER_TEMPLATE, |
| ld_wrapper_name, |
| real_cc=CC_PATH, |
| ld_flags=ld_flags_str) |
| |
| return instantiate_template( |
| HOST_TARGET_TEMPLATE, |
| target=target, |
| cc=cc_wrapper_name.as_posix(), |
| cxx=cxx_wrapper_name.as_posix(), |
| llvm_config=LLVM_CONFIG_PATH.as_posix(), |
| linker=ld_wrapper_name.as_posix(), |
| ar=AR_PATH.as_posix(), |
| ranlib=RANLIB_PATH.as_posix(), |
| musl_root=f"musl-root = \"{HOST_SYSROOTS[target]}\"" if "musl" in target else "") |
| |
| |
| def bare_config(target: str, cc_flags: list[str], ld_flags: list[str], env: dict[str, str]) -> str: |
| cc_wrapper_name, _, ld_wrapper_name = get_wrapper_paths(target) |
| cc_flags_str, _, ld_flags_str = apply_target_flags(target, cc_flags, [], ld_flags) |
| print_flags(target, cc_flags_str, "", ld_flags_str) |
| |
| envified_target = target.replace("-", "_") |
| env[f"CC_{envified_target}"] = cc_wrapper_name.as_posix() |
| env[f"LD_{envified_target}"] = ld_wrapper_name.as_posix() |
| |
| instantiate_template_exec( |
| BARE_CC_WRAPPER_TEMPLATE, |
| cc_wrapper_name, |
| real_cc=CC_PATH, |
| cc_flags=cc_flags_str) |
| |
| instantiate_template_exec( |
| BARE_LINKER_WRAPPER_TEMPLATE, |
| ld_wrapper_name, |
| real_cc=CC_PATH, |
| ld_flags=ld_flags_str) |
| |
| return instantiate_template( |
| BARE_TARGET_TEMPLATE, |
| target=target, |
| cc=cc_wrapper_name.as_posix(), |
| cxx=cc_wrapper_name.as_posix(), |
| linker=ld_wrapper_name.as_posix(), |
| ar=AR_PATH.as_posix()) |
| |
| |
| def device_config(target: str, cc_flags: list[str], ld_flags: list[str], env: dict[str, str]) -> str: |
| cc_wrapper_name, _, ld_wrapper_name = get_wrapper_paths(target) |
| cc_flags_str, _, ld_flags_str = apply_target_flags( |
| target, cc_flags, [], ld_flags, android_version=ANDROID_TARGET_VERSION) |
| print_flags(target, cc_flags_str, "", ld_flags_str) |
| |
| envified_target = target.replace("-", "_") |
| env[f"CC_{envified_target}"] = cc_wrapper_name.as_posix() |
| env[f"LD_{envified_target}"] = ld_wrapper_name.as_posix() |
| |
| instantiate_template_exec( |
| DEVICE_CC_WRAPPER_TEMPLATE, |
| cc_wrapper_name, |
| real_cc=CC_PATH, |
| cc_flags=cc_flags_str) |
| |
| instantiate_template_exec( |
| DEVICE_LINKER_WRAPPER_TEMPLATE, |
| ld_wrapper_name, |
| real_cc=CC_PATH, |
| ld_flags=ld_flags_str) |
| |
| return instantiate_template( |
| DEVICE_TARGET_TEMPLATE, |
| target=target, |
| cc=cc_wrapper_name.as_posix(), |
| cxx=cc_wrapper_name.as_posix(), |
| linker=ld_wrapper_name.as_posix(), |
| ar=AR_PATH.as_posix()) |
| |
| # |
| # Main configuration |
| # |
| |
| CC_FLAG_PIC: str = "-fpic" |
| LD_FLAG_PIC: str = "-Wl,-mllvm,--relocation-model=pic" |
| LD_FLAG_USE_LLD: str = "-fuse-ld=lld" |
| LD_OLD_DTAGS: str = "-Wl,--disable-new-dtags" |
| LD_FLAG_RPATH: str = f"-Wl,-rpath,{build_platform.rpath_origin()}/../lib64" |
| |
| MACOSX_VERSION_FLAG: str = "-mmacosx-version-min=10.14" |
| |
| HOST_SYSROOTS: dict[str, str] = { |
| "x86_64-unknown-linux-gnu": GCC_SYSROOT_PATH.as_posix(), |
| "i686-unknown-linux-gnu": GCC_SYSROOT_PATH.as_posix(), |
| "x86_64-apple-darwin": darwin_sysroot(), |
| "x86_64-unknown-linux-musl": MUSL_SYSROOT64_PATH.as_posix(), |
| "i686-unknown-linux-musl": MUSL_SYSROOT32_PATH.as_posix(), |
| "x86_64-pc-windows-gnu": MINGW_SYSROOT_PATH.as_posix(), |
| } |
| |
| |
| TARGET_COMMON_FLAGS: dict[str, list[str]] = {} |
| for arch, sysroot in HOST_SYSROOTS.items(): |
| sysroot_flag = f"--sysroot={sysroot}" |
| if arch in TARGET_COMMON_FLAGS: |
| TARGET_COMMON_FLAGS[arch].append(sysroot_flag) |
| else: |
| TARGET_COMMON_FLAGS[arch] = [sysroot_flag] |
| |
| TARGET_CC_FLAGS: dict[str, list[str]] = { |
| "x86_64-apple-darwin": ["-D_LIBCPP_AVAILABILITY_HAS_NO_VERBOSE_ABORT=1"], |
| "x86_64-unknown-linux-musl": ["-D_LIBCPP_HAS_MUSL_LIBC"], |
| "i686-unknown-linux-musl": ["-D_LIBCPP_HAS_MUSL_LIBC"], |
| } |
| TARGET_CXX_FLAGS: dict[str, list[str]] = {} |
| |
| HOST_LINUX_LD_FLAGS: list[str] = [ |
| LD_FLAG_USE_LLD, |
| "--rtlib=compiler-rt", |
| # Rely on rust.llvm-libunwind="in-tree" in config.toml to link host |
| # binaries against the in-tree built LLVM libunwind. The version of |
| # libunwind in our prebuilts is for devices only. |
| #"-lunwind", |
| f"-B{GCC_LIBGCC_PATH.as_posix()}", |
| f"-L{GCC_LIBGCC_PATH.as_posix()}", |
| f"-L{GCC_LIB_PATH.as_posix()}", |
| f"-L{LLVM_CXX_RUNTIME_PATH_HOST.as_posix()}", |
| LD_OLD_DTAGS, |
| LD_FLAG_RPATH, |
| ] |
| HOST_WINDOWS_LDFLAGS: list[str] = [ |
| LD_FLAG_USE_LLD, |
| # "--rtlib=compiler-rt", |
| f"-B{MINGW_LIBGCC_PATH.as_posix()}", |
| f"-L{MINGW_LIBGCC_PATH.as_posix()}", |
| f"-L{MINGW_LIB_PATH.as_posix()}", |
| f"-L{LLVM_CXX_RUNTIME_PATH_WINDOWS.as_posix()}", |
| ] |
| TARGET_LD_FLAGS: dict[str, list[str]] = { |
| # When performing LTO, the LLVM IR generator doesn't know about these |
| # target specific symbols. By telling the linker about them ahead of time |
| # we avoid an error when they are encountered when the native code is |
| # emitted. See b/201551165 for more information. |
| "armv7-linux-androideabi": [ |
| "-u __aeabi_uidiv", |
| "-u __aeabi_idiv0", |
| LD_OLD_DTAGS, |
| LD_FLAG_RPATH, |
| ], |
| |
| "x86_64-unknown-linux-gnu": HOST_LINUX_LD_FLAGS, |
| "i686-unknown-linux-gnu": HOST_LINUX_LD_FLAGS, |
| |
| "x86_64-apple-darwin": [ |
| f"-L{LLVM_CXX_RUNTIME_PATH_HOST}", |
| LD_FLAG_RPATH, |
| ], |
| |
| "x86_64-unknown-linux-musl": [ |
| LD_FLAG_USE_LLD, |
| "--rtlib=compiler-rt", |
| f"-L{LLVM_CXX_RUNTIME_PATH_LINUX_MUSL}", |
| f"-L{MUSL_SYSROOT64_PATH.as_posix()}/lib", |
| LD_OLD_DTAGS, |
| LD_FLAG_RPATH, |
| ], |
| "i686-unknown-linux-musl": [ |
| LD_FLAG_USE_LLD, |
| "--rtlib=compiler-rt", |
| f"-L{LLVM_CXX_RUNTIME_PATH_LINUX_MUSL}", |
| f"-L{MUSL_SYSROOT32_PATH.as_posix()}/lib", |
| LD_OLD_DTAGS, |
| LD_FLAG_RPATH, |
| ], |
| |
| "x86_64-pc-windows-gnu": HOST_WINDOWS_LDFLAGS, |
| } |
| |
| MUSL_RUSTFLAGS: list[str] = [ |
| # Rust defaults to using its own crt objects when targeting musl, but we |
| # want to use the ones from the sysroot with the embedded dynamic |
| # linker. It defaults to no when targeting glibc, darwin or android. |
| "-Clink-self-contained=no", |
| ] |
| |
| BTI_RUSTFLAGS_X86: list[str] = [ |
| "-Zcf-protection=branch", |
| ] |
| |
| BTI_RUSTFLAGS_AARCH64: list[str] = [ |
| "-Zbranch-protection=bti", |
| ] |
| |
| TARGET_RUSTFLAGS: dict[str, list[str]] = { |
| "x86_64-unknown-linux-musl": MUSL_RUSTFLAGS, |
| "i686-unknown-linux-musl": MUSL_RUSTFLAGS, |
| "aarch64-unknown-none": BTI_RUSTFLAGS_AARCH64, |
| "aarch64-unknown-linux-gnu": BTI_RUSTFLAGS_AARCH64, |
| "aarch64-linux-android": BTI_RUSTFLAGS_AARCH64, |
| "x86_64-unknown-linux-gnu": BTI_RUSTFLAGS_X86, |
| "riscv64-linux-android": ["-C target-feature=+V,+Zba,+Zbb,+Zbs"], |
| } |
| |
| def configure(args: argparse.Namespace, env: dict[str, str]) -> None: |
| """Generates config.toml and compiler wrappers for the rustc build.""" |
| |
| # |
| # Update environment variables |
| # |
| |
| path: list[Union[Path, str]] = [ |
| PYTHON_PATH.parent, |
| RUST_HOST_STAGE0_PATH / "bin", |
| CMAKE_PREBUILT_PATH / "bin", |
| NINJA_PREBUILT_PATH, |
| BUILD_TOOLS_PREBUILT_MULTICALL, |
| BUILD_TOOLS_PREBUILT_BIN_PATH, |
| OUT_PATH_BIN_LINKS, |
| ] |
| |
| # Continue to use the system search paths on Darwin. |
| if build_platform.is_darwin(): |
| path.append(env["PATH"]) |
| |
| if build_platform.is_windows(): |
| path.extend([ |
| GIT_USR_BIN_PATH, # So we can find sh.exe |
| MINGW_LIB_PATH.parent / "bin", |
| MINGW_LIB_PATH.parent / "lib", |
| ]) |
| |
| env["PATH"] = os.pathsep.join([str(p) for p in path]) |
| |
| # System libraries are still required to build the Mac and Windows |
| # toolchains. |
| if build_platform.is_linux(): |
| if "LIBRARY_PATH" in env: |
| del env["LIBRARY_PATH"] |
| |
| # Use LD_LIBRARY_PATH to tell the build system where to find libc++.so.1 |
| # without polluting the rpath of the produced artifacts. |
| if not build_platform.is_windows(): |
| env["LD_LIBRARY_PATH"] = LLVM_CXX_RUNTIME_PATH_HOST.as_posix() |
| |
| # Tell the rust bootstrap system where to place its final products |
| env["DESTDIR"] = OUT_PATH_PACKAGE.as_posix() |
| |
| # Tell pkg-config where to find metadata |
| env["PKG_CONFIG_PATH"] = GCC_PKG_CONFIG_PATH.as_posix() |
| |
| # By default, the lzma-sys crate links against the system's liblzma.so. |
| # This causes Cargo to propagate a dependency to the system library |
| # directory to all of the libraries that depend on lzma-sys. |
| # |
| # Setting this property causes the crate to build a static liblzma.a and |
| # link against that. |
| env["LZMA_API_STATIC"] = "1" |
| |
| # Ensure libz is compiled from in-tree source. |
| env["LIBZ_SYS_STATIC"] = "1" |
| |
| # Explicitly set the host AR path; this is required to build the |
| # openssl-src crate. |
| env["AR"] = AR_PATH.as_posix() |
| |
| # |
| # Select the targets |
| # |
| |
| host_targets: list[str] = [args.host] |
| if build_platform.is_linux(): |
| if not args.host_multilibs: |
| # Make sure that a compiler for the host triple can be found |
| if args.host != build_platform.triple(): |
| host_targets.append(build_platform.triple()) |
| else: |
| for t in HOST_TARGETS_DEFAULT: |
| if t != args.host: |
| host_targets.append(t) |
| |
| bare_targets: list[str] = [] |
| if args.bare_targets: |
| bare_targets = BARE_TARGETS_DEFAULT |
| |
| device_targets: list[str] = [] |
| if args.device_targets: |
| device_targets = DEVICE_TARGETS_DEFAULT |
| |
| all_targets: list[str] = host_targets + bare_targets + device_targets |
| |
| # |
| # Flag set definitions |
| # |
| |
| common_cc_flags = [] |
| # `-fuse-ld=lld` will cause Clang to use the prebuilt version of LLD. This |
| # is not desired on Darwin hosts as only the system linker can successfully |
| # link binaries for the platform. As such this flag is not included here |
| # and is instead listed in `bare_ld_flags`, `device_ld_flags` and specific |
| # host target flags. |
| common_ld_flags = [] |
| |
| host_common_flags = [] |
| host_cc_flags = [CC_FLAG_PIC] |
| # All flags from host_cc_flags will be added to host_cxx_flags |
| host_cxx_flags = [ |
| "--stdlib=libc++", |
| f"-I{CXXSTD_PATH.as_posix()}", |
| ] |
| host_ld_flags = [ |
| LD_FLAG_PIC, |
| ] |
| |
| bare_cc_flags: list[str] = [] |
| bare_ld_flags: list[str] = [LD_FLAG_USE_LLD] |
| |
| device_common_flags = [f"--sysroot={(args.ndk_path / NDK_LLVM_PATH_SUFFIX / NDK_SYSROOT_PATH_SUFFIX).as_posix()}"] |
| device_cc_flags = [CC_FLAG_PIC] |
| # No need to pass `--rtlib=compiler-rt -lunwind` arguments here because NDK |
| # r23+ only has compiler-rt |
| device_ld_flags = [ |
| LD_FLAG_USE_LLD, |
| LD_FLAG_PIC, |
| ] |
| |
| llvm_common_flags = [] |
| llvm_cc_flags: list[str] = [] |
| llvm_ld_flags = [] |
| |
| env_cflags: list[str] = [] |
| env_rustflags: list[str] = [ |
| "-Crelocation-model=pic", |
| f"-Cdlltool={DLLTOOL_PATH}", |
| ] + ([] if args.verbose else ["-Awarnings"]) |
| env_rustflags_bootstrap: list[str] = [] |
| env_rustflags_not_bootstrap: list[str] = [] |
| env_rustdocflags: list[str] = [ |
| # For some reason, rustdoc needs a linker. |
| f"-Clinker={get_wrapper_paths(args.host)[2]}" |
| ] |
| |
| # |
| # Build platform based configuration |
| # |
| |
| if build_platform.is_darwin(): |
| host_common_flags.append(MACOSX_VERSION_FLAG) |
| |
| # The Linux build of clang has some architecture-specific libraries, and it knows how |
| # to find them. The Windows build doesn't have these, and so it doesn't know how to find |
| # libunwind.a. So, when building on Windows, we need to point to the right directory in |
| # in the Linux build of clang. |
| if build_platform.is_windows(): |
| for target, arch in DEVICE_TARGET_AND_ARCH.items(): |
| unwind_path = DEVICE_LIB_PATH / arch |
| if not unwind_path.is_dir(): |
| raise RuntimeError(f"{unwind_path} is not a directory") |
| |
| flag = f"-L{unwind_path.as_posix()}" |
| if target in TARGET_LD_FLAGS: |
| TARGET_LD_FLAGS[target].append(flag) |
| else: |
| TARGET_LD_FLAGS[target] = [flag] |
| |
| # |
| # Command-line based configuration |
| # |
| |
| # LTO |
| |
| llvm_lto_config = "false" |
| rust_lto_config = "thin-local" |
| if args.lto == "thin": |
| llvm_lto_config = "true" |
| rust_lto_config = "thin" |
| |
| # PGO |
| |
| llvm_pgo_config: str = "" |
| rustc_pgo_config: str = "" |
| if args.profile_generate != None: |
| profile_name_llvm = PROFILE_SUBDIR_LLVM if args.llvm_linkage == "shared" else PROFILE_SUBDIR_RUST |
| |
| llvm_cc_flags.append(vp_counters_flags(16)) |
| llvm_cc_flags.append("-Wno-unused-command-line-argument") |
| |
| env_rustflags.append("-Cllvm-args=-vp-counters-per-site=16") |
| |
| llvm_pgo_config = f"profile-generate = \"{args.profile_generate / profile_name_llvm}\"" |
| rustc_pgo_config = f"profile-generate = \"{args.profile_generate / PROFILE_SUBDIR_RUST}\"" |
| |
| elif args.profile_use != None: |
| |
| # LLVM |
| profile_path_llvm: Path = args.profile_use / PROFILE_NAME_LLVM_CS |
| if not profile_path_llvm.exists(): |
| profile_path_llvm = args.profile_use / PROFILE_NAME_LLVM |
| |
| if profile_path_llvm.exists(): |
| llvm_pgo_config = f"profile-use = \"{profile_path_llvm}\"" |
| |
| # Rust |
| profile_path_rust: Path = args.profile_use / PROFILE_NAME_RUST |
| if profile_path_rust.exists(): |
| rustc_pgo_config = f"profile-use = \"{profile_path_rust}\"" |
| |
| if not (profile_path_llvm.exists() or profile_path_rust.exists()): |
| sys.exit(f"No profiles found in specified directory: {args.profile_use}") |
| |
| |
| if args.cs_profile_generate != None: |
| # TODO: The vp-counters-per-site value needs to be tuned to eliminate |
| # warnings about the inability to allocate counters during |
| # context-sensitive profiling. |
| |
| if args.llvm_linkage == "shared": |
| profile_path = args.cs_profile_generate / PROFILE_SUBDIR_LLVM_CS |
| llvm_common_flags += [ |
| f"-fcs-profile-generate={profile_path}", |
| vp_counters_flags(32), |
| ] |
| |
| else: # args.llvm_linkage == "static" |
| if args.lto == None: |
| raise RuntimeError("Context-sensitive PGO with static LLVM linkage requires LTO to be enabled") |
| |
| profile_path = args.cs_profile_generate / PROFILE_SUBDIR_RUST |
| |
| llvm_common_flags += [ |
| f"-fcs-profile-generate={profile_path}", |
| vp_counters_flags(32), |
| ] |
| llvm_ld_flags += [ |
| " -Wl,--lto-cs-profile-generate", |
| f"-Wl,--lto-cs-profile-file={profile_path}", |
| ] |
| |
| env_rustflags += [ |
| f"-C link-arg=-fcs-profile-generate={profile_path}", |
| " -C link-arg=-Wl,--lto-cs-profile-generate", |
| f"-C link-arg=-Wl,--lto-cs-profile-file={profile_path}" |
| ] |
| |
| |
| # Misc. |
| |
| if args.emit_relocs: |
| for target in HOST_TARGETS_DEFAULT: |
| # "-Wl,--emit-relocs" is not supported on Windows targets |
| if "linux" in target: |
| TARGET_LD_FLAGS[target].append("-Wl,--emit-relocs") |
| |
| if args.gc_sections and build_platform.is_linux(): |
| common_cc_flags += ["-ffunction-sections", "-fdata-sections"] |
| common_ld_flags.append("-Wl,--gc-sections") |
| |
| if args.cgu1: |
| env_rustflags.append("-Ccodegen-units=1") |
| |
| llvm_link_shared = "true" if args.llvm_linkage == "shared" else "false" |
| |
| # Coalesce flags |
| |
| host_cc_flags = common_cc_flags + host_common_flags + host_cc_flags |
| host_cxx_flags = host_cc_flags + host_cxx_flags |
| host_ld_flags = common_ld_flags + host_common_flags + host_ld_flags |
| |
| bare_cc_flags = common_cc_flags + bare_cc_flags |
| bare_ld_flags = common_ld_flags + bare_ld_flags |
| |
| device_cc_flags = common_cc_flags + device_common_flags + device_cc_flags |
| device_ld_flags = common_ld_flags + device_common_flags + device_ld_flags |
| |
| llvm_cc_flags_str = " ".join(llvm_common_flags + llvm_cc_flags) |
| llvm_ld_flags_str = " ".join( |
| host_ld_flags + |
| llvm_common_flags + |
| llvm_ld_flags) |
| |
| env["CFLAGS"] = " ".join(env_cflags) |
| env["RUSTFLAGS_BOOTSTRAP"] = " ".join(env_rustflags + env_rustflags_bootstrap) |
| env["RUSTFLAGS_NOT_BOOTSTRAP"] = " ".join(env_rustflags + env_rustflags_not_bootstrap) |
| env["RUSTDOCFLAGS"] = " ".join(env_rustdocflags) |
| |
| # Display final flag strings (and set some straggling env vars) |
| |
| print() |
| print("Compiler/Linker Flags") |
| print() |
| print(f"env PATH: {env['PATH']}") |
| print(f"env LIBRARY_PATH: {env.get('LIBRARY_PATH', '')}") |
| print() |
| print(f"env CFLAGS : {env['CFLAGS']}") |
| print(f"env RUSTFLAGS_BOOTSTRAP : {env['RUSTFLAGS_BOOTSTRAP']}") |
| print(f"env RUSTFLAGS_NOT_BOOTSTRAP: {env['RUSTFLAGS_NOT_BOOTSTRAP']}") |
| print() |
| print(f"LLVM CC Flags: {llvm_cc_flags_str}") |
| print(f"LLVM LD Flags: {llvm_ld_flags_str}") |
| print() |
| |
| # The LLVM build needs different linker flags for x86_64-unknown-linux-gnu and |
| # x86_64-unknown-linux-musl when cross-compiling host musl tools. The LLVM |
| # build never uses the linker wrapper, it runs the compiler wrappers to link |
| # instead, so the target-specific linker flags can't go in the wrappers. It |
| # only has a single field in config.toml for all architectures. The only way |
| # to pass target-specific linker flags to LLVM is to use LDFLAGS_<triple> |
| # environment variables. |
| for target in host_targets: |
| env_var_name = "LDFLAGS_" + target.replace("-", "_") |
| env[env_var_name] = " ".join( |
| TARGET_COMMON_FLAGS[target] + |
| TARGET_LD_FLAGS[target]) |
| print(f"env {env_var_name} = {env[env_var_name]}") |
| print() |
| |
| for target, flags in TARGET_RUSTFLAGS.items(): |
| if target in all_targets: |
| key = f"CARGO_TARGET_{target.replace('-', '_').upper()}_RUSTFLAGS" |
| env[key] = " ".join(flags) |
| print(f"env {key}: {env[key]}") |
| print() |
| |
| |
| # |
| # Instantiate wrappers |
| # |
| |
| host_configs = "\n".join( |
| [host_config(target, host_cc_flags, host_cxx_flags, host_ld_flags, env) for target in host_targets]) |
| bare_configs = "\n".join( |
| [bare_config(target, bare_cc_flags, bare_ld_flags, env) for target in bare_targets]) |
| device_configs = "\n".join( |
| [device_config(target, device_cc_flags, device_ld_flags, env) for target in device_targets]) |
| |
| quoted_target_list = ",".join([f'\"{target}\"' for target in all_targets]) |
| |
| |
| # |
| # Print Environment |
| # |
| |
| print() |
| print("Environment Variables") |
| for key, val in sorted(env.items()): |
| print(f"\t{key} => {val}") |
| print() |
| |
| |
| instantiate_template_file( |
| CONFIG_TOML_TEMPLATE, |
| OUT_PATH_RUST_SOURCE / "config.toml", |
| llvm_link_shared=llvm_link_shared, |
| llvm_cflags=llvm_cc_flags_str, |
| llvm_cxxflags=llvm_cc_flags_str, |
| llvm_ldflags=llvm_ld_flags_str, |
| llvm_lto_config=llvm_lto_config, |
| llvm_pgo_config=llvm_pgo_config, |
| stage0_host_triple=RUST_STAGE0_TRIPLE, |
| new_host_triple=args.host, |
| all_targets=quoted_target_list, |
| cargo=CARGO_PATH.as_posix(), |
| rustc=RUSTC_PATH.as_posix(), |
| python=PYTHON_PATH.as_posix(), |
| verbose=1 if args.verbose else 0, |
| description=f"\"Android Rust Toolchain version {args.build_name}\"", |
| rust_lto_config=rust_lto_config, |
| rust_pgo_config=rustc_pgo_config, |
| host_configs=host_configs, |
| bare_configs=bare_configs, |
| device_configs=device_configs) |