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