aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wailes <chriswailes@google.com>2024-04-12 17:30:51 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-04-12 17:30:51 +0000
commit9801b686e453221b5c8caaeb95061378bd908fc2 (patch)
treebf04c25027e81d8c7f7296bdbc573d427f87e611
parentab8ff3dcd463466c7bb15e5600f0deab3330ed8f (diff)
parent7fc8801087677e921bb8f4c1ab19349b83ab7a57 (diff)
downloadandroid_rust-9801b686e453221b5c8caaeb95061378bd908fc2.tar.gz
Merge changes If90e39c5,Ibecbb6fc,Iab509f23,I1a53525d,Ia18f82f3 into main
* changes: Return the ability to invoke BOLT when building the toolchain Take the Stage 0 Rust toolchain as a command line option Add a RustToolchain class to manage paths Add a ClangToolchain class to manage paths Clean up error/exception handling
-rw-r--r--src/android_rust/cargo.py7
-rw-r--r--src/android_rust/config.py82
-rw-r--r--src/android_rust/paths.py25
-rw-r--r--src/android_rust/source_manager.py33
-rw-r--r--src/android_rust/toolchains.py159
-rw-r--r--src/android_rust/utils.py50
-rwxr-xr-xtools/audit.py5
-rwxr-xr-xtools/boltifyer.py37
-rwxr-xr-xtools/build.py119
-rwxr-xr-xtools/fetch_source.py11
-rwxr-xr-xtools/pipeline.py4
-rwxr-xr-xtools/update_prebuilts.py13
12 files changed, 407 insertions, 138 deletions
diff --git a/src/android_rust/cargo.py b/src/android_rust/cargo.py
index 6bea1aa..3df245a 100644
--- a/src/android_rust/cargo.py
+++ b/src/android_rust/cargo.py
@@ -16,7 +16,8 @@ import os
from pathlib import Path
import shutil
-from android_rust.paths import CARGO_DENY_CONFIG_PATH, CARGO_PATH, OUT_PATH
+from android_rust.paths import CARGO_DENY_CONFIG_PATH, OUT_PATH
+from android_rust.toolchains import RUST_TOOLCHAIN_HOST
from android_rust.utils import run_and_exit_on_failure
@@ -34,7 +35,7 @@ class Crate:
self,
crate_path: Path,
env: dict[str, str],
- cargo_path: Path | None = None,
+ cargo_path: Path = RUST_TOOLCHAIN_HOST.cargo(),
target: str | None = None,
linker: Path | None = None,
) -> None:
@@ -42,7 +43,7 @@ class Crate:
self.env = env.copy()
# TODO: Use tomllib to get the crate name. But this requires python 3.11
self.build_dir = OUT_PATH / crate_path.name
- self.cargo_path = cargo_path if cargo_path else CARGO_PATH
+ self.cargo_path = cargo_path
# Make sure that cargo is in our path, so plugins, rustc, etc. are run from there.
self.env["PATH"] = os.pathsep.join(
[str(self.cargo_path.resolve().parent), self.env["PATH"]])
diff --git a/src/android_rust/config.py b/src/android_rust/config.py
index 2b381ec..f6f1268 100644
--- a/src/android_rust/config.py
+++ b/src/android_rust/config.py
@@ -18,12 +18,12 @@ import argparse
import os
from pathlib import Path
import subprocess
-import sys
from typing import Any, Tuple, Union
import android_rust.build_platform as build_platform
from android_rust.paths import *
-from android_rust.utils import instantiate_template, instantiate_template_file, instantiate_template_exec
+from android_rust.toolchains import LLVM_TOOLCHAIN_HOST, LLVM_TOOLCHAIN_LINUX, LLVM_TOOLCHAIN_WINDOWS
+from android_rust.utils import ScriptException, instantiate_template, instantiate_template_file, instantiate_template_exec
#
# Constants
@@ -179,16 +179,25 @@ def host_config(
env[f"CC_{envified_target}"] = str(cc_wrapper_name)
env[f"CXX_{envified_target}"] = str(cxx_wrapper_name)
env[f"LD_{envified_target}"] = str(ld_wrapper_name)
- env[f"RANLIB_{envified_target}"] = str(RANLIB_PATH)
+ env[f"RANLIB_{envified_target}"] = str(LLVM_TOOLCHAIN_HOST.ranlib())
instantiate_template_exec(
- HOST_CC_WRAPPER_TEMPLATE, cc_wrapper_name, real_cc=CC_PATH, cc_flags=cc_flags_str)
+ HOST_CC_WRAPPER_TEMPLATE,
+ cc_wrapper_name,
+ real_cc=LLVM_TOOLCHAIN_HOST.clang(),
+ cc_flags=cc_flags_str)
instantiate_template_exec(
- HOST_CXX_WRAPPER_TEMPLATE, cxx_wrapper_name, real_cxx=CXX_PATH, cxx_flags=cxx_flags_str)
+ HOST_CXX_WRAPPER_TEMPLATE,
+ cxx_wrapper_name,
+ real_cxx=LLVM_TOOLCHAIN_HOST.clangxx(),
+ cxx_flags=cxx_flags_str)
instantiate_template_exec(
- HOST_LINKER_WRAPPER_TEMPLATE, ld_wrapper_name, real_cc=CC_PATH, ld_flags=ld_flags_str)
+ HOST_LINKER_WRAPPER_TEMPLATE,
+ ld_wrapper_name,
+ real_cc=LLVM_TOOLCHAIN_HOST.clang(),
+ ld_flags=ld_flags_str)
# as_posix() is necessary here to prevent the backslashes from being
# interpreted as the start of an esacape sequence on Windows hosts.
@@ -198,8 +207,8 @@ def host_config(
cc=cc_wrapper_name.as_posix(),
cxx=cxx_wrapper_name.as_posix(),
linker=ld_wrapper_name.as_posix(),
- ar=AR_PATH.as_posix(),
- ranlib=RANLIB_PATH.as_posix(),
+ ar=LLVM_TOOLCHAIN_HOST.ar().as_posix(),
+ ranlib=LLVM_TOOLCHAIN_HOST.ranlib().as_posix(),
profiler="true" if "linux" in target else "false",
musl_root=f"musl-root = \"{HOST_SYSROOTS[target]}\"" if "musl" in target else "")
@@ -214,10 +223,16 @@ def bare_config(target: str, cc_flags: list[str], ld_flags: list[str], env: dict
env[f"LD_{envified_target}"] = str(ld_wrapper_name)
instantiate_template_exec(
- BARE_CC_WRAPPER_TEMPLATE, cc_wrapper_name, real_cc=CC_PATH, cc_flags=cc_flags_str)
+ BARE_CC_WRAPPER_TEMPLATE,
+ cc_wrapper_name,
+ real_cc=LLVM_TOOLCHAIN_HOST.clang(),
+ cc_flags=cc_flags_str)
instantiate_template_exec(
- BARE_LINKER_WRAPPER_TEMPLATE, ld_wrapper_name, real_cc=CC_PATH, ld_flags=ld_flags_str)
+ BARE_LINKER_WRAPPER_TEMPLATE,
+ ld_wrapper_name,
+ real_cc=LLVM_TOOLCHAIN_HOST.clang(),
+ ld_flags=ld_flags_str)
# as_posix() is necessary here to prevent the backslashes from being
# interpreted as the start of an esacape sequence on Windows hosts.
@@ -227,7 +242,7 @@ def bare_config(target: str, cc_flags: list[str], ld_flags: list[str], env: dict
cc=cc_wrapper_name.as_posix(),
cxx=cc_wrapper_name.as_posix(),
linker=ld_wrapper_name.as_posix(),
- ar=AR_PATH.as_posix())
+ ar=LLVM_TOOLCHAIN_HOST.ar().as_posix())
def device_config(
@@ -242,10 +257,16 @@ def device_config(
env[f"LD_{envified_target}"] = str(ld_wrapper_name)
instantiate_template_exec(
- DEVICE_CC_WRAPPER_TEMPLATE, cc_wrapper_name, real_cc=CC_PATH, cc_flags=cc_flags_str)
+ DEVICE_CC_WRAPPER_TEMPLATE,
+ cc_wrapper_name,
+ real_cc=LLVM_TOOLCHAIN_HOST.clang(),
+ cc_flags=cc_flags_str)
instantiate_template_exec(
- DEVICE_LINKER_WRAPPER_TEMPLATE, ld_wrapper_name, real_cc=CC_PATH, ld_flags=ld_flags_str)
+ DEVICE_LINKER_WRAPPER_TEMPLATE,
+ ld_wrapper_name,
+ real_cc=LLVM_TOOLCHAIN_HOST.clang(),
+ ld_flags=ld_flags_str)
# as_posix() is necessary here to prevent the backslashes from being
# interpreted as the start of an esacape sequence on Windows hosts.
@@ -255,7 +276,7 @@ def device_config(
cc=cc_wrapper_name.as_posix(),
cxx=cc_wrapper_name.as_posix(),
linker=ld_wrapper_name.as_posix(),
- ar=AR_PATH.as_posix())
+ ar=LLVM_TOOLCHAIN_HOST.ar().as_posix())
#
@@ -312,7 +333,7 @@ HOST_LINUX_LD_FLAGS: list[str] = [
f"-B{GCC_LIBGCC_PATH}",
f"-L{GCC_LIBGCC_PATH}",
f"-L{GCC_LIB_PATH}",
- f"-L{LLVM_CXX_RUNTIME_PATH_HOST}",
+ f"-L{LLVM_TOOLCHAIN_HOST.lib()}",
LD_OLD_DTAGS,
LD_FLAG_RPATH,
]
@@ -321,7 +342,7 @@ HOST_WINDOWS_LDFLAGS: list[str] = [
f"-B{MINGW_LIBGCC_PATH}",
f"-L{MINGW_LIBGCC_PATH}",
f"-L{MINGW_LIB_PATH}",
- f"-L{LLVM_CXX_RUNTIME_PATH_WINDOWS}",
+ f"-L{LLVM_TOOLCHAIN_WINDOWS.lib()}",
]
TARGET_LD_FLAGS: dict[str, list[str]] = {
# When performing LTO, the LLVM IR generator doesn't know about these
@@ -337,17 +358,17 @@ TARGET_LD_FLAGS: dict[str, list[str]] = {
"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}",
+ f"-L{LLVM_TOOLCHAIN_HOST.lib()}",
LD_FLAG_RPATH,
],
"aarch64-apple-darwin": [
- f"-L{LLVM_CXX_RUNTIME_PATH_HOST}",
+ f"-L{LLVM_TOOLCHAIN_HOST.lib()}",
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{LLVM_TOOLCHAIN_HOST.musl_lib()}",
f"-L{MUSL_SYSROOT64_PATH}/lib",
LD_OLD_DTAGS,
LD_FLAG_RPATH,
@@ -355,7 +376,7 @@ TARGET_LD_FLAGS: dict[str, list[str]] = {
"i686-unknown-linux-musl": [
LD_FLAG_USE_LLD,
"--rtlib=compiler-rt",
- f"-L{LLVM_CXX_RUNTIME_PATH_LINUX_MUSL}",
+ f"-L{LLVM_TOOLCHAIN_HOST.musl_lib()}",
f"-L{MUSL_SYSROOT32_PATH}/lib",
LD_OLD_DTAGS,
LD_FLAG_RPATH,
@@ -444,7 +465,7 @@ def configure(args: argparse.Namespace, env: dict[str, str]) -> None:
# 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"] = str(LLVM_CXX_RUNTIME_PATH_HOST)
+ env["LD_LIBRARY_PATH"] = str(LLVM_TOOLCHAIN_HOST.lib())
# Tell the rust bootstrap system where to place its final products
env["DESTDIR"] = str(OUT_PATH_PACKAGE)
@@ -465,7 +486,7 @@ def configure(args: argparse.Namespace, env: dict[str, str]) -> None:
# Explicitly set the host AR path; this is required to build the
# openssl-src crate.
- env["AR"] = str(AR_PATH)
+ env["AR"] = str(LLVM_TOOLCHAIN_HOST.ar())
env["CARGO_HOME"] = str(OUT_PATH_CARGO_HOME)
@@ -513,7 +534,7 @@ def configure(args: argparse.Namespace, env: dict[str, str]) -> None:
# All flags from host_cc_flags will be added to host_cxx_flags
host_cxx_flags = [
"--stdlib=libc++",
- f"-I{CXXSTD_PATH}",
+ f"-I{LLVM_TOOLCHAIN_HOST.cxxstd()}",
]
host_ld_flags = [
LD_FLAG_PIC,
@@ -540,7 +561,7 @@ def configure(args: argparse.Namespace, env: dict[str, str]) -> None:
env_cflags: list[str] = []
env_rustflags: list[str] = [
"-Crelocation-model=pic",
- f"-Cdlltool={DLLTOOL_PATH}",
+ f"-Cdlltool={LLVM_TOOLCHAIN_HOST.dlltool()}",
] + ([] if args.verbose else ["-Awarnings"])
env_rustflags_bootstrap: list[str] = []
env_rustflags_not_bootstrap: list[str] = []
@@ -561,8 +582,11 @@ def configure(args: argparse.Namespace, env: dict[str, str]) -> None:
# 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():
+ device_lib = LLVM_TOOLCHAIN_LINUX.device_lib()
+ assert (device_lib is not None)
+
for target, arch in DEVICE_TARGET_AND_ARCH.items():
- unwind_path = DEVICE_LIB_PATH / arch
+ unwind_path = device_lib / arch
if not unwind_path.is_dir():
raise RuntimeError(f"{unwind_path} is not a directory")
@@ -615,7 +639,7 @@ def configure(args: argparse.Namespace, env: dict[str, str]) -> None:
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}")
+ raise ScriptException(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
@@ -758,13 +782,13 @@ def configure(args: argparse.Namespace, env: dict[str, str]) -> None:
llvm_cxxflags=llvm_cc_flags_str,
llvm_ldflags=llvm_ld_flags_str,
llvm_lto_config=llvm_lto_config,
- llvm_cxx_runtime_path_host=LLVM_CXX_RUNTIME_PATH_HOST.as_posix(),
+ llvm_cxx_runtime_path_host=LLVM_TOOLCHAIN_HOST.lib(),
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(),
+ cargo=args.rust_stage0.cargo().as_posix(),
+ rustc=args.rust_stage0.rustc().as_posix(),
python=PYTHON_PATH.as_posix(),
verbose=1 if args.verbose else 0,
description=f"\"Android Rust Toolchain version {args.build_name}\"",
diff --git a/src/android_rust/paths.py b/src/android_rust/paths.py
index 26ed5ef..3201240 100644
--- a/src/android_rust/paths.py
+++ b/src/android_rust/paths.py
@@ -111,10 +111,6 @@ RUST_HOST_STAGE0_PATH: Path = RUST_PREBUILT_PATH / build_platform.pr
LLVM_PREBUILT_PATH_HOST: Path = PREBUILT_PATH / "clang" / "host" / build_platform.prebuilt() / CLANG_NAME
LLVM_PREBUILT_PATH_LINUX: Path = PREBUILT_PATH / "clang" / "host" / "linux-x86" / CLANG_NAME
LLVM_PREBUILT_PATH_WINDOWS: Path = PREBUILT_PATH / "clang" / "host" / "windows-x86" / CLANG_NAME
-LLVM_CXX_RUNTIME_PATH_HOST: Path = LLVM_PREBUILT_PATH_HOST / "lib"
-LLVM_CXX_RUNTIME_PATH_LINUX_GLIBC: Path = LLVM_PREBUILT_PATH_LINUX / "lib"
-LLVM_CXX_RUNTIME_PATH_LINUX_MUSL: Path = LLVM_PREBUILT_PATH_LINUX / "musl" / "lib" / "x86_64-unknown-linux-musl"
-LLVM_CXX_RUNTIME_PATH_WINDOWS: Path = LLVM_PREBUILT_PATH_WINDOWS / "lib"
GCC_TOOLCHAIN_PATH: Path = PREBUILT_PATH / "gcc" / build_platform.prebuilt() / "host" / ("x86_64-linux-glibc" + GLIBC_VERSION)
GCC_LIB_PATH: Path = GCC_TOOLCHAIN_PATH / "x86_64-linux" / "lib64"
@@ -149,26 +145,6 @@ NDK_SYSROOT_PATH_SUFFIX: Path = Path("sysroot")
SOONG_PATH: Path = WORKSPACE_PATH / "build" / "soong"
#
-# Paths to toolchain executables
-#
-_EXE = ".exe" if build_platform.is_windows() else ""
-CARGO_PATH: Path = RUST_HOST_STAGE0_PATH / "bin" / ("cargo" + _EXE)
-RUSTC_PATH: Path = RUST_HOST_STAGE0_PATH / "bin" / ("rustc" + _EXE)
-NEW_CARGO_PATH: Path = OUT_PATH_PACKAGE / "bin" / ("cargo" + _EXE)
-CC_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("clang" + _EXE)
-CXX_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("clang++" + _EXE)
-AR_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("llvm-ar" + _EXE)
-DLLTOOL_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("llvm-dlltool" + _EXE)
-BOLT_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("llvm-bolt" + _EXE)
-RANLIB_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("llvm-ranlib" + _EXE)
-PROFDATA_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("llvm-profdata" + _EXE)
-OBJCOPY_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("llvm-objcopy" + _EXE)
-RANLIB_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("llvm-ranlib" + _EXE)
-READELF_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("llvm-readelf" + _EXE)
-MERGE_FDATA_PATH: Path = LLVM_PREBUILT_PATH_HOST / "bin" / ("merge-fdata" + _EXE)
-CXXSTD_PATH: Path = LLVM_PREBUILT_PATH_HOST / "include" / "c++" / "v1"
-
-#
# Paths to utilities used by the build script.
#
@@ -186,7 +162,6 @@ if build_platform.is_windows():
GIT_USR_BIN_PATH: Path = Path("C:\\") / "program files" / "git" / "usr" / "bin"
FILE_PATH: Path = GIT_USR_BIN_PATH / "file.exe"
PATCH_PATH: Path = GIT_USR_BIN_PATH / "patch.exe"
- DEVICE_LIB_PATH: Path = LLVM_CXX_RUNTIME_PATH_LINUX_GLIBC / "clang" / CLANG_VERSION / "lib" / "linux"
TAR_PATH: Path = Path("C:\\") / "phony" / "path" / "do" / "not" / "use"
else:
PYTHON_PATH: Path = PYTHON_PREBUILT_PATH / "bin" / "python3"
diff --git a/src/android_rust/source_manager.py b/src/android_rust/source_manager.py
index 9d90b5d..eba520b 100644
--- a/src/android_rust/source_manager.py
+++ b/src/android_rust/source_manager.py
@@ -17,14 +17,13 @@
Package to manage Rust source files when building a toolchain distributable.
"""
+import io
from pathlib import Path
import shutil
import subprocess
-import sys
-from typing import Any
from android_rust.paths import OUT_PATH_PATCHS_LOG, PATCH_PATH, OUT_PATH_PATCHED_FILES
-from android_rust.utils import prepare_command
+from android_rust.utils import ScriptException, prepare_command
def ensure_unique_patch_numbers(patch_list: list[Path]) -> None:
@@ -69,7 +68,7 @@ def copy_or_restore(
patched_files.write(f"{file}\n")
-def apply_patches(code_dir: Path, patch_list: list[Path], patch_abort: bool = False) -> None:
+def apply_patches(code_dir: Path, patch_list: list[Path]) -> None:
count_padding = len(str(len(patch_list)))
# We will overwrite the log file if it already existed.
@@ -93,20 +92,18 @@ def apply_patches(code_dir: Path, patch_list: list[Path], patch_abort: bool = Fa
if result.stderr:
f.write(result.stderr.decode("UTF-8") + "\n")
- if result.returncode != 0 and patch_abort:
- print(f"\nBuild failed when applying patch {filepath}")
- print("If developing locally, try the --no-patch-abort flag")
+ if result.returncode != 0:
+ err_msg = io.StringIO()
+ err_msg.write(f"Failed to apply patch {filepath}\n")
if result.stdout:
- print("\nOutput (stdout):")
- print(result.stdout.decode("UTF-8"))
+ err_msg.write("\nOutput (stdout):")
+ err_msg.write(result.stdout.decode("UTF-8"))
if result.stderr:
- print("\nOutput (stderr):")
- print(result.stderr.decode("UTF-8"))
-
- print("Failed")
+ err_msg.write("\nOutput (stderr):")
+ err_msg.write(result.stderr.decode("UTF-8"))
f.truncate()
- sys.exit(result.returncode)
+ raise ScriptException(err_msg.getvalue())
# Remove any possible leftovers from the previous log
f.truncate()
@@ -117,11 +114,7 @@ def apply_patches(code_dir: Path, patch_list: list[Path], patch_abort: bool = Fa
def setup_files(
- input_dir: Path,
- output_dir: Path,
- patches_dir: Path,
- patch_abort: bool = False,
- repatch: bool = False) -> None:
+ input_dir: Path, output_dir: Path, patches_dir: Path, repatch: bool = False) -> None:
"""Copy source and apply patches in a performant and fault-tolerant manner.
This function creates a copy of the source directory and
@@ -132,4 +125,4 @@ def setup_files(
ensure_unique_patch_numbers(patch_list)
copy_or_restore(input_dir, output_dir, patch_list, repatch, True)
- apply_patches(output_dir, patch_list, patch_abort=patch_abort)
+ apply_patches(output_dir, patch_list)
diff --git a/src/android_rust/toolchains.py b/src/android_rust/toolchains.py
new file mode 100644
index 0000000..fa9585e
--- /dev/null
+++ b/src/android_rust/toolchains.py
@@ -0,0 +1,159 @@
+# Copyright (C) 2024 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.
+
+import inspect
+from pathlib import Path
+
+from android_rust.paths import CLANG_VERSION, LLVM_PREBUILT_PATH_HOST, LLVM_PREBUILT_PATH_LINUX, LLVM_PREBUILT_PATH_WINDOWS, RUST_HOST_STAGE0_PATH
+
+
+class ClangToolchain:
+ PATH_METHODS = [
+ "ar",
+ "bolt",
+ "clang",
+ "clangxx",
+ "dlltool",
+ "merge_fdata",
+ "objcopy",
+ "profdata",
+ "ranlib",
+ "readelf",
+ ]
+
+ def __init__(self, base_dir: Path):
+ self.base_dir = base_dir
+ self.bin_dir = base_dir / "bin"
+ self.exe = ".exe" if self.is_windows() else ""
+
+ for method_name in self.__class__.PATH_METHODS:
+ path = getattr(self, method_name)()
+ if path is not None and not path.exists():
+ raise RuntimeError(f"Clang toolchain path does not exist: {path}")
+
+ #
+ # Binary Paths
+ #
+
+ def ar(self) -> Path:
+ return self.bin_dir / ("llvm-ar" + self.exe)
+
+ def bolt(self) -> Path | None:
+ if self.is_linux():
+ return self.bin_dir / ("llvm-bolt" + self.exe)
+ else:
+ return None
+
+ def clang(self) -> Path:
+ return self.bin_dir / ("clang" + self.exe)
+
+ def clangxx(self) -> Path:
+ return self.bin_dir / ("clang++" + self.exe)
+
+ def dlltool(self) -> Path:
+ return self.bin_dir / ("llvm-dlltool" + self.exe)
+
+ def merge_fdata(self) -> Path | None:
+ if self.is_linux():
+ return self.bin_dir / ("merge-fdata" + self.exe)
+ else:
+ return None
+
+ def objcopy(self) -> Path:
+ return self.bin_dir / ("llvm-objcopy" + self.exe)
+
+ def profdata(self) -> Path:
+ return self.bin_dir / ("llvm-profdata" + self.exe)
+
+ def ranlib(self) -> Path:
+ return self.bin_dir / ("llvm-ranlib" + self.exe)
+
+ def readelf(self) -> Path:
+ return self.bin_dir / ("llvm-readelf" + self.exe)
+
+ #
+ # Include Paths
+ #
+
+ def cxxstd(self) -> Path:
+ return self.base_dir / "include" / "c++" / "v1"
+
+ def lib(self) -> Path:
+ return self.base_dir / "lib"
+
+ def musl_lib(self) -> Path | None:
+ if self.is_linux():
+ return self.base_dir / "musl" / "lib" / "x86_64-unknown-linux-musl"
+ else:
+ return None
+
+ def device_lib(self) -> Path | None:
+ if self.is_linux():
+ return self.base_dir / "lib" / "clang" / CLANG_VERSION / "lib" / "linux"
+ else:
+ return None
+
+ #
+ # Helper Functions
+ #
+
+ def is_linux(self) -> bool:
+ return "linux" in str(self.base_dir)
+
+ def is_windows(self) -> bool:
+ return "windows" in str(self.base_dir)
+
+
+class RustToolchain:
+ PATH_METHODS = [
+ "cargo",
+ "rustc",
+ ]
+
+ def __init__(self, base_dir: Path):
+ self.base_dir = base_dir
+ self.bin_dir = base_dir / "bin"
+ self.exe = ".exe" if self.is_windows() else ""
+
+ for method_name in self.__class__.PATH_METHODS:
+ path = getattr(self, method_name)()
+ if path is not None and not path.exists():
+ raise RuntimeError(f"Clang toolchain path does not exist: {path}")
+
+ #
+ # Binary Paths
+ #
+
+ def cargo(self) -> Path:
+ return self.bin_dir / ("cargo" + self.exe)
+
+ def rustc(self) -> Path:
+ return self.bin_dir / ("rustc" + self.exe)
+
+ #
+ # Helper Functions
+ #
+
+ def is_linux(self) -> bool:
+ return "linux" in str(self.base_dir)
+
+ def is_windows(self) -> bool:
+ return "windows" in str(self.base_dir)
+
+
+LLVM_TOOLCHAIN_HOST = ClangToolchain(LLVM_PREBUILT_PATH_HOST)
+LLVM_TOOLCHAIN_LINUX = ClangToolchain(LLVM_PREBUILT_PATH_LINUX)
+LLVM_TOOLCHAIN_WINDOWS = ClangToolchain(LLVM_PREBUILT_PATH_WINDOWS)
+
+RUST_TOOLCHAIN_HOST = RustToolchain(RUST_HOST_STAGE0_PATH)
diff --git a/src/android_rust/utils.py b/src/android_rust/utils.py
index 221bd22..94edac8 100644
--- a/src/android_rust/utils.py
+++ b/src/android_rust/utils.py
@@ -30,8 +30,6 @@ from typing import Any, Optional, TextIO, TypedDict, Tuple, Union, cast
import android_rust.build_platform as build_platform
from android_rust.paths import (
FILE_PATH,
- MERGE_FDATA_PATH,
- OBJCOPY_PATH,
OUT_PATH,
PROFILE_NAME_LLVM,
PROFILE_NAME_LLVM_CS,
@@ -39,12 +37,12 @@ from android_rust.paths import (
PROFILE_NAMES,
PROFILE_SUBDIR_BOLT,
PROFILE_SUBDIRS,
- PROFDATA_PATH,
SOONG_UI_PATH,
TAR_PATH,
UNZIP_LINK_PATH,
WORKSPACE_PATH,
XZ_PATH)
+from android_rust.toolchains import LLVM_TOOLCHAIN_HOST
class RunQuietArgDct(TypedDict):
@@ -52,6 +50,18 @@ class RunQuietArgDct(TypedDict):
stderr: int
+class ScriptException(Exception):
+
+ """
+ Indicates that the arguments given either don't work or don't make sense
+ in the context of the system state
+ """
+
+ def __init__(self, message: str):
+ self.message = message
+ super().__init__(message)
+
+
GIT_REFERENCE_BRANCH = "aosp/main"
# BOLT profile name examples:
@@ -270,7 +280,7 @@ class GitRepo:
self.checkout(branch_name)
return False
else:
- sys.exit(
+ raise ScriptException(
f"Branch {branch_name} already exists and the 'overwrite' option was not set")
else:
print(f"Creating branch {branch_name}")
@@ -295,7 +305,7 @@ class GitRepo:
elif retcode == 1:
return True
else:
- sys.exit("Failed to compute diff for Git repo {self.path}")
+ raise RuntimeError("Failed to compute diff for Git repo {self.path}")
def reset_hard(self, number: int) -> None:
run_and_exit_on_failure(["git", "reset", "--hard", f"HEAD~{number}"],
@@ -439,18 +449,22 @@ def get_prebuilt_binary_paths(root: Path, toplevel_only: bool = False) -> list[P
def merge_profdata(inputs: list[Path], outpath: Path) -> None:
- run_and_exit_on_failure([
- PROFDATA_PATH,
+ run_and_exit_on_failure(
+ [
+ LLVM_TOOLCHAIN_HOST.profdata(),
"merge",
- "-o", outpath,
+ "-o",
+ outpath,
] + inputs,
f"Failed to produce merged PGO profile {outpath}") # yapf: disable
def merge_fdata(inputs: list[Path], outpath: Path) -> None:
- run_quiet_and_exit_on_failure([
- MERGE_FDATA_PATH,
- "-o", outpath,
+ run_quiet_and_exit_on_failure(
+ [
+ LLVM_TOOLCHAIN_HOST.merge_fdata(),
+ "-o",
+ outpath,
] + inputs,
f"Failed to produce merged BOLT profiles {outpath}") # yapf: disable
@@ -509,7 +523,8 @@ def export_profiles(src_path: Optional[Path], dist_path: Path) -> None:
merge_fdata(
list(src_path.glob(f"{binary}.*.fdata")), bolt_output_path / f"{binary}.fdata")
- archive_create(dist_path / "bolt-profiles", dist_path, PROFILE_SUBDIR_BOLT, overwrite=True)
+ archive_create(
+ dist_path / "bolt-profiles", dist_path, PROFILE_SUBDIR_BOLT, overwrite=True)
else:
for subdir, profile_name in zip(PROFILE_SUBDIRS, PROFILE_NAMES):
@@ -535,8 +550,9 @@ def merge_project_profiles(indirs: list[Path], outdir: Path) -> None:
def strip_symbols(obj_path: Path, flag: str = "--strip-unneeded") -> int:
- return subprocess.run([str(OBJCOPY_PATH), "--keep-section='.rustc'", flag,
- str(obj_path)]).returncode
+ return subprocess.run(
+ [str(LLVM_TOOLCHAIN_HOST.objcopy()), "--keep-section='.rustc'", flag,
+ str(obj_path)]).returncode
#
@@ -587,7 +603,11 @@ def instantiate_template(template_path: Path, **kwargs: Any) -> str:
#
-def archive_create(out_path_stem: Path, root_dir: Path, base_dir: Path = Path("."), overwrite: bool = False) -> int:
+def archive_create(
+ out_path_stem: Path,
+ root_dir: Path,
+ base_dir: Path = Path("."),
+ overwrite: bool = False) -> int:
archive_path = out_path_stem.with_suffix(out_path_stem.suffix + ".tar")
if overwrite:
diff --git a/tools/audit.py b/tools/audit.py
index 6d2aa2c..d262f6b 100755
--- a/tools/audit.py
+++ b/tools/audit.py
@@ -25,7 +25,8 @@ import sys
import context
-from android_rust.paths import READELF_PATH, TOOLCHAIN_RESOURCE_PATH
+from android_rust.paths import TOOLCHAIN_RESOURCE_PATH
+from android_rust.toolchains import LLVM_TOOLCHAIN_HOST
from android_rust.utils import ResolvedPath, print_colored, TERM_GREEN, TERM_RED
@@ -69,7 +70,7 @@ def get_required_libs_map(scandir: Path) -> dict[str, list[str]]:
for lib_path in lib_paths:
local_libs.append(lib_path.name)
- result = subprocess.run([READELF_PATH, "--dynamic", lib_path],
+ result = subprocess.run([LLVM_TOOLCHAIN_HOST.readelf(), "--dynamic", lib_path],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
text=True)
diff --git a/tools/boltifyer.py b/tools/boltifyer.py
index a9cd856..a73bb38 100755
--- a/tools/boltifyer.py
+++ b/tools/boltifyer.py
@@ -26,7 +26,9 @@ from typing import Optional, TextIO
import context
+from android_rust import build_platform
from android_rust.paths import *
+from android_rust.toolchains import LLVM_TOOLCHAIN_HOST
from android_rust.utils import (
ExtantPath,
ResolvedPath,
@@ -97,13 +99,16 @@ def parse_args() -> argparse.Namespace:
@contextmanager
-def unpack_prebuilt_archive(archive_path: Path) -> Iterator[Path]:
- with TemporaryDirectory() as temp_dir:
- temp_dir_path = Path(temp_dir)
- print(f"Unpacking archive into {temp_dir}")
- if archive_extract(archive_path, temp_dir_path) != 0:
- raise RuntimeError("Failed to unpack prebuilt archive")
- yield temp_dir_path
+def handle_input_path(input_path: Path) -> Iterator[Path]:
+ if is_archive(input_path):
+ with TemporaryDirectory() as temp_dir:
+ temp_dir_path = Path(temp_dir)
+ print(f"Unpacking archive into {temp_dir}")
+ if archive_extract(input_path, temp_dir_path) != 0:
+ raise RuntimeError("Failed to unpack prebuilt archive")
+ yield temp_dir_path
+ else:
+ yield input_path
@contextmanager
@@ -123,12 +128,15 @@ def expand_profiles(profile_path: Path | None) -> Iterator[Path | None]:
def invoke_bolt(obj_path: Path, bolt_log: TextIO, options: list[str] = []) -> int:
+ bolt_path = LLVM_TOOLCHAIN_HOST.bolt()
+ assert (bolt_path is not None)
+
obj_path_bolted = extend_suffix(obj_path, ".bolt")
bolt_log.write(f"BOLTing {str(obj_path)}\n")
print(f"BOLTing {str(obj_path)}\n")
bolt_log.flush()
- retcode = subprocess.run([BOLT_PATH] + options + ["-o", obj_path_bolted, obj_path],
+ retcode = subprocess.run([bolt_path] + options + ["-o", obj_path_bolted, obj_path],
stdout=bolt_log,
stderr=bolt_log).returncode
@@ -195,14 +203,14 @@ def process_objects(
return 0
-def boltify_archive(
+def boltify_toolchain(
input_path: Path,
dist_path: Path,
build_name: str,
profile_generate: Path | None = None,
profile_use: Path | None = None) -> int:
with (dist_path / BOLT_LOG_NAME).open("w") as bolt_log:
- with unpack_prebuilt_archive(input_path) as toolchain_dir_path:
+ with handle_input_path(input_path) as toolchain_dir_path:
print_fs_tree(toolchain_dir_path)
with expand_profiles(profile_use) as profile_use_path:
@@ -217,15 +225,20 @@ def boltify_archive(
return retcode
print(f"Creating BOLTed archive")
- retcode = archive_create(dist_path / f"rust-{build_name}", toolchain_dir_path, overwrite=True)
+ retcode = archive_create(
+ dist_path / f"rust-{build_name}", toolchain_dir_path, overwrite=True)
if retcode != 0:
print("Error creating the BOLTed archive")
return retcode
def main() -> int:
+ if not build_platform.is_linux():
+ print("BOLT tools are only available on Linux hosts")
+ return 1
+
args = parse_args()
- retval = boltify_archive(
+ retval = boltify_toolchain(
args.archive_path,
args.dist_path,
args.build_name,
diff --git a/tools/build.py b/tools/build.py
index bc31852..ad8d204 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -28,16 +28,19 @@ import tarfile
import tempfile
import urllib.request
+from boltifyer import boltify_toolchain
import context
import audit
from android_rust import build_platform, cargo, config, source_manager
from android_rust.paths import *
+from android_rust.toolchains import LLVM_TOOLCHAIN_HOST, RustToolchain
from android_rust.utils import (
TERM_GREEN,
TERM_RED,
TERM_YELLOW,
+ ScriptException,
ExtantPath,
ResolvedPath,
archive_create,
@@ -96,7 +99,12 @@ def parse_args(argv: list[str] | None) -> argparse.Namespace:
"""Parses arguments and returns the parsed structure."""
parser = argparse.ArgumentParser("Build the Rust Toolchain")
parser.add_argument(
- "--build-name", "-b", default="dev", help="Release name for the dist result")
+ "--build-name",
+ "-b",
+ default=build_platform.system(),
+ help="Release name for the dist result")
+ parser.add_argument(
+ "--bolt-name", help="Name for the archive containing the BOLTed version of the toolchain")
parser.add_argument(
"--dist",
"-d",
@@ -114,11 +122,6 @@ def parse_args(argv: list[str] | None) -> argparse.Namespace:
action="store_true",
help="Don't copy the whole source. Just copy and repatch the files affected by the patches.")
parser.add_argument(
- "--patch-abort",
- action=argparse.BooleanOptionalAction,
- default=True,
- help="Abort on patch failure")
- parser.add_argument(
"--stage", "-s", type=int, choices=[1, 2, 3], help="Target Rust boostrap stage")
parser.add_argument(
"--config-only",
@@ -132,6 +135,12 @@ def parse_args(argv: list[str] | None) -> argparse.Namespace:
parser.add_argument(
"--verbose", action=argparse.BooleanOptionalAction, default=True, help="Verbose")
+ parser.add_argument(
+ "--rust-stage0",
+ type=ExtantPath,
+ default=RUST_HOST_STAGE0_PATH,
+ help="Path to Rust toolchain to bootstrap this build")
+
ndk_group = parser.add_mutually_exclusive_group()
ndk_group.add_argument(
"--ndk",
@@ -164,6 +173,22 @@ def parse_args(argv: list[str] | None) -> argparse.Namespace:
nargs="?",
const=OUT_PATH_PROFILES,
help="Instrument the LLVM libraries to generate context-sensitive profiles")
+
+ parser.add_argument(
+ "--bolt-opt",
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help="Produce an additional BOLT optimized copy of the toolchain")
+
+ bolt_group = parser.add_mutually_exclusive_group()
+ bolt_group.add_argument(
+ "--bolt-profile-generate",
+ type=ExtantPath,
+ nargs="?",
+ const=OUT_PATH_PROFILES,
+ help="Add BOLT instrumentation to the toolchain")
+ bolt_group.add_argument("--bolt-profile-use", type=ExtantPath, help="Path to BOLT profiles")
+
parser.add_argument(
"--lto",
"-l",
@@ -241,6 +266,15 @@ def parse_args(argv: list[str] | None) -> argparse.Namespace:
args.device_targets = False
args.host_multilibs = False
+ if args.bolt_name is None:
+ args.bolt_name = args.build_name + "-bolt"
+
+ if args.bolt_profile_use is not None or args.bolt_profile_generate is not None:
+ args.bolt_opt = True
+
+ if args.bolt_opt:
+ args.emit_relocs = True
+
return args
@@ -291,6 +325,16 @@ def initialize_ndk(args: argparse.Namespace) -> int:
return 1
+def initialize_rust_stage0(args: argparse.Namespace) -> None:
+ if is_archive(args.rust_stage0):
+ print("Extracting Rust Stage 0 archive")
+ extract_dir = Path(tempfile.mkdtemp(prefix="rust-stage0-"))
+ archive_extract(args.rust_stage0, extract_dir)
+ args.rust_stage0 = extract_dir
+
+ args.rust_stage0 = RustToolchain(args.rust_stage0)
+
+
def extract_ndk_archive(archive_path: Path) -> Path:
print(f"Unzipping NKD archive {str(archive_path)}")
@@ -306,11 +350,12 @@ def extract_ndk_archive(archive_path: Path) -> Path:
return extract_dir / archive_top_level[0].name
-def regenerate_lockfile(project_path: Path, env: dict[str, str]) -> None:
+def regenerate_lockfile(
+ rust_toolchain: RustToolchain, project_path: Path, env: dict[str, str]) -> None:
"""Offline fetch to regenerate lockfiles"""
- run_and_exit_on_failure([CARGO_PATH, "fetch", "--offline"],
- f"Failed to rebuild {project_path}/Cargo.lock via cargo-fetch operation",
+ run_and_exit_on_failure([rust_toolchain.cargo(), "fetch", "--offline"],
+ f"Failed to rebuilt {project_path}/Cargo.lock via cargo-fetch operation",
cwd=project_path,
env=env)
@@ -367,23 +412,21 @@ def main(argv: list[str] | None = None) -> int:
raise RuntimeError("Unable to find sh executable")
os.symlink(ZIPTOOL_PATH, UNZIP_LINK_PATH)
- os.symlink(OBJCOPY_PATH, STRIP_LINK_PATH)
+ os.symlink(LLVM_TOOLCHAIN_HOST.objcopy(), STRIP_LINK_PATH)
retcode = initialize_ndk(args)
if retcode != 0:
return retcode
+ initialize_rust_stage0(args)
+
#
# Setup source files
#
if args.copy_and_patch:
source_manager.setup_files(
- RUST_SOURCE_PATH,
- OUT_PATH_RUST_SOURCE,
- PATCHES_PATH,
- patch_abort=args.patch_abort,
- repatch=args.repatch)
+ RUST_SOURCE_PATH, OUT_PATH_RUST_SOURCE, PATCHES_PATH, repatch=args.repatch)
if build_platform.is_darwin():
# To avoid using system libc++.dylib on Darwin hosts we need to copy
@@ -391,7 +434,7 @@ def main(argv: list[str] | None = None) -> int:
# necessary because buildbot security policies do not allow for
# modifying the DYLD_LIBRARY_PATH environment variable.
OUT_PATH_LLVM_LIB_DIR.mkdir(parents=True, exist_ok=True)
- shutil.copy2(LLVM_CXX_RUNTIME_PATH_HOST / "libc++.dylib", OUT_PATH_LLVM_LIB_DIR)
+ shutil.copy2(LLVM_TOOLCHAIN_HOST.lib() / "libc++.dylib", OUT_PATH_LLVM_LIB_DIR)
#
# Configure Rust
@@ -421,10 +464,10 @@ def main(argv: list[str] | None = None) -> int:
# Because some patches may have touched vendored source we will rebuild
# specific Cargo.lock files.
- regenerate_lockfile(OUT_PATH_RUST_SOURCE, env)
+ regenerate_lockfile(args.rust_stage0, OUT_PATH_RUST_SOURCE, env)
# TODO: Required by patch #40
- regenerate_lockfile(OUT_PATH_RUST_BOOTSTRAP_SOURCE, env)
- regenerate_lockfile(OUT_PATH_RUST_CARGO_SOURCE, env)
+ regenerate_lockfile(args.rust_stage0, OUT_PATH_RUST_BOOTSTRAP_SOURCE, env)
+ regenerate_lockfile(args.rust_stage0, OUT_PATH_RUST_CARGO_SOURCE, env)
# We only need to perform stage 3 of the bootstrap process when we are
# collecting profile data.
@@ -524,13 +567,16 @@ def main(argv: list[str] | None = None) -> int:
copy_libs = []
# Install the libc++ library to out/package/lib64/
if build_platform.is_darwin():
- copy_libs.append(LLVM_CXX_RUNTIME_PATH_HOST / "libc++.dylib")
- copy_libs.append(LLVM_CXX_RUNTIME_PATH_HOST / "libc++abi.dylib")
+ copy_libs.append(LLVM_TOOLCHAIN_HOST.lib() / "libc++.dylib")
+ copy_libs.append(LLVM_TOOLCHAIN_HOST.lib() / "libc++abi.dylib")
elif args.host == "x86_64-unknown-linux-musl":
- copy_libs.append(LLVM_CXX_RUNTIME_PATH_LINUX_MUSL / "libc++.so")
+ musl_lib = LLVM_TOOLCHAIN_HOST.musl_lib()
+ assert (musl_lib)
+
+ copy_libs.append(musl_lib / "libc++.so")
copy_libs.append(MUSL_SYSROOT64_PATH / "lib" / "libc_musl.so")
elif not build_platform.is_windows():
- copy_libs.append(LLVM_CXX_RUNTIME_PATH_HOST / "libc++.so")
+ copy_libs.append(LLVM_TOOLCHAIN_HOST.lib() / "libc++.so")
if copy_libs:
lib64_path = OUT_PATH_PACKAGE / "lib64"
@@ -553,17 +599,18 @@ def main(argv: list[str] | None = None) -> int:
#
if args.host == build_platform.triple():
+ new_toolchain = RustToolchain(OUT_PATH_PACKAGE)
cargo_deny = cargo.Crate(
WORKSPACE_PATH / "toolchain" / "cargo-deny",
env,
- cargo_path=NEW_CARGO_PATH,
+ cargo_path=new_toolchain.cargo(),
target=args.host,
linker=config.get_wrapper_paths(args.host)[2])
cargo_deny.cargo_install(OUT_PATH_PACKAGE)
cargo_vet = cargo.Crate(
WORKSPACE_PATH / "toolchain" / "cargo-vet",
env,
- cargo_path=NEW_CARGO_PATH,
+ cargo_path=new_toolchain.cargo(),
target=args.host,
linker=config.get_wrapper_paths(args.host)[2])
cargo_vet.cargo_install(OUT_PATH_PACKAGE)
@@ -625,14 +672,34 @@ def main(argv: list[str] | None = None) -> int:
print("")
#
+ # BOLT
+ #
+
+ if args.bolt_opt:
+ boltify_toolchain(
+ OUT_PATH_PACKAGE,
+ args.dist_path,
+ args.bolt_name,
+ profile_generate=args.bolt_profile_generate,
+ profile_use=args.bolt_profile_use)
+
+ #
# Cleanup
#
if args.ndk_path.is_relative_to(tempfile.gettempdir()):
shutil.rmtree(args.ndk_path)
+ if args.rust_stage0.base_dir.is_relative_to(tempfile.gettempdir()):
+ shutil.rmtree(args.rust_stage0.base_dir.as_posix())
+
return retcode
if __name__ == "__main__":
- sys.exit(main())
+ try:
+ sys.exit(main())
+
+ except (ScriptException, argparse.ArgumentTypeError) as err:
+ print_colored(str(err), TERM_RED)
+ sys.exit(1)
diff --git a/tools/fetch_source.py b/tools/fetch_source.py
index 3948a18..9baa460 100755
--- a/tools/fetch_source.py
+++ b/tools/fetch_source.py
@@ -15,6 +15,7 @@
# limitations under the License.
import argparse
+import sys
import context
@@ -138,7 +139,7 @@ def fetch_and_extract_archive(build_type: str, rust_version: str) -> None:
RUST_REPO.add('.')
-def main() -> None:
+def main() -> int:
args = parse_args()
rust_version: str = args.rust_version + get_extra_tag(args.build_type)
branch_name: str = args.branch or (BRANCH_NAME_TEMPLATE % rust_version)
@@ -149,7 +150,13 @@ def main() -> None:
fetch_and_extract_archive(args.build_type, rust_version)
RUST_REPO.amend_or_commit(make_commit_message(rust_version, args.issue))
print("Done")
+ return 0
if __name__ == '__main__':
- main()
+ try:
+ sys.exit(main())
+
+ except utils.ScriptException as err:
+ utils.print_colored(str(err), utils.TERM_RED)
+ sys.exit(1)
diff --git a/tools/pipeline.py b/tools/pipeline.py
index c96eb19..d29c199 100755
--- a/tools/pipeline.py
+++ b/tools/pipeline.py
@@ -224,7 +224,7 @@ def main() -> None:
if args.start <= 4 and 4 <= args.end:
print("Executing Stage 4")
dist_path_stage4 = setup_dist_instance("stage4")
- retcode = boltifyer.boltify_archive(
+ retcode = boltifyer.boltify_toolchain(
dist_path_stage3 / f"rust-{args.build_name}-stage3.tar.xz",
dist_path_stage4,
f"rust-{args.build_name}-stage4", # .tar.xz added by archive function
@@ -290,7 +290,7 @@ def main() -> None:
if args.start <= 6 and 6 <= args.end:
print("Executing Stage 6")
dist_path_stage6 = setup_dist_instance("stage6")
- boltifyer.boltify_archive(
+ boltifyer.boltify_toolchain(
dist_path_stage3 / f"rust-{args.build_name}-stage3.tar.xz",
dist_path_stage6,
f"rust-{args.build_name}-stage6", # .tar.xz added by archive function
diff --git a/tools/update_prebuilts.py b/tools/update_prebuilts.py
index 02f9e27..8ea3e24 100755
--- a/tools/update_prebuilts.py
+++ b/tools/update_prebuilts.py
@@ -41,11 +41,14 @@ from android_rust.paths import (
TOOLCHAIN_PATH,
)
from android_rust.utils import (
+ ScriptException,
GitRepo,
archive_extract,
+ print_colored,
replace_file_contents,
run_and_exit_on_failure,
run_quiet,
+ TERM_RED,
VERSION_PATTERN,
version_string_type,
)
@@ -478,7 +481,7 @@ def update_soong(branch_name: str, overwrite: bool, version: str, bid: int, issu
SOONG_REPO.commit(make_commit_message(version, bid, issue))
-def main() -> None:
+def main() -> int:
args = parse_args()
branch_name: str = args.branch or make_branch_name(args.version)
bid: int = args.bid or get_lkgb()
@@ -502,7 +505,13 @@ def main() -> None:
update_soong(branch_name, args.overwrite, args.version, bid, args.issue)
print("Done")
+ return 0
if __name__ == "__main__":
- main()
+ try:
+ sys.exit(main())
+
+ except ScriptException as err:
+ print_colored(str(err), TERM_RED)
+ sys.exit(1)