1*924841ffSAndroid Build Coastguard Worker#!/usr/bin/env -S python3 -B 2*924841ffSAndroid Build Coastguard Worker# 3*924841ffSAndroid Build Coastguard Worker# Copyright (C) 2020 The Android Open Source Project 4*924841ffSAndroid Build Coastguard Worker# 5*924841ffSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*924841ffSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*924841ffSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*924841ffSAndroid Build Coastguard Worker# 9*924841ffSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*924841ffSAndroid Build Coastguard Worker# 11*924841ffSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*924841ffSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*924841ffSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*924841ffSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*924841ffSAndroid Build Coastguard Worker# limitations under the License. 16*924841ffSAndroid Build Coastguard Worker 17*924841ffSAndroid Build Coastguard Worker"""Downloads prebuilts for ART Module dependencies and creates CLs in git.""" 18*924841ffSAndroid Build Coastguard Worker 19*924841ffSAndroid Build Coastguard Workerimport argparse 20*924841ffSAndroid Build Coastguard Workerimport collections 21*924841ffSAndroid Build Coastguard Workerimport os 22*924841ffSAndroid Build Coastguard Workerimport subprocess 23*924841ffSAndroid Build Coastguard Workerimport sys 24*924841ffSAndroid Build Coastguard Workerimport tempfile 25*924841ffSAndroid Build Coastguard Worker 26*924841ffSAndroid Build Coastguard Worker 27*924841ffSAndroid Build Coastguard Worker# Prebuilt description used in commit message 28*924841ffSAndroid Build Coastguard WorkerPREBUILT_DESCR = "ART dependencies" 29*924841ffSAndroid Build Coastguard Worker 30*924841ffSAndroid Build Coastguard Worker 31*924841ffSAndroid Build Coastguard Worker# Branch and target tuple for a CI build 32*924841ffSAndroid Build Coastguard WorkerBuildSource = collections.namedtuple("BuildSource", [ 33*924841ffSAndroid Build Coastguard Worker "branch", 34*924841ffSAndroid Build Coastguard Worker "target", 35*924841ffSAndroid Build Coastguard Worker]) 36*924841ffSAndroid Build Coastguard Worker 37*924841ffSAndroid Build Coastguard Worker 38*924841ffSAndroid Build Coastguard Worker# The list of arches does not include riscv64: it is not supported by mainline, 39*924841ffSAndroid Build Coastguard Worker# and it is updated from a local build with --local-dist-riscv64 option (which 40*924841ffSAndroid Build Coastguard Worker# overwrites the list of arches to include only riscv64). 41*924841ffSAndroid Build Coastguard Worker# 42*924841ffSAndroid Build Coastguard Worker# TODO(b/286551985): add riscv64 here and don't override the global list. 43*924841ffSAndroid Build Coastguard WorkerARCHES = ["arm", "arm64", "x86", "x86_64"] 44*924841ffSAndroid Build Coastguard Worker 45*924841ffSAndroid Build Coastguard Worker# CI build for SDK snapshots 46*924841ffSAndroid Build Coastguard WorkerSDK_SOURCE = BuildSource("aosp-main", 47*924841ffSAndroid Build Coastguard Worker "mainline_modules_sdks-trunk_staging-userdebug") 48*924841ffSAndroid Build Coastguard Worker 49*924841ffSAndroid Build Coastguard Worker# Architecture-specific CI builds for APEXes. These are only used in the chroot 50*924841ffSAndroid Build Coastguard Worker# test setup (see art/tools/buildbot-build.sh). They never become part of any 51*924841ffSAndroid Build Coastguard Worker# dist artifact. 52*924841ffSAndroid Build Coastguard Worker# 53*924841ffSAndroid Build Coastguard Worker# There are currently no CI builds except for x86_64, so APEX updates are 54*924841ffSAndroid Build Coastguard Worker# skipped by default. 55*924841ffSAndroid Build Coastguard WorkerAPEX_SOURCE = { 56*924841ffSAndroid Build Coastguard Worker "x86_64": BuildSource("aosp-main", 57*924841ffSAndroid Build Coastguard Worker "mainline_modules_x86_64-trunk_staging-userdebug"), 58*924841ffSAndroid Build Coastguard Worker} 59*924841ffSAndroid Build Coastguard Worker 60*924841ffSAndroid Build Coastguard Worker# Paths to git projects to prepare CLs in 61*924841ffSAndroid Build Coastguard WorkerGIT_PROJECT_ROOTS = [ 62*924841ffSAndroid Build Coastguard Worker "prebuilts/module_sdk/conscrypt", 63*924841ffSAndroid Build Coastguard Worker "prebuilts/runtime", 64*924841ffSAndroid Build Coastguard Worker] 65*924841ffSAndroid Build Coastguard Worker 66*924841ffSAndroid Build Coastguard WorkerSDK_VERSION = "current" 67*924841ffSAndroid Build Coastguard Worker 68*924841ffSAndroid Build Coastguard WorkerSCRIPT_PATH = "prebuilts/runtime/mainline/update.py" 69*924841ffSAndroid Build Coastguard Worker 70*924841ffSAndroid Build Coastguard Worker 71*924841ffSAndroid Build Coastguard WorkerInstallEntry = collections.namedtuple( 72*924841ffSAndroid Build Coastguard Worker "InstallEntry", 73*924841ffSAndroid Build Coastguard Worker [ 74*924841ffSAndroid Build Coastguard Worker # Either "apex" or "module_sdk", for the --skip-* flags. 75*924841ffSAndroid Build Coastguard Worker "type", 76*924841ffSAndroid Build Coastguard Worker # Source CI build as a BuildSource tuple, or None if none exists. 77*924841ffSAndroid Build Coastguard Worker "source_build", 78*924841ffSAndroid Build Coastguard Worker # Artifact path in the build, passed to fetch_target. Should match a 79*924841ffSAndroid Build Coastguard Worker # single file. "{BUILD}" gets replaced with the build number. 80*924841ffSAndroid Build Coastguard Worker "source_path", 81*924841ffSAndroid Build Coastguard Worker # Local install path. 82*924841ffSAndroid Build Coastguard Worker "install_path", 83*924841ffSAndroid Build Coastguard Worker # True if the entry is a zip file that should be unzipped to 84*924841ffSAndroid Build Coastguard Worker # install_path. 85*924841ffSAndroid Build Coastguard Worker "install_unzipped", 86*924841ffSAndroid Build Coastguard Worker # If set, the entry is a zip from which this single file is extracted to 87*924841ffSAndroid Build Coastguard Worker # install_path. 88*924841ffSAndroid Build Coastguard Worker "unzip_single_file", 89*924841ffSAndroid Build Coastguard Worker ], 90*924841ffSAndroid Build Coastguard Worker defaults=(False, None), # Defaults for install_unzipped and unzip_single_file. 91*924841ffSAndroid Build Coastguard Worker) 92*924841ffSAndroid Build Coastguard Worker 93*924841ffSAndroid Build Coastguard Worker 94*924841ffSAndroid Build Coastguard Workerdef install_apex_entries(module_name, apex_name): 95*924841ffSAndroid Build Coastguard Worker return [ 96*924841ffSAndroid Build Coastguard Worker InstallEntry( 97*924841ffSAndroid Build Coastguard Worker type="apex", 98*924841ffSAndroid Build Coastguard Worker source_build=APEX_SOURCE.get(arch, None), 99*924841ffSAndroid Build Coastguard Worker source_path=os.path.join( 100*924841ffSAndroid Build Coastguard Worker "mainline_modules_" + arch, 101*924841ffSAndroid Build Coastguard Worker apex_name + ".apex"), 102*924841ffSAndroid Build Coastguard Worker install_path=os.path.join( 103*924841ffSAndroid Build Coastguard Worker "prebuilts/runtime/mainline", 104*924841ffSAndroid Build Coastguard Worker module_name, 105*924841ffSAndroid Build Coastguard Worker "apex", 106*924841ffSAndroid Build Coastguard Worker apex_name + "-" + arch + ".apex")) 107*924841ffSAndroid Build Coastguard Worker for arch in ARCHES] 108*924841ffSAndroid Build Coastguard Worker 109*924841ffSAndroid Build Coastguard Worker 110*924841ffSAndroid Build Coastguard Workerdef install_unbundled_sdk_entries(apex_name, mainline_sdk_name, sdk_type, install_path): 111*924841ffSAndroid Build Coastguard Worker if "riscv64" in ARCHES: 112*924841ffSAndroid Build Coastguard Worker if sdk_type == "host-exports": # no host prebuilts for riscv64 113*924841ffSAndroid Build Coastguard Worker return [] 114*924841ffSAndroid Build Coastguard Worker install_path = os.path.join("prebuilts/runtime/mainline/local_riscv64", 115*924841ffSAndroid Build Coastguard Worker install_path) 116*924841ffSAndroid Build Coastguard Worker return [ 117*924841ffSAndroid Build Coastguard Worker InstallEntry( 118*924841ffSAndroid Build Coastguard Worker type="module_sdk", 119*924841ffSAndroid Build Coastguard Worker source_build=SDK_SOURCE, 120*924841ffSAndroid Build Coastguard Worker source_path=os.path.join( 121*924841ffSAndroid Build Coastguard Worker "mainline-sdks/for-latest-build", 122*924841ffSAndroid Build Coastguard Worker SDK_VERSION, 123*924841ffSAndroid Build Coastguard Worker apex_name, 124*924841ffSAndroid Build Coastguard Worker sdk_type, 125*924841ffSAndroid Build Coastguard Worker mainline_sdk_name + "-" + sdk_type + "-" + SDK_VERSION + ".zip"), 126*924841ffSAndroid Build Coastguard Worker install_path=install_path, 127*924841ffSAndroid Build Coastguard Worker install_unzipped=True)] 128*924841ffSAndroid Build Coastguard Worker 129*924841ffSAndroid Build Coastguard Worker 130*924841ffSAndroid Build Coastguard Workerdef install_bundled_sdk_entries(module_name, sdk_type): 131*924841ffSAndroid Build Coastguard Worker if "riscv64" in ARCHES: 132*924841ffSAndroid Build Coastguard Worker if sdk_type == "host-exports": # no host prebuilts for riscv64 133*924841ffSAndroid Build Coastguard Worker return [] 134*924841ffSAndroid Build Coastguard Worker return [ 135*924841ffSAndroid Build Coastguard Worker InstallEntry( 136*924841ffSAndroid Build Coastguard Worker type="module_sdk", 137*924841ffSAndroid Build Coastguard Worker source_build=SDK_SOURCE, 138*924841ffSAndroid Build Coastguard Worker source_path=os.path.join( 139*924841ffSAndroid Build Coastguard Worker "bundled-mainline-sdks", 140*924841ffSAndroid Build Coastguard Worker "com.android." + module_name, 141*924841ffSAndroid Build Coastguard Worker sdk_type, 142*924841ffSAndroid Build Coastguard Worker module_name + "-module-" + sdk_type + "-" + SDK_VERSION + ".zip"), 143*924841ffSAndroid Build Coastguard Worker install_path=os.path.join( 144*924841ffSAndroid Build Coastguard Worker "prebuilts/runtime/mainline", 145*924841ffSAndroid Build Coastguard Worker module_name, 146*924841ffSAndroid Build Coastguard Worker sdk_type), 147*924841ffSAndroid Build Coastguard Worker install_unzipped=True)] 148*924841ffSAndroid Build Coastguard Worker 149*924841ffSAndroid Build Coastguard Worker 150*924841ffSAndroid Build Coastguard Workerdef install_platform_mainline_sdk_entries(sdk_type): 151*924841ffSAndroid Build Coastguard Worker if "riscv64" in ARCHES: 152*924841ffSAndroid Build Coastguard Worker if sdk_type == "host-exports": # no host prebuilts for riscv64 153*924841ffSAndroid Build Coastguard Worker return [] 154*924841ffSAndroid Build Coastguard Worker return [ 155*924841ffSAndroid Build Coastguard Worker InstallEntry( 156*924841ffSAndroid Build Coastguard Worker type="module_sdk", 157*924841ffSAndroid Build Coastguard Worker source_build=SDK_SOURCE, 158*924841ffSAndroid Build Coastguard Worker source_path=os.path.join( 159*924841ffSAndroid Build Coastguard Worker "bundled-mainline-sdks", 160*924841ffSAndroid Build Coastguard Worker "platform-mainline", 161*924841ffSAndroid Build Coastguard Worker sdk_type, 162*924841ffSAndroid Build Coastguard Worker "platform-mainline-" + sdk_type + "-" + SDK_VERSION + ".zip"), 163*924841ffSAndroid Build Coastguard Worker install_path=os.path.join( 164*924841ffSAndroid Build Coastguard Worker "prebuilts/runtime/mainline/platform", 165*924841ffSAndroid Build Coastguard Worker sdk_type), 166*924841ffSAndroid Build Coastguard Worker install_unzipped=True)] 167*924841ffSAndroid Build Coastguard Worker 168*924841ffSAndroid Build Coastguard Worker 169*924841ffSAndroid Build Coastguard Worker# This is defined as a function (not a global list) because it depends on the 170*924841ffSAndroid Build Coastguard Worker# list of architectures, which may change after parsing options. 171*924841ffSAndroid Build Coastguard Workerdef install_entries(): 172*924841ffSAndroid Build Coastguard Worker return ( 173*924841ffSAndroid Build Coastguard Worker # Conscrypt 174*924841ffSAndroid Build Coastguard Worker install_apex_entries("conscrypt", "com.android.conscrypt") + 175*924841ffSAndroid Build Coastguard Worker install_unbundled_sdk_entries( 176*924841ffSAndroid Build Coastguard Worker "com.android.conscrypt", "conscrypt-module", "sdk", 177*924841ffSAndroid Build Coastguard Worker "prebuilts/module_sdk/conscrypt/current") + 178*924841ffSAndroid Build Coastguard Worker install_unbundled_sdk_entries( 179*924841ffSAndroid Build Coastguard Worker "com.android.conscrypt", "conscrypt-module", "test-exports", 180*924841ffSAndroid Build Coastguard Worker "prebuilts/module_sdk/conscrypt/current/test-exports") + 181*924841ffSAndroid Build Coastguard Worker install_unbundled_sdk_entries( 182*924841ffSAndroid Build Coastguard Worker "com.android.conscrypt", "conscrypt-module", "host-exports", 183*924841ffSAndroid Build Coastguard Worker "prebuilts/module_sdk/conscrypt/current/host-exports") + 184*924841ffSAndroid Build Coastguard Worker 185*924841ffSAndroid Build Coastguard Worker # Runtime (Bionic) 186*924841ffSAndroid Build Coastguard Worker # sdk and host-exports must always be updated together, because the linker 187*924841ffSAndroid Build Coastguard Worker # and the CRT object files gets embedded in the binaries on linux host 188*924841ffSAndroid Build Coastguard Worker # Bionic (see code and comments around host_bionic_linker_script in 189*924841ffSAndroid Build Coastguard Worker # build/soong). 190*924841ffSAndroid Build Coastguard Worker install_apex_entries("runtime", "com.android.runtime") + 191*924841ffSAndroid Build Coastguard Worker install_bundled_sdk_entries("runtime", "sdk") + 192*924841ffSAndroid Build Coastguard Worker install_bundled_sdk_entries("runtime", "host-exports") + 193*924841ffSAndroid Build Coastguard Worker 194*924841ffSAndroid Build Coastguard Worker # I18N 195*924841ffSAndroid Build Coastguard Worker install_apex_entries("i18n", "com.android.i18n") + 196*924841ffSAndroid Build Coastguard Worker install_bundled_sdk_entries("i18n", "sdk") + 197*924841ffSAndroid Build Coastguard Worker install_bundled_sdk_entries("i18n", "test-exports") + 198*924841ffSAndroid Build Coastguard Worker 199*924841ffSAndroid Build Coastguard Worker # tzdata 200*924841ffSAndroid Build Coastguard Worker install_apex_entries("tzdata", "com.android.tzdata") + 201*924841ffSAndroid Build Coastguard Worker install_bundled_sdk_entries("tzdata", "test-exports") + 202*924841ffSAndroid Build Coastguard Worker 203*924841ffSAndroid Build Coastguard Worker # Platform 204*924841ffSAndroid Build Coastguard Worker install_platform_mainline_sdk_entries("sdk") + 205*924841ffSAndroid Build Coastguard Worker install_platform_mainline_sdk_entries("test-exports") + 206*924841ffSAndroid Build Coastguard Worker 207*924841ffSAndroid Build Coastguard Worker []) 208*924841ffSAndroid Build Coastguard Worker 209*924841ffSAndroid Build Coastguard Worker 210*924841ffSAndroid Build Coastguard Workerdef check_call(cmd, **kwargs): 211*924841ffSAndroid Build Coastguard Worker """Proxy for subprocess.check_call with logging.""" 212*924841ffSAndroid Build Coastguard Worker msg = " ".join(cmd) if isinstance(cmd, list) else cmd 213*924841ffSAndroid Build Coastguard Worker if "cwd" in kwargs: 214*924841ffSAndroid Build Coastguard Worker msg = "In " + kwargs["cwd"] + ": " + msg 215*924841ffSAndroid Build Coastguard Worker print(msg) 216*924841ffSAndroid Build Coastguard Worker subprocess.check_call(cmd, **kwargs) 217*924841ffSAndroid Build Coastguard Worker 218*924841ffSAndroid Build Coastguard Worker 219*924841ffSAndroid Build Coastguard Workerdef fetch_artifact(branch, target, build, fetch_pattern, local_dir, zip_entry=None): 220*924841ffSAndroid Build Coastguard Worker """Fetches artifact from the build server.""" 221*924841ffSAndroid Build Coastguard Worker fetch_artifact_path = "/google/data/ro/projects/android/fetch_artifact" 222*924841ffSAndroid Build Coastguard Worker cmd = [fetch_artifact_path, "--branch", branch, "--target", target, 223*924841ffSAndroid Build Coastguard Worker "--bid", build, fetch_pattern] 224*924841ffSAndroid Build Coastguard Worker if zip_entry: 225*924841ffSAndroid Build Coastguard Worker cmd += ["--zip_entry", zip_entry] 226*924841ffSAndroid Build Coastguard Worker check_call(cmd, cwd=local_dir) 227*924841ffSAndroid Build Coastguard Worker 228*924841ffSAndroid Build Coastguard Worker 229*924841ffSAndroid Build Coastguard Workerdef start_branch(git_branch_name, git_dirs): 230*924841ffSAndroid Build Coastguard Worker """Creates a new repo branch in the given projects.""" 231*924841ffSAndroid Build Coastguard Worker check_call(["repo", "start", git_branch_name] + git_dirs) 232*924841ffSAndroid Build Coastguard Worker # In case the branch already exists we reset it to upstream, to get a clean 233*924841ffSAndroid Build Coastguard Worker # update CL. 234*924841ffSAndroid Build Coastguard Worker for git_dir in git_dirs: 235*924841ffSAndroid Build Coastguard Worker check_call(["git", "reset", "--hard", "@{upstream}"], cwd=git_dir) 236*924841ffSAndroid Build Coastguard Worker 237*924841ffSAndroid Build Coastguard Worker 238*924841ffSAndroid Build Coastguard Workerdef upload_branch(git_root, git_branch_name): 239*924841ffSAndroid Build Coastguard Worker """Uploads the CLs in the given branch in the given project.""" 240*924841ffSAndroid Build Coastguard Worker # Set the branch as topic to bundle with the CLs in other git projects (if 241*924841ffSAndroid Build Coastguard Worker # any). 242*924841ffSAndroid Build Coastguard Worker check_call(["repo", "upload", "-t", "--br=" + git_branch_name, git_root]) 243*924841ffSAndroid Build Coastguard Worker 244*924841ffSAndroid Build Coastguard Worker 245*924841ffSAndroid Build Coastguard Workerdef remove_files(git_root, subpaths, stage_removals): 246*924841ffSAndroid Build Coastguard Worker """Removes files in the work tree, optionally staging them in git.""" 247*924841ffSAndroid Build Coastguard Worker if stage_removals: 248*924841ffSAndroid Build Coastguard Worker check_call(["git", "rm", "-qrf", "--ignore-unmatch"] + subpaths, cwd=git_root) 249*924841ffSAndroid Build Coastguard Worker # Need a plain rm afterwards even if git rm was executed, because git won't 250*924841ffSAndroid Build Coastguard Worker # remove directories if they have non-git files in them. 251*924841ffSAndroid Build Coastguard Worker check_call(["rm", "-rf"] + subpaths, cwd=git_root) 252*924841ffSAndroid Build Coastguard Worker 253*924841ffSAndroid Build Coastguard Worker 254*924841ffSAndroid Build Coastguard Workerdef commit(git_root, prebuilt_descr, installed_sources, add_paths, bug_number): 255*924841ffSAndroid Build Coastguard Worker """Commits the new prebuilts.""" 256*924841ffSAndroid Build Coastguard Worker check_call(["git", "add"] + 257*924841ffSAndroid Build Coastguard Worker [path for path in add_paths 258*924841ffSAndroid Build Coastguard Worker if os.path.exists(os.path.join(git_root, path))], 259*924841ffSAndroid Build Coastguard Worker cwd=git_root) 260*924841ffSAndroid Build Coastguard Worker 261*924841ffSAndroid Build Coastguard Worker if installed_sources: 262*924841ffSAndroid Build Coastguard Worker message = "Update {} prebuilts.\n\n".format(prebuilt_descr) 263*924841ffSAndroid Build Coastguard Worker if len(installed_sources) == 1: 264*924841ffSAndroid Build Coastguard Worker message += "Taken from {}.".format(installed_sources[0]) 265*924841ffSAndroid Build Coastguard Worker else: 266*924841ffSAndroid Build Coastguard Worker message += "Taken from:\n{}".format( 267*924841ffSAndroid Build Coastguard Worker "\n".join([s.capitalize() for s in installed_sources])) 268*924841ffSAndroid Build Coastguard Worker else: 269*924841ffSAndroid Build Coastguard Worker # For riscv64, update from a local tree is the only available option. 270*924841ffSAndroid Build Coastguard Worker message = "" if "riscv64" in ARCHES else "DO NOT SUBMIT: " 271*924841ffSAndroid Build Coastguard Worker message += ( 272*924841ffSAndroid Build Coastguard Worker "Update {prebuilt_descr} prebuilts from local build." 273*924841ffSAndroid Build Coastguard Worker .format(prebuilt_descr=prebuilt_descr)) 274*924841ffSAndroid Build Coastguard Worker message += ("\n\nCL prepared by {}." 275*924841ffSAndroid Build Coastguard Worker "\n\nTest: Presubmits".format(SCRIPT_PATH)) 276*924841ffSAndroid Build Coastguard Worker if bug_number: 277*924841ffSAndroid Build Coastguard Worker message += ("\nBug: {}".format(bug_number)) 278*924841ffSAndroid Build Coastguard Worker 279*924841ffSAndroid Build Coastguard Worker msg_fd, msg_path = tempfile.mkstemp() 280*924841ffSAndroid Build Coastguard Worker try: 281*924841ffSAndroid Build Coastguard Worker with os.fdopen(msg_fd, "w") as f: 282*924841ffSAndroid Build Coastguard Worker f.write(message) 283*924841ffSAndroid Build Coastguard Worker # Do a diff first to skip the commit without error if there are no changes 284*924841ffSAndroid Build Coastguard Worker # to commit. 285*924841ffSAndroid Build Coastguard Worker check_call("git diff-index --quiet --cached HEAD -- || " 286*924841ffSAndroid Build Coastguard Worker "git commit -F " + msg_path, shell=True, cwd=git_root) 287*924841ffSAndroid Build Coastguard Worker finally: 288*924841ffSAndroid Build Coastguard Worker os.unlink(msg_path) 289*924841ffSAndroid Build Coastguard Worker 290*924841ffSAndroid Build Coastguard Worker 291*924841ffSAndroid Build Coastguard Workerdef install_entry(tmp_dir, local_dist, build_numbers, entry): 292*924841ffSAndroid Build Coastguard Worker """Installs one file specified by entry.""" 293*924841ffSAndroid Build Coastguard Worker 294*924841ffSAndroid Build Coastguard Worker if not local_dist and not entry.source_build: 295*924841ffSAndroid Build Coastguard Worker print("WARNING: No CI build for {} - skipping.".format(entry.source_path)) 296*924841ffSAndroid Build Coastguard Worker return None 297*924841ffSAndroid Build Coastguard Worker 298*924841ffSAndroid Build Coastguard Worker build_number = (build_numbers[entry.source_build.branch] 299*924841ffSAndroid Build Coastguard Worker if build_numbers else None) 300*924841ffSAndroid Build Coastguard Worker 301*924841ffSAndroid Build Coastguard Worker # Fall back to the username as the build ID if we have no build number. That's 302*924841ffSAndroid Build Coastguard Worker # what a dist install does in a local build. 303*924841ffSAndroid Build Coastguard Worker source_path = entry.source_path.replace( 304*924841ffSAndroid Build Coastguard Worker "{BUILD}", str(build_number) if build_number else os.getenv("USER")) 305*924841ffSAndroid Build Coastguard Worker 306*924841ffSAndroid Build Coastguard Worker source_dir, source_file = os.path.split(source_path) 307*924841ffSAndroid Build Coastguard Worker 308*924841ffSAndroid Build Coastguard Worker if local_dist: 309*924841ffSAndroid Build Coastguard Worker download_dir = os.path.join(tmp_dir, source_dir) 310*924841ffSAndroid Build Coastguard Worker else: 311*924841ffSAndroid Build Coastguard Worker download_dir = os.path.join(tmp_dir, 312*924841ffSAndroid Build Coastguard Worker entry.source_build.branch, 313*924841ffSAndroid Build Coastguard Worker build_number, 314*924841ffSAndroid Build Coastguard Worker entry.source_build.target, 315*924841ffSAndroid Build Coastguard Worker source_dir) 316*924841ffSAndroid Build Coastguard Worker os.makedirs(download_dir, exist_ok=True) 317*924841ffSAndroid Build Coastguard Worker download_file = os.path.join(download_dir, source_file) 318*924841ffSAndroid Build Coastguard Worker 319*924841ffSAndroid Build Coastguard Worker unzip_dir = None 320*924841ffSAndroid Build Coastguard Worker unzip_file = None 321*924841ffSAndroid Build Coastguard Worker if entry.unzip_single_file: 322*924841ffSAndroid Build Coastguard Worker unzip_dir = os.path.join(download_dir, 323*924841ffSAndroid Build Coastguard Worker source_path.removesuffix(".zip") + "_unzip") 324*924841ffSAndroid Build Coastguard Worker os.makedirs(unzip_dir, exist_ok=True) 325*924841ffSAndroid Build Coastguard Worker unzip_file = os.path.join(unzip_dir, entry.unzip_single_file) 326*924841ffSAndroid Build Coastguard Worker 327*924841ffSAndroid Build Coastguard Worker if not local_dist and unzip_file: 328*924841ffSAndroid Build Coastguard Worker if not os.path.exists(unzip_file): 329*924841ffSAndroid Build Coastguard Worker # Use the --zip_entry option to fetch_artifact to avoid downloading the 330*924841ffSAndroid Build Coastguard Worker # whole zip. 331*924841ffSAndroid Build Coastguard Worker fetch_artifact(entry.source_build.branch, 332*924841ffSAndroid Build Coastguard Worker entry.source_build.target, 333*924841ffSAndroid Build Coastguard Worker build_number, 334*924841ffSAndroid Build Coastguard Worker source_path, 335*924841ffSAndroid Build Coastguard Worker unzip_dir, 336*924841ffSAndroid Build Coastguard Worker entry.unzip_single_file) 337*924841ffSAndroid Build Coastguard Worker if not os.path.exists(unzip_file): 338*924841ffSAndroid Build Coastguard Worker sys.exit("fetch_artifact didn't create expected file {}".format(unzip_file)) 339*924841ffSAndroid Build Coastguard Worker else: 340*924841ffSAndroid Build Coastguard Worker # Fetch files once by downloading them into a specific location in tmp_dir 341*924841ffSAndroid Build Coastguard Worker # only if they're not already there. 342*924841ffSAndroid Build Coastguard Worker if not os.path.exists(download_file): 343*924841ffSAndroid Build Coastguard Worker if local_dist: 344*924841ffSAndroid Build Coastguard Worker check_call(["cp", os.path.join(local_dist, source_path), download_dir]) 345*924841ffSAndroid Build Coastguard Worker else: 346*924841ffSAndroid Build Coastguard Worker fetch_artifact(entry.source_build.branch, 347*924841ffSAndroid Build Coastguard Worker entry.source_build.target, 348*924841ffSAndroid Build Coastguard Worker build_number, 349*924841ffSAndroid Build Coastguard Worker source_path, 350*924841ffSAndroid Build Coastguard Worker download_dir) 351*924841ffSAndroid Build Coastguard Worker if not os.path.exists(download_file): 352*924841ffSAndroid Build Coastguard Worker sys.exit("Failed to retrieve {}".format(source_path)) 353*924841ffSAndroid Build Coastguard Worker 354*924841ffSAndroid Build Coastguard Worker install_dir, install_file = os.path.split(entry.install_path) 355*924841ffSAndroid Build Coastguard Worker os.makedirs(install_dir, exist_ok=True) 356*924841ffSAndroid Build Coastguard Worker 357*924841ffSAndroid Build Coastguard Worker if entry.install_unzipped: 358*924841ffSAndroid Build Coastguard Worker if "riscv64" in ARCHES: 359*924841ffSAndroid Build Coastguard Worker tmp_dir = os.path.join(install_file, "tmp") 360*924841ffSAndroid Build Coastguard Worker check_call(["mkdir", "-p", tmp_dir], cwd=install_dir) 361*924841ffSAndroid Build Coastguard Worker check_call(["unzip", "-DD", "-o", download_file, "-d", tmp_dir], 362*924841ffSAndroid Build Coastguard Worker cwd=install_dir) 363*924841ffSAndroid Build Coastguard Worker # Conscrypt is not owned by the ART team, so we keep a local copy of its 364*924841ffSAndroid Build Coastguard Worker # prebuilt with Android.bp files renamed to ArtThinBuild.bp to avoid Soong 365*924841ffSAndroid Build Coastguard Worker # adding them as part of the build graph. 366*924841ffSAndroid Build Coastguard Worker if "local_riscv64" in install_dir: 367*924841ffSAndroid Build Coastguard Worker patch_cmd = ("sed -i 's|This is auto-generated. DO NOT EDIT.|" 368*924841ffSAndroid Build Coastguard Worker "DO NOT COMMIT. Changes in this file are temporary and generated " 369*924841ffSAndroid Build Coastguard Worker "by art/tools/buildbot-build.sh. See b/286551985.|g' {} ; ") 370*924841ffSAndroid Build Coastguard Worker rename_cmd = 'f="{}" ; mv "$f" "$(dirname $f)"/ArtThinBuild.bp' 371*924841ffSAndroid Build Coastguard Worker check_call(["find", "-type", "f", "-name", "Android.bp", 372*924841ffSAndroid Build Coastguard Worker "-exec", "sh", "-c", patch_cmd + rename_cmd, ";"], 373*924841ffSAndroid Build Coastguard Worker cwd=os.path.join(install_dir, tmp_dir)) 374*924841ffSAndroid Build Coastguard Worker check_call(["find", "-type", "f", "-regextype", "posix-extended", 375*924841ffSAndroid Build Coastguard Worker "-regex", ".*riscv64.*|.*Android.bp|.*ArtThinBuild.bp", 376*924841ffSAndroid Build Coastguard Worker "-exec", "cp", "--parents", "{}", "..", ";"], 377*924841ffSAndroid Build Coastguard Worker cwd=os.path.join(install_dir, tmp_dir)) 378*924841ffSAndroid Build Coastguard Worker check_call(["rm", "-rf", tmp_dir], cwd=install_dir) 379*924841ffSAndroid Build Coastguard Worker else: 380*924841ffSAndroid Build Coastguard Worker check_call(["mkdir", install_file], cwd=install_dir) 381*924841ffSAndroid Build Coastguard Worker # Add -DD to not extract timestamps that may confuse the build system. 382*924841ffSAndroid Build Coastguard Worker check_call(["unzip", "-DD", download_file, "-d", install_file], 383*924841ffSAndroid Build Coastguard Worker cwd=install_dir) 384*924841ffSAndroid Build Coastguard Worker elif entry.unzip_single_file: 385*924841ffSAndroid Build Coastguard Worker if not os.path.exists(unzip_file): 386*924841ffSAndroid Build Coastguard Worker check_call(["unzip", download_file, "-d", unzip_dir, entry.unzip_single_file]) 387*924841ffSAndroid Build Coastguard Worker check_call(["cp", unzip_file, install_file], cwd=install_dir) 388*924841ffSAndroid Build Coastguard Worker else: 389*924841ffSAndroid Build Coastguard Worker check_call(["cp", download_file, install_file], cwd=install_dir) 390*924841ffSAndroid Build Coastguard Worker 391*924841ffSAndroid Build Coastguard Worker # Return a description of the source location for inclusion in the commit 392*924841ffSAndroid Build Coastguard Worker # message. 393*924841ffSAndroid Build Coastguard Worker return ( 394*924841ffSAndroid Build Coastguard Worker "branch {}, target {}, build {}".format( 395*924841ffSAndroid Build Coastguard Worker entry.source_build.branch, 396*924841ffSAndroid Build Coastguard Worker entry.source_build.target, 397*924841ffSAndroid Build Coastguard Worker build_number) 398*924841ffSAndroid Build Coastguard Worker if not local_dist else None) 399*924841ffSAndroid Build Coastguard Worker 400*924841ffSAndroid Build Coastguard Worker 401*924841ffSAndroid Build Coastguard Workerdef install_paths_per_git_root(roots, paths): 402*924841ffSAndroid Build Coastguard Worker """Partitions the given paths into subpaths within the given roots. 403*924841ffSAndroid Build Coastguard Worker 404*924841ffSAndroid Build Coastguard Worker Args: 405*924841ffSAndroid Build Coastguard Worker roots: List of root paths. 406*924841ffSAndroid Build Coastguard Worker paths: List of paths relative to the same directory as the root paths. 407*924841ffSAndroid Build Coastguard Worker 408*924841ffSAndroid Build Coastguard Worker Returns: 409*924841ffSAndroid Build Coastguard Worker A dict mapping each root to the subpaths under it. It's an error if some 410*924841ffSAndroid Build Coastguard Worker path doesn't go into any root. 411*924841ffSAndroid Build Coastguard Worker """ 412*924841ffSAndroid Build Coastguard Worker res = collections.defaultdict(list) 413*924841ffSAndroid Build Coastguard Worker for path in paths: 414*924841ffSAndroid Build Coastguard Worker found = False 415*924841ffSAndroid Build Coastguard Worker for root in roots: 416*924841ffSAndroid Build Coastguard Worker if path.startswith(root + "/"): 417*924841ffSAndroid Build Coastguard Worker res[root].append(path[len(root) + 1:]) 418*924841ffSAndroid Build Coastguard Worker found = True 419*924841ffSAndroid Build Coastguard Worker break 420*924841ffSAndroid Build Coastguard Worker if not found: 421*924841ffSAndroid Build Coastguard Worker sys.exit("Install path {} is not in any of the git roots: {}" 422*924841ffSAndroid Build Coastguard Worker .format(path, " ".join(roots))) 423*924841ffSAndroid Build Coastguard Worker return res 424*924841ffSAndroid Build Coastguard Worker 425*924841ffSAndroid Build Coastguard Worker 426*924841ffSAndroid Build Coastguard Workerdef get_args(): 427*924841ffSAndroid Build Coastguard Worker need_aosp_main_throttled = any( 428*924841ffSAndroid Build Coastguard Worker source is not None and source.branch == "aosp-main-throttled" 429*924841ffSAndroid Build Coastguard Worker for source in ([SDK_SOURCE] + list(APEX_SOURCE.values()))) 430*924841ffSAndroid Build Coastguard Worker if need_aosp_main_throttled: 431*924841ffSAndroid Build Coastguard Worker epilog="Either --aosp-main-build and --aosp-main-throttled-build, or --local-dist, is required." 432*924841ffSAndroid Build Coastguard Worker else: 433*924841ffSAndroid Build Coastguard Worker epilog="Either --aosp-main-build or --local-dist is required." 434*924841ffSAndroid Build Coastguard Worker 435*924841ffSAndroid Build Coastguard Worker """Parses and returns command line arguments.""" 436*924841ffSAndroid Build Coastguard Worker parser = argparse.ArgumentParser(epilog=epilog) 437*924841ffSAndroid Build Coastguard Worker 438*924841ffSAndroid Build Coastguard Worker parser.add_argument("--aosp-main-build", metavar="NUMBER", 439*924841ffSAndroid Build Coastguard Worker help="Build number to fetch from aosp-main") 440*924841ffSAndroid Build Coastguard Worker parser.add_argument("--aosp-main-throttled-build", metavar="NUMBER", 441*924841ffSAndroid Build Coastguard Worker help="Build number to fetch from aosp-main-throttled") 442*924841ffSAndroid Build Coastguard Worker parser.add_argument("--local-dist", metavar="PATH", 443*924841ffSAndroid Build Coastguard Worker help="Take prebuilts from this local dist dir instead of " 444*924841ffSAndroid Build Coastguard Worker "using fetch_artifact") 445*924841ffSAndroid Build Coastguard Worker parser.add_argument("--local-dist-riscv64", metavar="PATH", 446*924841ffSAndroid Build Coastguard Worker help="Copy riscv64 prebuilts from a local path, which " 447*924841ffSAndroid Build Coastguard Worker "must be $HOME/<path-to-aosp-root>/out/dist with prebuilts " 448*924841ffSAndroid Build Coastguard Worker "already built for aosp_riscv64-trunk_staging-userdebug " 449*924841ffSAndroid Build Coastguard Worker "target as described in README_riscv64.md. Only " 450*924841ffSAndroid Build Coastguard Worker "riscv64-specific files and Android.bp are updated.") 451*924841ffSAndroid Build Coastguard Worker parser.add_argument("--skip-apex", default=True, 452*924841ffSAndroid Build Coastguard Worker action=argparse.BooleanOptionalAction, 453*924841ffSAndroid Build Coastguard Worker help="Do not fetch .apex files.") 454*924841ffSAndroid Build Coastguard Worker parser.add_argument("--skip-module-sdk", action="store_true", 455*924841ffSAndroid Build Coastguard Worker help="Do not fetch and unpack sdk and module_export zips.") 456*924841ffSAndroid Build Coastguard Worker parser.add_argument("--skip-cls", action="store_true", 457*924841ffSAndroid Build Coastguard Worker help="Do not create branches or git commits") 458*924841ffSAndroid Build Coastguard Worker parser.add_argument("--bug", metavar="NUMBER", 459*924841ffSAndroid Build Coastguard Worker help="Add a 'Bug' line with this number to commit " 460*924841ffSAndroid Build Coastguard Worker "messages.") 461*924841ffSAndroid Build Coastguard Worker parser.add_argument("--upload", action="store_true", 462*924841ffSAndroid Build Coastguard Worker help="Upload the CLs to Gerrit") 463*924841ffSAndroid Build Coastguard Worker parser.add_argument("--tmp-dir", metavar="PATH", 464*924841ffSAndroid Build Coastguard Worker help="Temporary directory for downloads. The default is " 465*924841ffSAndroid Build Coastguard Worker "to create one and delete it when finished, but this one " 466*924841ffSAndroid Build Coastguard Worker "will be kept, and any files already in it won't be " 467*924841ffSAndroid Build Coastguard Worker "downloaded again.") 468*924841ffSAndroid Build Coastguard Worker 469*924841ffSAndroid Build Coastguard Worker args = parser.parse_args() 470*924841ffSAndroid Build Coastguard Worker 471*924841ffSAndroid Build Coastguard Worker if args.local_dist_riscv64: 472*924841ffSAndroid Build Coastguard Worker global ARCHES 473*924841ffSAndroid Build Coastguard Worker ARCHES = ["riscv64"] 474*924841ffSAndroid Build Coastguard Worker args.local_dist = args.local_dist_riscv64 475*924841ffSAndroid Build Coastguard Worker 476*924841ffSAndroid Build Coastguard Worker got_build_numbers = bool(args.aosp_main_build and 477*924841ffSAndroid Build Coastguard Worker (args.aosp_main_throttled_build or not need_aosp_main_throttled)) 478*924841ffSAndroid Build Coastguard Worker if ((not got_build_numbers and not args.local_dist) or 479*924841ffSAndroid Build Coastguard Worker (got_build_numbers and args.local_dist)): 480*924841ffSAndroid Build Coastguard Worker sys.exit(parser.format_help()) 481*924841ffSAndroid Build Coastguard Worker 482*924841ffSAndroid Build Coastguard Worker return args 483*924841ffSAndroid Build Coastguard Worker 484*924841ffSAndroid Build Coastguard Worker 485*924841ffSAndroid Build Coastguard Workerdef main(): 486*924841ffSAndroid Build Coastguard Worker """Program entry point.""" 487*924841ffSAndroid Build Coastguard Worker args = get_args() 488*924841ffSAndroid Build Coastguard Worker 489*924841ffSAndroid Build Coastguard Worker if any(path for path in GIT_PROJECT_ROOTS if not os.path.exists(path)): 490*924841ffSAndroid Build Coastguard Worker sys.exit("This script must be run in the root of the Android build tree.") 491*924841ffSAndroid Build Coastguard Worker 492*924841ffSAndroid Build Coastguard Worker build_numbers = None 493*924841ffSAndroid Build Coastguard Worker if args.aosp_main_build: 494*924841ffSAndroid Build Coastguard Worker build_numbers = { 495*924841ffSAndroid Build Coastguard Worker "aosp-main": args.aosp_main_build, 496*924841ffSAndroid Build Coastguard Worker "aosp-main-throttled": args.aosp_main_throttled_build, 497*924841ffSAndroid Build Coastguard Worker } 498*924841ffSAndroid Build Coastguard Worker 499*924841ffSAndroid Build Coastguard Worker entries = install_entries() 500*924841ffSAndroid Build Coastguard Worker 501*924841ffSAndroid Build Coastguard Worker if args.skip_apex: 502*924841ffSAndroid Build Coastguard Worker entries = [entry for entry in entries if entry.type != "apex"] 503*924841ffSAndroid Build Coastguard Worker if args.skip_module_sdk: 504*924841ffSAndroid Build Coastguard Worker entries = [entry for entry in entries if entry.type != "module_sdk"] 505*924841ffSAndroid Build Coastguard Worker if not entries: 506*924841ffSAndroid Build Coastguard Worker sys.exit("All prebuilts skipped - nothing to do.") 507*924841ffSAndroid Build Coastguard Worker 508*924841ffSAndroid Build Coastguard Worker install_paths = [entry.install_path for entry in entries] 509*924841ffSAndroid Build Coastguard Worker install_paths_per_root = install_paths_per_git_root( 510*924841ffSAndroid Build Coastguard Worker GIT_PROJECT_ROOTS, install_paths) 511*924841ffSAndroid Build Coastguard Worker 512*924841ffSAndroid Build Coastguard Worker git_branch_name = PREBUILT_DESCR.lower().replace(" ", "-") + "-update" 513*924841ffSAndroid Build Coastguard Worker if args.aosp_main_build: 514*924841ffSAndroid Build Coastguard Worker git_branch_name += "-" + args.aosp_main_build 515*924841ffSAndroid Build Coastguard Worker 516*924841ffSAndroid Build Coastguard Worker if not args.skip_cls: 517*924841ffSAndroid Build Coastguard Worker git_paths = list(install_paths_per_root.keys()) 518*924841ffSAndroid Build Coastguard Worker start_branch(git_branch_name, git_paths) 519*924841ffSAndroid Build Coastguard Worker 520*924841ffSAndroid Build Coastguard Worker if not args.local_dist_riscv64: 521*924841ffSAndroid Build Coastguard Worker for git_root, subpaths in install_paths_per_root.items(): 522*924841ffSAndroid Build Coastguard Worker remove_files(git_root, subpaths, not args.skip_cls) 523*924841ffSAndroid Build Coastguard Worker 524*924841ffSAndroid Build Coastguard Worker all_installed_sources = {} 525*924841ffSAndroid Build Coastguard Worker 526*924841ffSAndroid Build Coastguard Worker tmp_dir_obj = None 527*924841ffSAndroid Build Coastguard Worker tmp_dir = args.tmp_dir 528*924841ffSAndroid Build Coastguard Worker if not args.tmp_dir: 529*924841ffSAndroid Build Coastguard Worker tmp_dir_obj = tempfile.TemporaryDirectory() 530*924841ffSAndroid Build Coastguard Worker tmp_dir = tmp_dir_obj.name 531*924841ffSAndroid Build Coastguard Worker tmp_dir = os.path.abspath(tmp_dir) 532*924841ffSAndroid Build Coastguard Worker try: 533*924841ffSAndroid Build Coastguard Worker for entry in entries: 534*924841ffSAndroid Build Coastguard Worker installed_source = install_entry( 535*924841ffSAndroid Build Coastguard Worker tmp_dir, args.local_dist, build_numbers, entry) 536*924841ffSAndroid Build Coastguard Worker if installed_source: 537*924841ffSAndroid Build Coastguard Worker all_installed_sources[entry.install_path] = installed_source 538*924841ffSAndroid Build Coastguard Worker finally: 539*924841ffSAndroid Build Coastguard Worker if tmp_dir_obj: 540*924841ffSAndroid Build Coastguard Worker tmp_dir_obj.cleanup() 541*924841ffSAndroid Build Coastguard Worker 542*924841ffSAndroid Build Coastguard Worker if not args.skip_cls: 543*924841ffSAndroid Build Coastguard Worker for git_root, subpaths in install_paths_per_root.items(): 544*924841ffSAndroid Build Coastguard Worker installed_sources = set(src for path, src in all_installed_sources.items() 545*924841ffSAndroid Build Coastguard Worker if path.startswith(git_root + "/")) 546*924841ffSAndroid Build Coastguard Worker commit(git_root, PREBUILT_DESCR, sorted(list(installed_sources)), 547*924841ffSAndroid Build Coastguard Worker subpaths, args.bug) 548*924841ffSAndroid Build Coastguard Worker 549*924841ffSAndroid Build Coastguard Worker if args.upload: 550*924841ffSAndroid Build Coastguard Worker # Don't upload all projects in a single repo upload call, because that 551*924841ffSAndroid Build Coastguard Worker # makes it pop up an interactive editor. 552*924841ffSAndroid Build Coastguard Worker for git_root in install_paths_per_root: 553*924841ffSAndroid Build Coastguard Worker upload_branch(git_root, git_branch_name) 554*924841ffSAndroid Build Coastguard Worker 555*924841ffSAndroid Build Coastguard Worker 556*924841ffSAndroid Build Coastguard Workerif __name__ == "__main__": 557*924841ffSAndroid Build Coastguard Worker main() 558