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