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