1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*8975f5c5SAndroid Build Coastguard Worker# Copyright 2022 The Chromium Authors 3*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file. 5*8975f5c5SAndroid Build Coastguard Worker"""Check out the Fuchsia SDK from a given GCS path. Should be used in a 6*8975f5c5SAndroid Build Coastguard Worker'hooks_os' entry so that it only runs when .gclient's custom_vars includes 7*8975f5c5SAndroid Build Coastguard Worker'fuchsia'.""" 8*8975f5c5SAndroid Build Coastguard Worker 9*8975f5c5SAndroid Build Coastguard Workerimport argparse 10*8975f5c5SAndroid Build Coastguard Workerimport json 11*8975f5c5SAndroid Build Coastguard Workerimport logging 12*8975f5c5SAndroid Build Coastguard Workerimport os 13*8975f5c5SAndroid Build Coastguard Workerimport platform 14*8975f5c5SAndroid Build Coastguard Workerimport subprocess 15*8975f5c5SAndroid Build Coastguard Workerimport sys 16*8975f5c5SAndroid Build Coastguard Workerfrom typing import Optional 17*8975f5c5SAndroid Build Coastguard Worker 18*8975f5c5SAndroid Build Coastguard Workerfrom gcs_download import DownloadAndUnpackFromCloudStorage 19*8975f5c5SAndroid Build Coastguard Worker 20*8975f5c5SAndroid Build Coastguard Workersys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 21*8975f5c5SAndroid Build Coastguard Worker 'test'))) 22*8975f5c5SAndroid Build Coastguard Worker 23*8975f5c5SAndroid Build Coastguard Workerfrom common import SDK_ROOT, get_host_os, make_clean_directory 24*8975f5c5SAndroid Build Coastguard Worker 25*8975f5c5SAndroid Build Coastguard Worker_VERSION_FILE = os.path.join(SDK_ROOT, 'meta', 'manifest.json') 26*8975f5c5SAndroid Build Coastguard Worker 27*8975f5c5SAndroid Build Coastguard Worker 28*8975f5c5SAndroid Build Coastguard Workerdef _GetHostArch(): 29*8975f5c5SAndroid Build Coastguard Worker host_arch = platform.machine() 30*8975f5c5SAndroid Build Coastguard Worker # platform.machine() returns AMD64 on 64-bit Windows. 31*8975f5c5SAndroid Build Coastguard Worker if host_arch in ['x86_64', 'AMD64']: 32*8975f5c5SAndroid Build Coastguard Worker return 'amd64' 33*8975f5c5SAndroid Build Coastguard Worker elif host_arch == 'aarch64': 34*8975f5c5SAndroid Build Coastguard Worker return 'arm64' 35*8975f5c5SAndroid Build Coastguard Worker raise Exception('Unsupported host architecture: %s' % host_arch) 36*8975f5c5SAndroid Build Coastguard Worker 37*8975f5c5SAndroid Build Coastguard Worker 38*8975f5c5SAndroid Build Coastguard Workerdef GetSDKOverrideGCSPath() -> Optional[str]: 39*8975f5c5SAndroid Build Coastguard Worker """Fetches the sdk override path from a file or an environment variable. 40*8975f5c5SAndroid Build Coastguard Worker 41*8975f5c5SAndroid Build Coastguard Worker Returns: 42*8975f5c5SAndroid Build Coastguard Worker The override sdk location, stripped of white space. 43*8975f5c5SAndroid Build Coastguard Worker Example: gs://fuchsia-artifacts/development/some-id/sdk 44*8975f5c5SAndroid Build Coastguard Worker """ 45*8975f5c5SAndroid Build Coastguard Worker if os.getenv('FUCHSIA_SDK_OVERRIDE'): 46*8975f5c5SAndroid Build Coastguard Worker return os.environ['FUCHSIA_SDK_OVERRIDE'].strip() 47*8975f5c5SAndroid Build Coastguard Worker 48*8975f5c5SAndroid Build Coastguard Worker path = os.path.join(os.path.dirname(__file__), 'sdk_override.txt') 49*8975f5c5SAndroid Build Coastguard Worker 50*8975f5c5SAndroid Build Coastguard Worker if os.path.isfile(path): 51*8975f5c5SAndroid Build Coastguard Worker with open(path, 'r') as f: 52*8975f5c5SAndroid Build Coastguard Worker return f.read().strip() 53*8975f5c5SAndroid Build Coastguard Worker 54*8975f5c5SAndroid Build Coastguard Worker return None 55*8975f5c5SAndroid Build Coastguard Worker 56*8975f5c5SAndroid Build Coastguard Worker 57*8975f5c5SAndroid Build Coastguard Workerdef _GetCurrentVersionFromManifest() -> Optional[str]: 58*8975f5c5SAndroid Build Coastguard Worker if not os.path.exists(_VERSION_FILE): 59*8975f5c5SAndroid Build Coastguard Worker return None 60*8975f5c5SAndroid Build Coastguard Worker with open(_VERSION_FILE) as f: 61*8975f5c5SAndroid Build Coastguard Worker return json.load(f)['id'] 62*8975f5c5SAndroid Build Coastguard Worker 63*8975f5c5SAndroid Build Coastguard Worker 64*8975f5c5SAndroid Build Coastguard Workerdef main(): 65*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 66*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--cipd-prefix', help='CIPD base directory for the SDK.') 67*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--version', help='Specifies the SDK version.') 68*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--verbose', 69*8975f5c5SAndroid Build Coastguard Worker '-v', 70*8975f5c5SAndroid Build Coastguard Worker action='store_true', 71*8975f5c5SAndroid Build Coastguard Worker help='Enable debug-level logging.') 72*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 73*8975f5c5SAndroid Build Coastguard Worker '--file', 74*8975f5c5SAndroid Build Coastguard Worker help='Specifies the sdk tar.gz file name without .tar.gz suffix', 75*8975f5c5SAndroid Build Coastguard Worker default='core') 76*8975f5c5SAndroid Build Coastguard Worker args = parser.parse_args() 77*8975f5c5SAndroid Build Coastguard Worker 78*8975f5c5SAndroid Build Coastguard Worker logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO) 79*8975f5c5SAndroid Build Coastguard Worker 80*8975f5c5SAndroid Build Coastguard Worker # Exit if there's no SDK support for this platform. 81*8975f5c5SAndroid Build Coastguard Worker try: 82*8975f5c5SAndroid Build Coastguard Worker host_plat = get_host_os() 83*8975f5c5SAndroid Build Coastguard Worker except: 84*8975f5c5SAndroid Build Coastguard Worker logging.warning('Fuchsia SDK is not supported on this platform.') 85*8975f5c5SAndroid Build Coastguard Worker return 0 86*8975f5c5SAndroid Build Coastguard Worker 87*8975f5c5SAndroid Build Coastguard Worker # TODO(crbug.com/326004432): Remove this once DEPS have been fixed not to 88*8975f5c5SAndroid Build Coastguard Worker # include the "version:" prefix. 89*8975f5c5SAndroid Build Coastguard Worker if args.version.startswith('version:'): 90*8975f5c5SAndroid Build Coastguard Worker args.version = args.version[len('version:'):] 91*8975f5c5SAndroid Build Coastguard Worker 92*8975f5c5SAndroid Build Coastguard Worker gcs_tarball_prefix = GetSDKOverrideGCSPath() 93*8975f5c5SAndroid Build Coastguard Worker if not gcs_tarball_prefix: 94*8975f5c5SAndroid Build Coastguard Worker # sdk_override contains the full path but not only the version id. But since 95*8975f5c5SAndroid Build Coastguard Worker # the scenario is limited to dry-run, it's not worth complexity to extract 96*8975f5c5SAndroid Build Coastguard Worker # the version id. 97*8975f5c5SAndroid Build Coastguard Worker if args.version == _GetCurrentVersionFromManifest(): 98*8975f5c5SAndroid Build Coastguard Worker return 0 99*8975f5c5SAndroid Build Coastguard Worker 100*8975f5c5SAndroid Build Coastguard Worker make_clean_directory(SDK_ROOT) 101*8975f5c5SAndroid Build Coastguard Worker 102*8975f5c5SAndroid Build Coastguard Worker # Download from CIPD if there is no override file. 103*8975f5c5SAndroid Build Coastguard Worker if not gcs_tarball_prefix: 104*8975f5c5SAndroid Build Coastguard Worker if not args.cipd_prefix: 105*8975f5c5SAndroid Build Coastguard Worker parser.exit(1, '--cipd-prefix must be specified.') 106*8975f5c5SAndroid Build Coastguard Worker if not args.version: 107*8975f5c5SAndroid Build Coastguard Worker parser.exit(2, '--version must be specified.') 108*8975f5c5SAndroid Build Coastguard Worker logging.info('Downloading SDK from CIPD...') 109*8975f5c5SAndroid Build Coastguard Worker ensure_file = '%s%s-%s version:%s' % (args.cipd_prefix, host_plat, 110*8975f5c5SAndroid Build Coastguard Worker _GetHostArch(), args.version) 111*8975f5c5SAndroid Build Coastguard Worker subprocess.run(('cipd', 'ensure', '-ensure-file', '-', '-root', SDK_ROOT, 112*8975f5c5SAndroid Build Coastguard Worker '-log-level', 'warning'), 113*8975f5c5SAndroid Build Coastguard Worker check=True, 114*8975f5c5SAndroid Build Coastguard Worker text=True, 115*8975f5c5SAndroid Build Coastguard Worker input=ensure_file) 116*8975f5c5SAndroid Build Coastguard Worker 117*8975f5c5SAndroid Build Coastguard Worker # Verify that the downloaded version matches the expected one. 118*8975f5c5SAndroid Build Coastguard Worker downloaded_version = _GetCurrentVersionFromManifest() 119*8975f5c5SAndroid Build Coastguard Worker if downloaded_version != args.version: 120*8975f5c5SAndroid Build Coastguard Worker logging.error( 121*8975f5c5SAndroid Build Coastguard Worker 'SDK version after download does not match expected (downloaded:%s ' 122*8975f5c5SAndroid Build Coastguard Worker 'vs expected:%s)', downloaded_version, args.version) 123*8975f5c5SAndroid Build Coastguard Worker return 3 124*8975f5c5SAndroid Build Coastguard Worker else: 125*8975f5c5SAndroid Build Coastguard Worker logging.info('Downloading SDK from GCS...') 126*8975f5c5SAndroid Build Coastguard Worker DownloadAndUnpackFromCloudStorage( 127*8975f5c5SAndroid Build Coastguard Worker f'{gcs_tarball_prefix}/{get_host_os()}-{_GetHostArch()}/' 128*8975f5c5SAndroid Build Coastguard Worker f'{args.file}.tar.gz', SDK_ROOT) 129*8975f5c5SAndroid Build Coastguard Worker 130*8975f5c5SAndroid Build Coastguard Worker # Build rules (e.g. fidl_library()) depend on updates to the top-level 131*8975f5c5SAndroid Build Coastguard Worker # manifest to spot when to rebuild for an SDK update. Ensure that ninja 132*8975f5c5SAndroid Build Coastguard Worker # sees that the SDK manifest has changed, regardless of the mtime set by 133*8975f5c5SAndroid Build Coastguard Worker # the download & unpack steps above, by setting mtime to now. 134*8975f5c5SAndroid Build Coastguard Worker # See crbug.com/1457463 135*8975f5c5SAndroid Build Coastguard Worker os.utime(os.path.join(SDK_ROOT, 'meta', 'manifest.json'), None) 136*8975f5c5SAndroid Build Coastguard Worker 137*8975f5c5SAndroid Build Coastguard Worker root_dir = os.path.dirname(os.path.realpath(__file__)) 138*8975f5c5SAndroid Build Coastguard Worker build_def_cmd = [ 139*8975f5c5SAndroid Build Coastguard Worker os.path.join(root_dir, 'gen_build_defs.py'), 140*8975f5c5SAndroid Build Coastguard Worker ] 141*8975f5c5SAndroid Build Coastguard Worker subprocess.run(build_def_cmd, check=True) 142*8975f5c5SAndroid Build Coastguard Worker 143*8975f5c5SAndroid Build Coastguard Worker return 0 144*8975f5c5SAndroid Build Coastguard Worker 145*8975f5c5SAndroid Build Coastguard Worker 146*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 147*8975f5c5SAndroid Build Coastguard Worker sys.exit(main()) 148