1*90c8c64dSAndroid Build Coastguard Worker# 2*90c8c64dSAndroid Build Coastguard Worker# Copyright (C) 2021 The Android Open Source Project 3*90c8c64dSAndroid Build Coastguard Worker# 4*90c8c64dSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*90c8c64dSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*90c8c64dSAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*90c8c64dSAndroid Build Coastguard Worker# 8*90c8c64dSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*90c8c64dSAndroid Build Coastguard Worker# 10*90c8c64dSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*90c8c64dSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*90c8c64dSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*90c8c64dSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*90c8c64dSAndroid Build Coastguard Worker# limitations under the License. 15*90c8c64dSAndroid Build Coastguard Worker# 16*90c8c64dSAndroid Build Coastguard Worker"""Tool for updating the prebuilt NDK ABI dumps.""" 17*90c8c64dSAndroid Build Coastguard Workerimport argparse 18*90c8c64dSAndroid Build Coastguard Workerimport logging 19*90c8c64dSAndroid Build Coastguard Workerfrom pathlib import Path 20*90c8c64dSAndroid Build Coastguard Workerimport shutil 21*90c8c64dSAndroid Build Coastguard Workerimport sys 22*90c8c64dSAndroid Build Coastguard Worker 23*90c8c64dSAndroid Build Coastguard Workerfrom .soong import Soong 24*90c8c64dSAndroid Build Coastguard Worker 25*90c8c64dSAndroid Build Coastguard Worker 26*90c8c64dSAndroid Build Coastguard Workerdef logger() -> logging.Logger: 27*90c8c64dSAndroid Build Coastguard Worker """Returns the module level logger.""" 28*90c8c64dSAndroid Build Coastguard Worker return logging.getLogger(__name__) 29*90c8c64dSAndroid Build Coastguard Worker 30*90c8c64dSAndroid Build Coastguard Worker 31*90c8c64dSAndroid Build Coastguard Workerclass Updater: 32*90c8c64dSAndroid Build Coastguard Worker """Tool for updating prebuilt NDK ABI dumps.""" 33*90c8c64dSAndroid Build Coastguard Worker 34*90c8c64dSAndroid Build Coastguard Worker def __init__(self, src_dir: Path, build_dir: Path) -> None: 35*90c8c64dSAndroid Build Coastguard Worker self.src_dir = src_dir 36*90c8c64dSAndroid Build Coastguard Worker self.build_dir = build_dir 37*90c8c64dSAndroid Build Coastguard Worker 38*90c8c64dSAndroid Build Coastguard Worker def build_abi_dumps(self) -> None: 39*90c8c64dSAndroid Build Coastguard Worker """Builds the updated NDK ABI dumps.""" 40*90c8c64dSAndroid Build Coastguard Worker soong = Soong(self.src_dir, self.build_dir) 41*90c8c64dSAndroid Build Coastguard Worker logger().info(f"Building ABI dumps to {self.build_dir}") 42*90c8c64dSAndroid Build Coastguard Worker soong.build( 43*90c8c64dSAndroid Build Coastguard Worker ["dump-ndk-abi"], 44*90c8c64dSAndroid Build Coastguard Worker env={ 45*90c8c64dSAndroid Build Coastguard Worker "TARGET_PRODUCT": "ndk", 46*90c8c64dSAndroid Build Coastguard Worker "TARGET_RELEASE": "trunk_staging", 47*90c8c64dSAndroid Build Coastguard Worker # TODO: remove ALLOW_MISSING_DEPENDENCIES=true when all the 48*90c8c64dSAndroid Build Coastguard Worker # riscv64 dependencies exist (currently blocked by 49*90c8c64dSAndroid Build Coastguard Worker # http://b/273792258). 50*90c8c64dSAndroid Build Coastguard Worker "ALLOW_MISSING_DEPENDENCIES": "true", 51*90c8c64dSAndroid Build Coastguard Worker # TODO: remove BUILD_BROKEN_DISABLE_BAZEL=1 when bazel supports 52*90c8c64dSAndroid Build Coastguard Worker # riscv64 (http://b/262192655). 53*90c8c64dSAndroid Build Coastguard Worker "BUILD_BROKEN_DISABLE_BAZEL": "1", 54*90c8c64dSAndroid Build Coastguard Worker }, 55*90c8c64dSAndroid Build Coastguard Worker ) 56*90c8c64dSAndroid Build Coastguard Worker 57*90c8c64dSAndroid Build Coastguard Worker def copy_updated_abi_dumps(self) -> None: 58*90c8c64dSAndroid Build Coastguard Worker """Copies the NDK ABI dumps from the build directory to prebuilts.""" 59*90c8c64dSAndroid Build Coastguard Worker prebuilts_project = self.src_dir / "prebuilts/abi-dumps" 60*90c8c64dSAndroid Build Coastguard Worker prebuilts_dir = prebuilts_project / "ndk" 61*90c8c64dSAndroid Build Coastguard Worker abi_out = self.build_dir / "soong/abi-dumps/ndk" 62*90c8c64dSAndroid Build Coastguard Worker for version_dir in abi_out.iterdir(): 63*90c8c64dSAndroid Build Coastguard Worker try: 64*90c8c64dSAndroid Build Coastguard Worker int(version_dir.name) 65*90c8c64dSAndroid Build Coastguard Worker except ValueError: 66*90c8c64dSAndroid Build Coastguard Worker logger().info("Skipping %s because it is a preview API level", version_dir) 67*90c8c64dSAndroid Build Coastguard Worker continue 68*90c8c64dSAndroid Build Coastguard Worker 69*90c8c64dSAndroid Build Coastguard Worker for dump in version_dir.glob("**/abi.stg"): 70*90c8c64dSAndroid Build Coastguard Worker install_path = prebuilts_dir / dump.relative_to(abi_out) 71*90c8c64dSAndroid Build Coastguard Worker install_dir = install_path.parent 72*90c8c64dSAndroid Build Coastguard Worker if not install_dir.exists(): 73*90c8c64dSAndroid Build Coastguard Worker install_dir.mkdir(parents=True) 74*90c8c64dSAndroid Build Coastguard Worker logger().info(f"Copying ABI dump {dump} to {install_path}") 75*90c8c64dSAndroid Build Coastguard Worker shutil.copy2(dump, install_path) 76*90c8c64dSAndroid Build Coastguard Worker 77*90c8c64dSAndroid Build Coastguard Worker def run(self) -> None: 78*90c8c64dSAndroid Build Coastguard Worker """Runs the updater. 79*90c8c64dSAndroid Build Coastguard Worker 80*90c8c64dSAndroid Build Coastguard Worker Cleans the out directory, builds the ABI dumps, and copies the results 81*90c8c64dSAndroid Build Coastguard Worker to the prebuilts directory. 82*90c8c64dSAndroid Build Coastguard Worker """ 83*90c8c64dSAndroid Build Coastguard Worker self.build_abi_dumps() 84*90c8c64dSAndroid Build Coastguard Worker self.copy_updated_abi_dumps() 85*90c8c64dSAndroid Build Coastguard Worker 86*90c8c64dSAndroid Build Coastguard Worker 87*90c8c64dSAndroid Build Coastguard WorkerHELP = """\ 88*90c8c64dSAndroid Build Coastguard WorkerBuilds and updates the NDK ABI prebuilts. 89*90c8c64dSAndroid Build Coastguard Worker 90*90c8c64dSAndroid Build Coastguard WorkerWhenever a change is made that alters the NDK ABI (or an API level is 91*90c8c64dSAndroid Build Coastguard Workerfinalized, or a new preview codename is introduced to the build), the prebuilts 92*90c8c64dSAndroid Build Coastguard Workerin prebuilts/abi-dumps/ndk need to be updated to match. For any finalized APIs, 93*90c8c64dSAndroid Build Coastguard Workerthe breaking change typically needs to be reverted. 94*90c8c64dSAndroid Build Coastguard Worker 95*90c8c64dSAndroid Build Coastguard WorkerNote that typically this tool should be executed via 96*90c8c64dSAndroid Build Coastguard Workerdevelopment/tools/ndk/update_ndk_abi.sh. That script will ensure that this tool 97*90c8c64dSAndroid Build Coastguard Workeris up-to-date and run with the correct arguments. 98*90c8c64dSAndroid Build Coastguard Worker""" 99*90c8c64dSAndroid Build Coastguard Worker 100*90c8c64dSAndroid Build Coastguard Worker 101*90c8c64dSAndroid Build Coastguard Workerclass App: 102*90c8c64dSAndroid Build Coastguard Worker """Command line application from updating NDK ABI prebuilts.""" 103*90c8c64dSAndroid Build Coastguard Worker 104*90c8c64dSAndroid Build Coastguard Worker @staticmethod 105*90c8c64dSAndroid Build Coastguard Worker def parse_args() -> argparse.Namespace: 106*90c8c64dSAndroid Build Coastguard Worker """Parses and returns command line arguments.""" 107*90c8c64dSAndroid Build Coastguard Worker 108*90c8c64dSAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 109*90c8c64dSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, description=HELP 110*90c8c64dSAndroid Build Coastguard Worker ) 111*90c8c64dSAndroid Build Coastguard Worker 112*90c8c64dSAndroid Build Coastguard Worker def resolved_path(path: str) -> Path: 113*90c8c64dSAndroid Build Coastguard Worker """Converts a string into a fully resolved Path.""" 114*90c8c64dSAndroid Build Coastguard Worker return Path(path).resolve() 115*90c8c64dSAndroid Build Coastguard Worker 116*90c8c64dSAndroid Build Coastguard Worker parser.add_argument( 117*90c8c64dSAndroid Build Coastguard Worker "--src-dir", 118*90c8c64dSAndroid Build Coastguard Worker type=resolved_path, 119*90c8c64dSAndroid Build Coastguard Worker required=True, 120*90c8c64dSAndroid Build Coastguard Worker help="Path to the top of the Android source tree.", 121*90c8c64dSAndroid Build Coastguard Worker ) 122*90c8c64dSAndroid Build Coastguard Worker 123*90c8c64dSAndroid Build Coastguard Worker parser.add_argument( 124*90c8c64dSAndroid Build Coastguard Worker "out_dir", 125*90c8c64dSAndroid Build Coastguard Worker type=resolved_path, 126*90c8c64dSAndroid Build Coastguard Worker metavar="OUT_DIR", 127*90c8c64dSAndroid Build Coastguard Worker help="Output directory to use for building ABI dumps.", 128*90c8c64dSAndroid Build Coastguard Worker ) 129*90c8c64dSAndroid Build Coastguard Worker 130*90c8c64dSAndroid Build Coastguard Worker parser.add_argument( 131*90c8c64dSAndroid Build Coastguard Worker "-v", 132*90c8c64dSAndroid Build Coastguard Worker "--verbose", 133*90c8c64dSAndroid Build Coastguard Worker action="count", 134*90c8c64dSAndroid Build Coastguard Worker default=0, 135*90c8c64dSAndroid Build Coastguard Worker help="Increase logging verbosity.", 136*90c8c64dSAndroid Build Coastguard Worker ) 137*90c8c64dSAndroid Build Coastguard Worker 138*90c8c64dSAndroid Build Coastguard Worker return parser.parse_args() 139*90c8c64dSAndroid Build Coastguard Worker 140*90c8c64dSAndroid Build Coastguard Worker def run(self) -> None: 141*90c8c64dSAndroid Build Coastguard Worker """Builds the new NDK ABI dumps and copies them to prebuilts.""" 142*90c8c64dSAndroid Build Coastguard Worker args = self.parse_args() 143*90c8c64dSAndroid Build Coastguard Worker log_level = logging.DEBUG if args.verbose else logging.INFO 144*90c8c64dSAndroid Build Coastguard Worker logging.basicConfig(level=log_level) 145*90c8c64dSAndroid Build Coastguard Worker test_path = args.src_dir / "build/soong/soong_ui.bash" 146*90c8c64dSAndroid Build Coastguard Worker if not test_path.exists(): 147*90c8c64dSAndroid Build Coastguard Worker sys.exit( 148*90c8c64dSAndroid Build Coastguard Worker f"Source directory {args.src_dir} does not appear to be an " 149*90c8c64dSAndroid Build Coastguard Worker f"Android source tree: {test_path} does not exist." 150*90c8c64dSAndroid Build Coastguard Worker ) 151*90c8c64dSAndroid Build Coastguard Worker 152*90c8c64dSAndroid Build Coastguard Worker Updater(args.src_dir, args.out_dir).run() 153