1#!/usr/bin/env python3 2# Copyright 2024 The Chromium Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5import os 6import sys 7import tempfile 8import argparse 9from typing import List, Set 10 11REPOSITORY_ROOT = os.path.abspath( 12 os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir)) 13 14sys.path.insert(0, REPOSITORY_ROOT) 15import components.cronet.tools.utils as cronet_utils # pylint: disable=wrong-import-position 16import build.android.gyp.util.build_utils as build_utils # pylint: disable=wrong-import-position 17 18_ARCHS = ["x86", "x64", "arm", "arm64"] 19_GN2BP_SCRIPT_PATH = os.path.join(REPOSITORY_ROOT, 20 "components/cronet/gn2bp/gen_android_bp.py") 21_OUT_DIR = os.path.join(REPOSITORY_ROOT, "out") 22_EXTRA_GN_ARGS = ("is_cronet_for_aosp_build=true"), 23_GN_PATH = os.path.join(REPOSITORY_ROOT, 'buildtools/linux64/gn') 24 25 26def _run_gn2bp(desc_files: Set[tempfile.NamedTemporaryFile]) -> int: 27 with tempfile.NamedTemporaryFile(mode="w+", encoding='utf-8') as android_bp: 28 base_cmd = ["python3", _GN2BP_SCRIPT_PATH, "--out", android_bp.name] 29 for desc_file in desc_files: 30 # desc_file.name represents the absolute path. 31 base_cmd += ["--desc", desc_file.name] 32 return cronet_utils.run(base_cmd) 33 34 35def _get_args_for_aosp(arch: str) -> List[str]: 36 default_args = cronet_utils.get_android_gn_args(True, arch) 37 default_args += _EXTRA_GN_ARGS 38 return ' '.join(cronet_utils.filter_gn_args(default_args, 39 ["use_remoteexec"])) 40 41 42def _write_desc_json(gn_out_dir: str, 43 temp_file: tempfile.NamedTemporaryFile) -> int: 44 return cronet_utils.run([ 45 _GN_PATH, "desc", gn_out_dir, "--format=json", "--all-toolchains", "//*" 46 ], 47 stdout=temp_file) 48 49 50def _main(): 51 parser = argparse.ArgumentParser() 52 parser.add_argument('--stamp', 53 type=str, 54 help='Path to touch on success', 55 required=True) 56 args = parser.parse_args() 57 try: 58 # Create empty temp file for each architecture. 59 arch_to_temp_desc_file = { 60 arch: tempfile.NamedTemporaryFile(mode="w+", encoding='utf-8') 61 for arch in _ARCHS 62 } 63 64 for (arch, temp_file) in arch_to_temp_desc_file.items(): 65 # gn desc behaves completely differently when the output 66 # directory is outside of chromium/src, some paths will 67 # stop having // in the beginning of their labels 68 # eg (//A/B will become A/B), this mostly apply to files 69 # that are generated through actions and not targets. 70 # 71 # This is why the temporary directory has to be generated 72 # beneath the repository root until gn2bp is tweaked to 73 # deal with this small differences. 74 with tempfile.TemporaryDirectory(dir=_OUT_DIR) as gn_out_dir: 75 cronet_utils.gn(gn_out_dir, _get_args_for_aosp(arch)) 76 if _write_desc_json(gn_out_dir, temp_file) != 0: 77 # Close the files and exit if we failed to generate any 78 # of the desc.json files. 79 print(f"Failed to generate desc file for arch: {arch}") 80 for file in arch_to_temp_desc_file.values(): 81 # Close the temporary files so they can be deleted. 82 file.close() 83 sys.exit(-1) 84 85 res = _run_gn2bp(arch_to_temp_desc_file.values()) 86 finally: 87 for file in arch_to_temp_desc_file.values(): 88 # Close the temporary files so they can be deleted. 89 file.close() 90 91 if res != 0: 92 print("Failed to execute gn2bp!") 93 sys.exit(-1) 94 else: 95 build_utils.Touch(args.stamp) 96 return 0 97 98 99if __name__ == '__main__': 100 sys.exit(_main()) 101