1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6777b538SAndroid Build Coastguard Worker# Copyright 2022 The Chromium Authors 3*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file. 5*6777b538SAndroid Build Coastguard Worker"""Wrapper script to run action remotely through rewrapper with gn. 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard WorkerAlso includes Chromium-specific input processors which don't make sense to 8*6777b538SAndroid Build Coastguard Workerbe reclient inbuilt input processors.""" 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Workerimport argparse 11*6777b538SAndroid Build Coastguard Workerimport json 12*6777b538SAndroid Build Coastguard Workerimport os 13*6777b538SAndroid Build Coastguard Workerimport subprocess 14*6777b538SAndroid Build Coastguard Workerimport sys 15*6777b538SAndroid Build Coastguard Workerfrom enum import Enum 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker_THIS_DIR = os.path.realpath(os.path.dirname(__file__)) 18*6777b538SAndroid Build Coastguard Worker_SRC_DIR = os.path.dirname(os.path.dirname(_THIS_DIR)) 19*6777b538SAndroid Build Coastguard Worker_MOJOM_DIR = os.path.join(_SRC_DIR, 'mojo', 'public', 'tools', 'mojom') 20*6777b538SAndroid Build Coastguard Worker 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Workerclass CustomProcessor(Enum): 23*6777b538SAndroid Build Coastguard Worker mojom_parser = 'mojom_parser' 24*6777b538SAndroid Build Coastguard Worker 25*6777b538SAndroid Build Coastguard Worker def __str__(self): 26*6777b538SAndroid Build Coastguard Worker return self.value 27*6777b538SAndroid Build Coastguard Worker 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard Workerdef _normalize_path(path): 30*6777b538SAndroid Build Coastguard Worker # Always use posix-style directory separators as GN does it. 31*6777b538SAndroid Build Coastguard Worker return os.path.normpath(path).replace("\\", "/") 32*6777b538SAndroid Build Coastguard Worker 33*6777b538SAndroid Build Coastguard Worker 34*6777b538SAndroid Build Coastguard Workerdef _process_build_metadata_json(bm_file, input_roots, output_root, 35*6777b538SAndroid Build Coastguard Worker output_files, processed_inputs): 36*6777b538SAndroid Build Coastguard Worker """Recursively find mojom_parser inputs from a build_metadata file.""" 37*6777b538SAndroid Build Coastguard Worker # Import Mojo-specific dep here so non-Mojo remote actions don't need it. 38*6777b538SAndroid Build Coastguard Worker if _MOJOM_DIR not in sys.path: 39*6777b538SAndroid Build Coastguard Worker sys.path.insert(0, _MOJOM_DIR) 40*6777b538SAndroid Build Coastguard Worker from mojom_parser import RebaseAbsolutePath 41*6777b538SAndroid Build Coastguard Worker 42*6777b538SAndroid Build Coastguard Worker if bm_file in processed_inputs: 43*6777b538SAndroid Build Coastguard Worker return 44*6777b538SAndroid Build Coastguard Worker 45*6777b538SAndroid Build Coastguard Worker processed_inputs.add(bm_file) 46*6777b538SAndroid Build Coastguard Worker 47*6777b538SAndroid Build Coastguard Worker bm_dir = os.path.dirname(bm_file) 48*6777b538SAndroid Build Coastguard Worker 49*6777b538SAndroid Build Coastguard Worker with open(bm_file) as f: 50*6777b538SAndroid Build Coastguard Worker bm = json.load(f) 51*6777b538SAndroid Build Coastguard Worker 52*6777b538SAndroid Build Coastguard Worker # All sources and corresponding module files are inputs. 53*6777b538SAndroid Build Coastguard Worker for s in bm["sources"]: 54*6777b538SAndroid Build Coastguard Worker src = _normalize_path(os.path.join(bm_dir, s)) 55*6777b538SAndroid Build Coastguard Worker if src not in processed_inputs and os.path.exists(src): 56*6777b538SAndroid Build Coastguard Worker processed_inputs.add(src) 57*6777b538SAndroid Build Coastguard Worker src_module = _normalize_path( 58*6777b538SAndroid Build Coastguard Worker os.path.join( 59*6777b538SAndroid Build Coastguard Worker output_root, 60*6777b538SAndroid Build Coastguard Worker RebaseAbsolutePath(os.path.abspath(src), input_roots) + "-module")) 61*6777b538SAndroid Build Coastguard Worker if src_module in output_files: 62*6777b538SAndroid Build Coastguard Worker continue 63*6777b538SAndroid Build Coastguard Worker if src_module not in processed_inputs and os.path.exists(src_module): 64*6777b538SAndroid Build Coastguard Worker processed_inputs.add(src_module) 65*6777b538SAndroid Build Coastguard Worker 66*6777b538SAndroid Build Coastguard Worker # Recurse into build_metadata deps. 67*6777b538SAndroid Build Coastguard Worker for d in bm["deps"]: 68*6777b538SAndroid Build Coastguard Worker dep = _normalize_path(os.path.join(bm_dir, d)) 69*6777b538SAndroid Build Coastguard Worker _process_build_metadata_json(dep, input_roots, output_root, output_files, 70*6777b538SAndroid Build Coastguard Worker processed_inputs) 71*6777b538SAndroid Build Coastguard Worker 72*6777b538SAndroid Build Coastguard Worker 73*6777b538SAndroid Build Coastguard Workerdef _get_mojom_parser_inputs(exec_root, output_files, extra_args): 74*6777b538SAndroid Build Coastguard Worker """Get mojom inputs by walking generated build_metadata files. 75*6777b538SAndroid Build Coastguard Worker 76*6777b538SAndroid Build Coastguard Worker This is less complexity and disk I/O compared to parsing mojom files for 77*6777b538SAndroid Build Coastguard Worker imports and finding all imports. 78*6777b538SAndroid Build Coastguard Worker 79*6777b538SAndroid Build Coastguard Worker Start from the root build_metadata file passed to mojom_parser's 80*6777b538SAndroid Build Coastguard Worker --check-imports flag. 81*6777b538SAndroid Build Coastguard Worker """ 82*6777b538SAndroid Build Coastguard Worker argparser = argparse.ArgumentParser() 83*6777b538SAndroid Build Coastguard Worker argparser.add_argument('--check-imports', dest='check_imports', required=True) 84*6777b538SAndroid Build Coastguard Worker argparser.add_argument('--output-root', dest='output_root', required=True) 85*6777b538SAndroid Build Coastguard Worker argparser.add_argument('--input-root', 86*6777b538SAndroid Build Coastguard Worker default=[], 87*6777b538SAndroid Build Coastguard Worker action='append', 88*6777b538SAndroid Build Coastguard Worker dest='input_root_paths') 89*6777b538SAndroid Build Coastguard Worker mojom_parser_args, _ = argparser.parse_known_args(args=extra_args) 90*6777b538SAndroid Build Coastguard Worker 91*6777b538SAndroid Build Coastguard Worker input_roots = list(map(os.path.abspath, mojom_parser_args.input_root_paths)) 92*6777b538SAndroid Build Coastguard Worker output_root = os.path.abspath(mojom_parser_args.output_root) 93*6777b538SAndroid Build Coastguard Worker processed_inputs = set() 94*6777b538SAndroid Build Coastguard Worker _process_build_metadata_json(mojom_parser_args.check_imports, input_roots, 95*6777b538SAndroid Build Coastguard Worker output_root, output_files, processed_inputs) 96*6777b538SAndroid Build Coastguard Worker 97*6777b538SAndroid Build Coastguard Worker # Rebase paths onto rewrapper exec root. 98*6777b538SAndroid Build Coastguard Worker return map(lambda dep: _normalize_path(os.path.relpath(dep, exec_root)), 99*6777b538SAndroid Build Coastguard Worker processed_inputs) 100*6777b538SAndroid Build Coastguard Worker 101*6777b538SAndroid Build Coastguard Worker 102*6777b538SAndroid Build Coastguard Workerdef main(): 103*6777b538SAndroid Build Coastguard Worker # Set up argparser with some rewrapper flags. 104*6777b538SAndroid Build Coastguard Worker argparser = argparse.ArgumentParser(description='rewrapper executor for gn', 105*6777b538SAndroid Build Coastguard Worker allow_abbrev=False) 106*6777b538SAndroid Build Coastguard Worker argparser.add_argument('--custom_processor', 107*6777b538SAndroid Build Coastguard Worker type=CustomProcessor, 108*6777b538SAndroid Build Coastguard Worker choices=list(CustomProcessor)) 109*6777b538SAndroid Build Coastguard Worker argparser.add_argument('rewrapper_path') 110*6777b538SAndroid Build Coastguard Worker argparser.add_argument('--input_list_paths') 111*6777b538SAndroid Build Coastguard Worker argparser.add_argument('--output_list_paths') 112*6777b538SAndroid Build Coastguard Worker argparser.add_argument('--exec_root') 113*6777b538SAndroid Build Coastguard Worker parsed_args, extra_args = argparser.parse_known_args() 114*6777b538SAndroid Build Coastguard Worker 115*6777b538SAndroid Build Coastguard Worker # This script expects to be calling rewrapper. 116*6777b538SAndroid Build Coastguard Worker args = [parsed_args.rewrapper_path] 117*6777b538SAndroid Build Coastguard Worker 118*6777b538SAndroid Build Coastguard Worker # Get the output files list. 119*6777b538SAndroid Build Coastguard Worker output_files = set() 120*6777b538SAndroid Build Coastguard Worker with open(parsed_args.output_list_paths, 'r') as file: 121*6777b538SAndroid Build Coastguard Worker for line in file: 122*6777b538SAndroid Build Coastguard Worker # Output files are relative to exec_root. 123*6777b538SAndroid Build Coastguard Worker output_file = _normalize_path( 124*6777b538SAndroid Build Coastguard Worker os.path.join(parsed_args.exec_root, line.rstrip('\n'))) 125*6777b538SAndroid Build Coastguard Worker output_files.add(output_file) 126*6777b538SAndroid Build Coastguard Worker 127*6777b538SAndroid Build Coastguard Worker # Scan for and add explicit inputs for rewrapper if necessary. 128*6777b538SAndroid Build Coastguard Worker # These should be in a new input list paths file, as using --inputs can fail 129*6777b538SAndroid Build Coastguard Worker # if the list is extremely large. 130*6777b538SAndroid Build Coastguard Worker if parsed_args.custom_processor == CustomProcessor.mojom_parser: 131*6777b538SAndroid Build Coastguard Worker root, ext = os.path.splitext(parsed_args.input_list_paths) 132*6777b538SAndroid Build Coastguard Worker extra_inputs = _get_mojom_parser_inputs(parsed_args.exec_root, output_files, 133*6777b538SAndroid Build Coastguard Worker extra_args) 134*6777b538SAndroid Build Coastguard Worker extra_input_list_path = '%s__extra%s' % (root, ext) 135*6777b538SAndroid Build Coastguard Worker with open(extra_input_list_path, 'w') as file: 136*6777b538SAndroid Build Coastguard Worker with open(parsed_args.input_list_paths, 'r') as inputs: 137*6777b538SAndroid Build Coastguard Worker file.write(inputs.read()) 138*6777b538SAndroid Build Coastguard Worker file.write("\n".join(extra_inputs)) 139*6777b538SAndroid Build Coastguard Worker args += ["--input_list_paths=%s" % extra_input_list_path] 140*6777b538SAndroid Build Coastguard Worker else: 141*6777b538SAndroid Build Coastguard Worker args += ["--input_list_paths=%s" % parsed_args.input_list_paths] 142*6777b538SAndroid Build Coastguard Worker 143*6777b538SAndroid Build Coastguard Worker # Filter out --custom_processor= which is a flag for this script, 144*6777b538SAndroid Build Coastguard Worker # and filter out --input_list_paths= because we replace it above. 145*6777b538SAndroid Build Coastguard Worker # Pass on the rest of the args to rewrapper. 146*6777b538SAndroid Build Coastguard Worker args_rest = filter(lambda arg: '--custom_processor=' not in arg, sys.argv[2:]) 147*6777b538SAndroid Build Coastguard Worker args += filter(lambda arg: '--input_list_paths=' not in arg, args_rest) 148*6777b538SAndroid Build Coastguard Worker 149*6777b538SAndroid Build Coastguard Worker # Run rewrapper. 150*6777b538SAndroid Build Coastguard Worker proc = subprocess.run(args) 151*6777b538SAndroid Build Coastguard Worker return proc.returncode 152*6777b538SAndroid Build Coastguard Worker 153*6777b538SAndroid Build Coastguard Worker 154*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__': 155*6777b538SAndroid Build Coastguard Worker sys.exit(main()) 156