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