xref: /aosp_15_r20/external/cronet/build/config/ios/extract_metadata.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker# Copyright 2024 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Workerimport argparse
6*6777b538SAndroid Build Coastguard Workerimport json
7*6777b538SAndroid Build Coastguard Workerimport os
8*6777b538SAndroid Build Coastguard Workerimport subprocess
9*6777b538SAndroid Build Coastguard Workerimport sys
10*6777b538SAndroid Build Coastguard Workerimport shutil
11*6777b538SAndroid Build Coastguard Workerimport tempfile
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard WorkerTARGET_CPU_MAPPING = {
14*6777b538SAndroid Build Coastguard Worker    'x64': 'x86_64',
15*6777b538SAndroid Build Coastguard Worker    'arm64': 'arm64',
16*6777b538SAndroid Build Coastguard Worker}
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard WorkerMETADATA_FILES = ('extract.actionsdata', 'version.json')
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Workerdef read_json(path):
22*6777b538SAndroid Build Coastguard Worker  """Reads JSON file at `path`."""
23*6777b538SAndroid Build Coastguard Worker  with open(path, encoding='utf8') as stream:
24*6777b538SAndroid Build Coastguard Worker    return json.load(stream)
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Workerdef add_argument(parser, name, help, required=True):
28*6777b538SAndroid Build Coastguard Worker  """Add argument --{name} to `parser` with description `help`."""
29*6777b538SAndroid Build Coastguard Worker  parser.add_argument(f'--{name}', required=required, help=help)
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Workerdef extract_metadata(parsed, module_name, swift_files, const_files):
33*6777b538SAndroid Build Coastguard Worker  """
34*6777b538SAndroid Build Coastguard Worker  Extracts metadata for `module_name` according to `parsed`.
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker  If the extraction fails or no metadata is generated, terminate the script
37*6777b538SAndroid Build Coastguard Worker  with an error (after printing the command stdout/stderr to stderr).
38*6777b538SAndroid Build Coastguard Worker  """
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker  metadata_dir = os.path.join(parsed.output, 'Metadata.appintents')
41*6777b538SAndroid Build Coastguard Worker  if os.path.exists(metadata_dir):
42*6777b538SAndroid Build Coastguard Worker    shutil.rmtree(metadata_dir)
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker  target_cpu = TARGET_CPU_MAPPING[parsed.target_cpu]
45*6777b538SAndroid Build Coastguard Worker  target_triple = f'{target_cpu}-apple-ios{parsed.deployment_target}'
46*6777b538SAndroid Build Coastguard Worker  if parsed.target_environment == 'simulator':
47*6777b538SAndroid Build Coastguard Worker    target_triple += '-simulator'
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker  command = [
50*6777b538SAndroid Build Coastguard Worker      os.path.join(parsed.toolchain_dir, 'usr/bin/appintentsmetadataprocessor'),
51*6777b538SAndroid Build Coastguard Worker      '--toolchain-dir',
52*6777b538SAndroid Build Coastguard Worker      parsed.toolchain_dir,
53*6777b538SAndroid Build Coastguard Worker      '--sdk-root',
54*6777b538SAndroid Build Coastguard Worker      parsed.sdk_root,
55*6777b538SAndroid Build Coastguard Worker      '--deployment-target',
56*6777b538SAndroid Build Coastguard Worker      parsed.deployment_target,
57*6777b538SAndroid Build Coastguard Worker      '--target-triple',
58*6777b538SAndroid Build Coastguard Worker      target_triple,
59*6777b538SAndroid Build Coastguard Worker      '--module-name',
60*6777b538SAndroid Build Coastguard Worker      module_name,
61*6777b538SAndroid Build Coastguard Worker      '--output',
62*6777b538SAndroid Build Coastguard Worker      parsed.output,
63*6777b538SAndroid Build Coastguard Worker      '--binary-file',
64*6777b538SAndroid Build Coastguard Worker      parsed.binary_file,
65*6777b538SAndroid Build Coastguard Worker      '--compile-time-extraction',
66*6777b538SAndroid Build Coastguard Worker  ]
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker  inputs = set()
69*6777b538SAndroid Build Coastguard Worker  inputs.add(parsed.binary_file)
70*6777b538SAndroid Build Coastguard Worker
71*6777b538SAndroid Build Coastguard Worker  for swift_file in swift_files:
72*6777b538SAndroid Build Coastguard Worker    inputs.add(swift_file)
73*6777b538SAndroid Build Coastguard Worker    command.extend(('--source-files', swift_file))
74*6777b538SAndroid Build Coastguard Worker
75*6777b538SAndroid Build Coastguard Worker  for const_file in const_files:
76*6777b538SAndroid Build Coastguard Worker    inputs.add(const_file)
77*6777b538SAndroid Build Coastguard Worker    command.extend(('--swift-const-vals', const_file))
78*6777b538SAndroid Build Coastguard Worker
79*6777b538SAndroid Build Coastguard Worker  if parsed.xcode_version is not None:
80*6777b538SAndroid Build Coastguard Worker    command.extend(('--xcode-version', parsed.xcode_version))
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker  process = subprocess.Popen(command,
83*6777b538SAndroid Build Coastguard Worker                             stdout=subprocess.PIPE,
84*6777b538SAndroid Build Coastguard Worker                             stderr=subprocess.PIPE)
85*6777b538SAndroid Build Coastguard Worker  (stdout, stderr) = process.communicate()
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Worker  if process.returncode:
88*6777b538SAndroid Build Coastguard Worker    sys.stderr.write(stdout.decode('utf8'))
89*6777b538SAndroid Build Coastguard Worker    sys.stderr.write(stderr.decode('utf8'))
90*6777b538SAndroid Build Coastguard Worker    return process.returncode
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker  # Force failure if the tool extracted no data. This is because gn does
93*6777b538SAndroid Build Coastguard Worker  # not support optional outputs and thus it would consider the build as
94*6777b538SAndroid Build Coastguard Worker  # dirty if the output is missing.
95*6777b538SAndroid Build Coastguard Worker  if not os.path.exists(metadata_dir):
96*6777b538SAndroid Build Coastguard Worker    sys.stderr.write(f'error: no metadata generated for {module_name}\n')
97*6777b538SAndroid Build Coastguard Worker    sys.stderr.write(stdout.decode('utf8'))
98*6777b538SAndroid Build Coastguard Worker    sys.stderr.write(stderr.decode('utf8'))
99*6777b538SAndroid Build Coastguard Worker    return 1  # failure
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker  output_files = METADATA_FILES
102*6777b538SAndroid Build Coastguard Worker  with open(parsed.depfile, 'w', encoding='utf8') as depfile:
103*6777b538SAndroid Build Coastguard Worker    for output in output_files:
104*6777b538SAndroid Build Coastguard Worker      depfile.write(f'{metadata_dir}/{output}:')
105*6777b538SAndroid Build Coastguard Worker      for item in sorted(inputs):
106*6777b538SAndroid Build Coastguard Worker        depfile.write(f' {item}')
107*6777b538SAndroid Build Coastguard Worker      depfile.write('\n')
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker  return 0  # success
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Worker
112*6777b538SAndroid Build Coastguard Workerdef main(args):
113*6777b538SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
114*6777b538SAndroid Build Coastguard Worker
115*6777b538SAndroid Build Coastguard Worker  add_argument(parser, 'output', 'path to the output directory')
116*6777b538SAndroid Build Coastguard Worker  add_argument(parser, 'depfile', 'path to the output depfile')
117*6777b538SAndroid Build Coastguard Worker  add_argument(parser, 'toolchain-dir', 'path to the toolchain directory')
118*6777b538SAndroid Build Coastguard Worker  add_argument(parser, 'sdk-root', 'path to the SDK root directory')
119*6777b538SAndroid Build Coastguard Worker  add_argument(parser, 'target-cpu', 'target cpu architecture')
120*6777b538SAndroid Build Coastguard Worker  add_argument(parser, 'target-environment', 'target environment')
121*6777b538SAndroid Build Coastguard Worker  add_argument(parser, 'deployment-target', 'deployment target version')
122*6777b538SAndroid Build Coastguard Worker  add_argument(parser, 'binary-file', 'path to the binary to process')
123*6777b538SAndroid Build Coastguard Worker  add_argument(parser, 'module-info-path', 'path to the module info JSON file')
124*6777b538SAndroid Build Coastguard Worker  add_argument(parser, 'xcode-version', 'version of Xcode', required=False)
125*6777b538SAndroid Build Coastguard Worker
126*6777b538SAndroid Build Coastguard Worker  parsed = parser.parse_args(args)
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Worker  module_info = read_json(parsed.module_info_path)
129*6777b538SAndroid Build Coastguard Worker  return extract_metadata(
130*6777b538SAndroid Build Coastguard Worker      parsed,  #
131*6777b538SAndroid Build Coastguard Worker      module_info['module_name'],
132*6777b538SAndroid Build Coastguard Worker      module_info['swift_files'],
133*6777b538SAndroid Build Coastguard Worker      module_info['const_files'])
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard Worker
136*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__':
137*6777b538SAndroid Build Coastguard Worker  sys.exit(main(sys.argv[1:]))
138