blob: 825a239a8b8622c84edebc2d113cadc01d6f0d5b [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright (C) 2022 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 argparse
import inspect
import os
from pathlib import Path
import re
import sys
import tempfile
import context
import android_rust.build_platform as build_platform
from android_rust.paths import (
DIST_PATH_DEFAULT,
OUT_PATH_PROFILES,
PROFILE_SUBDIR_BOLT,
)
from android_rust.toolchains import CLANG_TOOLCHAIN_HOST, ClangToolchain, RustToolchain, export_profiles
from android_rust.utils import (
TERM_RED,
TEST_VERSION_NUMBER,
ExtantPath,
ResolvedPath,
ScriptException,
archive_extract,
is_archive,
prepare_prebuilts,
print_colored,
run_build_target,
)
RUST_PROFILES_NAME_PATTERN = re.compile(r"rust-profraw-(\S*)\.tar\.xz")
#
# Program logic
#
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description=inspect.getdoc(sys.modules[__name__]))
prebuilt_group = parser.add_mutually_exclusive_group(required=True)
prebuilt_group.add_argument(
"--prebuilt-path",
type=ExtantPath,
help="Path to either the build artifact or the directory that contains it")
prebuilt_group.add_argument(
"--reuse-prebuilt",
action="store_true",
help="Re-use the prebuilt in the test directory (prebuilts/rust/linux-x86/9.99.9)")
parser.add_argument(
"--target", type=str, default="aosp_cf_x86_64_phone", help="Device target to build for")
parser.add_argument(
"--variant",
type=str,
default="userdebug",
choices=[
"eng",
"user",
"userdebug",
],
help="Set the build target variant")
parser.add_argument(
"--release",
type=str,
default="trunk_staging",
choices=[
"next",
"trunk",
"trunk_food",
"trunk_staging",
],
help="Set the Android release name")
parser.add_argument(
"--dist",
"-d",
dest="dist_path",
type=ResolvedPath,
default=DIST_PATH_DEFAULT,
help="Where to place distributable artifacts")
parser.add_argument(
"--clean",
"-c",
action=argparse.BooleanOptionalAction,
default=False,
help="Run the clean step before testing the compiler")
parser.add_argument(
"--lint",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable/disable Clippy lints when building Android platform code")
parser.add_argument(
"--clang-prebuilt",
type=ExtantPath,
default=CLANG_TOOLCHAIN_HOST,
help="Path to Clang toolchain that will be used to merge profile data")
parser.add_argument(
"--all-rust",
action=argparse.BooleanOptionalAction,
default=False,
help="Build all Rust targets available for the product")
parser.add_argument(
"--image",
action=argparse.BooleanOptionalAction,
default=False,
help="Build an image as part of the compiler test")
parser.add_argument(
"--test-targets",
action=argparse.BooleanOptionalAction,
default=False,
help="Build the targets necessary to run tests in EngProd")
parser.add_argument(
"--rustdoc",
action=argparse.BooleanOptionalAction,
default=False,
help="Build all rustdoc targets")
parser.add_argument(
"--custom-targets",
nargs="+",
help="Targets to build in addition to those required by other flags")
pgo_group = parser.add_mutually_exclusive_group()
pgo_group.add_argument(
"--profile-generate",
type=Path,
nargs="?",
const=OUT_PATH_PROFILES,
help="Path where instrumented prebuilts will place their profiles")
pgo_group.add_argument(
"--cs-profile-generate",
type=Path,
nargs="?",
const=OUT_PATH_PROFILES,
help="Path were context-sensitive instrumented prebuilts will place their profiles")
pgo_group.add_argument(
"--bolt-profile-generate",
type=Path,
nargs="?",
const=OUT_PATH_PROFILES,
help="Path where BOLT instrumented prebuilts will place their profiles")
args = parser.parse_args()
if args.bolt_profile_generate:
args.bolt_profile_generate = (args.bolt_profile_generate / PROFILE_SUBDIR_BOLT).resolve()
return args
def ensure_bolt_profile_dir(profile_dir: Path) -> None:
if profile_dir:
print(f"Making BOLT profile directory: {profile_dir}")
profile_dir.mkdir(exist_ok=True, parents=True)
def initialize_clang_prebuilt(args: argparse.Namespace) -> None:
if isinstance(args.clang_prebuilt, Path):
if is_archive(args.clang_prebuilt):
extract_dir = Path(tempfile.mkdtemp(prefix="clang-prebuilt-"))
print(f"Extracting Clang archive to {extract_dir}")
archive_extract(args.clang_prebuilt, extract_dir, strip_components=1)
args.clang_prebuilt = extract_dir
args.clang_prebuilt = ClangToolchain(args.clang_prebuilt, host=build_platform.system())
def main() -> None:
args = parse_args()
if not (args.all_rust or args.rustdoc or args.image or args.test_targets or args.custom_targets):
sys.exit(
"One or more tests flags must be set: --all-rust, --rustdoc, --image, --test-targets, or --custom-targets")
initialize_clang_prebuilt(args)
toolchain_dir = prepare_prebuilts(args.prebuilt_path, args.reuse_prebuilt)
test_toolchain = RustToolchain(toolchain_dir)
env = os.environ.copy()
if args.lint is False:
env["SOONG_DISABLE_CLIPPY"] = "true"
common_args = {
"device_target": args.target,
"release_name": args.release,
"device_target_variant": args.variant,
"prebuilt_version": TEST_VERSION_NUMBER,
"env": env,
}
try:
if args.clean:
run_build_target("clean", **common_args)
ensure_bolt_profile_dir(args.bolt_profile_generate)
if args.all_rust:
print("Building Rust targets")
run_build_target(["rust"], **common_args)
if args.rustdoc:
print("Building Rustdocs targets")
run_build_target(["rustdoc"], **common_args)
if args.image:
print("Building Android image")
run_build_target(["droid", "dist"], **common_args)
if args.test_targets:
# Build the targets necessary for running tests in EngProd
print("Building Android test targets")
run_build_target([
"dist",
"continuous_instrumentation_tests",
"continuous_native_tests",
"device-tests",
"platform_tests",
],
**common_args) # yapf: disable
if args.custom_targets:
print(f"Building custom targets: {' '.join(args.custom_targets)}")
run_build_target(args.custom_targets, **common_args)
finally:
export_profiles(
args.clang_prebuilt,
args.profile_generate or args.cs_profile_generate or args.bolt_profile_generate,
args.dist_path,
test_toolchain.get_version())
if __name__ == "__main__":
try:
main()
except (ScriptException, argparse.ArgumentTypeError) as err:
print_colored(str(err), TERM_RED)
sys.exit(1)