xref: /aosp_15_r20/external/angle/build/toolchain/apple/compile_xcassets.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker# Copyright 2016 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 Worker"""Wrapper around actool to compile assets catalog.
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard WorkerThe script compile_xcassets.py is a wrapper around actool to compile
8*8975f5c5SAndroid Build Coastguard Workerassets catalog to Assets.car that turns warning into errors. It also
9*8975f5c5SAndroid Build Coastguard Workerfixes some quirks of actool to make it work from ninja (mostly that
10*8975f5c5SAndroid Build Coastguard Workeractool seems to require absolute path but gn generates command-line
11*8975f5c5SAndroid Build Coastguard Workerwith relative paths).
12*8975f5c5SAndroid Build Coastguard Worker
13*8975f5c5SAndroid Build Coastguard WorkerThe wrapper filter out any message that is not a section header and
14*8975f5c5SAndroid Build Coastguard Workernot a warning or error message, and fails if filtered output is not
15*8975f5c5SAndroid Build Coastguard Workerempty. This should to treat all warnings as error until actool has
16*8975f5c5SAndroid Build Coastguard Workeran option to fail with non-zero error code when there are warnings.
17*8975f5c5SAndroid Build Coastguard Worker"""
18*8975f5c5SAndroid Build Coastguard Worker
19*8975f5c5SAndroid Build Coastguard Workerimport argparse
20*8975f5c5SAndroid Build Coastguard Workerimport os
21*8975f5c5SAndroid Build Coastguard Workerimport re
22*8975f5c5SAndroid Build Coastguard Workerimport shutil
23*8975f5c5SAndroid Build Coastguard Workerimport subprocess
24*8975f5c5SAndroid Build Coastguard Workerimport sys
25*8975f5c5SAndroid Build Coastguard Workerimport tempfile
26*8975f5c5SAndroid Build Coastguard Workerimport zipfile
27*8975f5c5SAndroid Build Coastguard Worker
28*8975f5c5SAndroid Build Coastguard Worker# Pattern matching a section header in the output of actool.
29*8975f5c5SAndroid Build Coastguard WorkerSECTION_HEADER = re.compile('^/\\* ([^ ]*) \\*/$')
30*8975f5c5SAndroid Build Coastguard Worker
31*8975f5c5SAndroid Build Coastguard Worker# Name of the section containing informational messages that can be ignored.
32*8975f5c5SAndroid Build Coastguard WorkerNOTICE_SECTION = 'com.apple.actool.compilation-results'
33*8975f5c5SAndroid Build Coastguard Worker
34*8975f5c5SAndroid Build Coastguard Worker# Map special type of asset catalog to the corresponding command-line
35*8975f5c5SAndroid Build Coastguard Worker# parameter that need to be passed to actool.
36*8975f5c5SAndroid Build Coastguard WorkerACTOOL_FLAG_FOR_ASSET_TYPE = {
37*8975f5c5SAndroid Build Coastguard Worker    '.appiconset': '--app-icon',
38*8975f5c5SAndroid Build Coastguard Worker    '.launchimage': '--launch-image',
39*8975f5c5SAndroid Build Coastguard Worker}
40*8975f5c5SAndroid Build Coastguard Worker
41*8975f5c5SAndroid Build Coastguard Workerdef FixAbsolutePathInLine(line, relative_paths):
42*8975f5c5SAndroid Build Coastguard Worker  """Fix absolute paths present in |line| to relative paths."""
43*8975f5c5SAndroid Build Coastguard Worker  absolute_path = line.split(':')[0]
44*8975f5c5SAndroid Build Coastguard Worker  relative_path = relative_paths.get(absolute_path, absolute_path)
45*8975f5c5SAndroid Build Coastguard Worker  if absolute_path == relative_path:
46*8975f5c5SAndroid Build Coastguard Worker    return line
47*8975f5c5SAndroid Build Coastguard Worker  return relative_path + line[len(absolute_path):]
48*8975f5c5SAndroid Build Coastguard Worker
49*8975f5c5SAndroid Build Coastguard Worker
50*8975f5c5SAndroid Build Coastguard Workerdef FilterCompilerOutput(compiler_output, relative_paths):
51*8975f5c5SAndroid Build Coastguard Worker  """Filers actool compilation output.
52*8975f5c5SAndroid Build Coastguard Worker
53*8975f5c5SAndroid Build Coastguard Worker  The compiler output is composed of multiple sections for each different
54*8975f5c5SAndroid Build Coastguard Worker  level of output (error, warning, notices, ...). Each section starts with
55*8975f5c5SAndroid Build Coastguard Worker  the section name on a single line, followed by all the messages from the
56*8975f5c5SAndroid Build Coastguard Worker  section.
57*8975f5c5SAndroid Build Coastguard Worker
58*8975f5c5SAndroid Build Coastguard Worker  The function filter any lines that are not in com.apple.actool.errors or
59*8975f5c5SAndroid Build Coastguard Worker  com.apple.actool.document.warnings sections (as spurious messages comes
60*8975f5c5SAndroid Build Coastguard Worker  before any section of the output).
61*8975f5c5SAndroid Build Coastguard Worker
62*8975f5c5SAndroid Build Coastguard Worker  See crbug.com/730054, crbug.com/739163 and crbug.com/770634 for some example
63*8975f5c5SAndroid Build Coastguard Worker  messages that pollute the output of actool and cause flaky builds.
64*8975f5c5SAndroid Build Coastguard Worker
65*8975f5c5SAndroid Build Coastguard Worker  Args:
66*8975f5c5SAndroid Build Coastguard Worker    compiler_output: string containing the output generated by the
67*8975f5c5SAndroid Build Coastguard Worker      compiler (contains both stdout and stderr)
68*8975f5c5SAndroid Build Coastguard Worker    relative_paths: mapping from absolute to relative paths used to
69*8975f5c5SAndroid Build Coastguard Worker      convert paths in the warning and error messages (unknown paths
70*8975f5c5SAndroid Build Coastguard Worker      will be left unaltered)
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Worker  Returns:
73*8975f5c5SAndroid Build Coastguard Worker    The filtered output of the compiler. If the compilation was a
74*8975f5c5SAndroid Build Coastguard Worker    success, then the output will be empty, otherwise it will use
75*8975f5c5SAndroid Build Coastguard Worker    relative path and omit any irrelevant output.
76*8975f5c5SAndroid Build Coastguard Worker  """
77*8975f5c5SAndroid Build Coastguard Worker
78*8975f5c5SAndroid Build Coastguard Worker  filtered_output = []
79*8975f5c5SAndroid Build Coastguard Worker  current_section = None
80*8975f5c5SAndroid Build Coastguard Worker  data_in_section = False
81*8975f5c5SAndroid Build Coastguard Worker  for line in compiler_output.splitlines():
82*8975f5c5SAndroid Build Coastguard Worker    # TODO:(crbug.com/348008793): Ignore Dark and Tintable App Icon unassigned
83*8975f5c5SAndroid Build Coastguard Worker    # children warning when building with Xcode 15
84*8975f5c5SAndroid Build Coastguard Worker    if 'The app icon set "AppIcon" has 2 unassigned children' in line:
85*8975f5c5SAndroid Build Coastguard Worker      continue
86*8975f5c5SAndroid Build Coastguard Worker
87*8975f5c5SAndroid Build Coastguard Worker    match = SECTION_HEADER.search(line)
88*8975f5c5SAndroid Build Coastguard Worker    if match is not None:
89*8975f5c5SAndroid Build Coastguard Worker      data_in_section = False
90*8975f5c5SAndroid Build Coastguard Worker      current_section = match.group(1)
91*8975f5c5SAndroid Build Coastguard Worker      continue
92*8975f5c5SAndroid Build Coastguard Worker    if current_section and current_section != NOTICE_SECTION:
93*8975f5c5SAndroid Build Coastguard Worker      if not data_in_section:
94*8975f5c5SAndroid Build Coastguard Worker        data_in_section = True
95*8975f5c5SAndroid Build Coastguard Worker        filtered_output.append('/* %s */\n' % current_section)
96*8975f5c5SAndroid Build Coastguard Worker
97*8975f5c5SAndroid Build Coastguard Worker      fixed_line = FixAbsolutePathInLine(line, relative_paths)
98*8975f5c5SAndroid Build Coastguard Worker      filtered_output.append(fixed_line + '\n')
99*8975f5c5SAndroid Build Coastguard Worker
100*8975f5c5SAndroid Build Coastguard Worker  return ''.join(filtered_output)
101*8975f5c5SAndroid Build Coastguard Worker
102*8975f5c5SAndroid Build Coastguard Worker
103*8975f5c5SAndroid Build Coastguard Workerdef CompileAssetCatalog(output, platform, target_environment, product_type,
104*8975f5c5SAndroid Build Coastguard Worker                        min_deployment_target, possibly_zipped_inputs,
105*8975f5c5SAndroid Build Coastguard Worker                        compress_pngs, partial_info_plist, temporary_dir):
106*8975f5c5SAndroid Build Coastguard Worker  """Compile the .xcassets bundles to an asset catalog using actool.
107*8975f5c5SAndroid Build Coastguard Worker
108*8975f5c5SAndroid Build Coastguard Worker  Args:
109*8975f5c5SAndroid Build Coastguard Worker    output: absolute path to the containing bundle
110*8975f5c5SAndroid Build Coastguard Worker    platform: the targeted platform
111*8975f5c5SAndroid Build Coastguard Worker    product_type: the bundle type
112*8975f5c5SAndroid Build Coastguard Worker    min_deployment_target: minimum deployment target
113*8975f5c5SAndroid Build Coastguard Worker    possibly_zipped_inputs: list of absolute paths to .xcassets bundles or zips
114*8975f5c5SAndroid Build Coastguard Worker    compress_pngs: whether to enable compression of pngs
115*8975f5c5SAndroid Build Coastguard Worker    partial_info_plist: path to partial Info.plist to generate
116*8975f5c5SAndroid Build Coastguard Worker    temporary_dir: path to directory for storing temp data
117*8975f5c5SAndroid Build Coastguard Worker  """
118*8975f5c5SAndroid Build Coastguard Worker  command = [
119*8975f5c5SAndroid Build Coastguard Worker      'xcrun',
120*8975f5c5SAndroid Build Coastguard Worker      'actool',
121*8975f5c5SAndroid Build Coastguard Worker      '--output-format=human-readable-text',
122*8975f5c5SAndroid Build Coastguard Worker      '--notices',
123*8975f5c5SAndroid Build Coastguard Worker      '--warnings',
124*8975f5c5SAndroid Build Coastguard Worker      '--errors',
125*8975f5c5SAndroid Build Coastguard Worker      '--minimum-deployment-target',
126*8975f5c5SAndroid Build Coastguard Worker      min_deployment_target,
127*8975f5c5SAndroid Build Coastguard Worker  ]
128*8975f5c5SAndroid Build Coastguard Worker
129*8975f5c5SAndroid Build Coastguard Worker  if compress_pngs:
130*8975f5c5SAndroid Build Coastguard Worker    command.extend(['--compress-pngs'])
131*8975f5c5SAndroid Build Coastguard Worker
132*8975f5c5SAndroid Build Coastguard Worker  if product_type != '':
133*8975f5c5SAndroid Build Coastguard Worker    command.extend(['--product-type', product_type])
134*8975f5c5SAndroid Build Coastguard Worker
135*8975f5c5SAndroid Build Coastguard Worker  if platform == 'mac':
136*8975f5c5SAndroid Build Coastguard Worker    command.extend([
137*8975f5c5SAndroid Build Coastguard Worker        '--platform',
138*8975f5c5SAndroid Build Coastguard Worker        'macosx',
139*8975f5c5SAndroid Build Coastguard Worker        '--target-device',
140*8975f5c5SAndroid Build Coastguard Worker        'mac',
141*8975f5c5SAndroid Build Coastguard Worker    ])
142*8975f5c5SAndroid Build Coastguard Worker  elif platform == 'ios':
143*8975f5c5SAndroid Build Coastguard Worker    if target_environment == 'simulator':
144*8975f5c5SAndroid Build Coastguard Worker      command.extend([
145*8975f5c5SAndroid Build Coastguard Worker          '--platform',
146*8975f5c5SAndroid Build Coastguard Worker          'iphonesimulator',
147*8975f5c5SAndroid Build Coastguard Worker          '--target-device',
148*8975f5c5SAndroid Build Coastguard Worker          'iphone',
149*8975f5c5SAndroid Build Coastguard Worker          '--target-device',
150*8975f5c5SAndroid Build Coastguard Worker          'ipad',
151*8975f5c5SAndroid Build Coastguard Worker      ])
152*8975f5c5SAndroid Build Coastguard Worker    elif target_environment == 'device':
153*8975f5c5SAndroid Build Coastguard Worker      command.extend([
154*8975f5c5SAndroid Build Coastguard Worker          '--platform',
155*8975f5c5SAndroid Build Coastguard Worker          'iphoneos',
156*8975f5c5SAndroid Build Coastguard Worker          '--target-device',
157*8975f5c5SAndroid Build Coastguard Worker          'iphone',
158*8975f5c5SAndroid Build Coastguard Worker          '--target-device',
159*8975f5c5SAndroid Build Coastguard Worker          'ipad',
160*8975f5c5SAndroid Build Coastguard Worker      ])
161*8975f5c5SAndroid Build Coastguard Worker    elif target_environment == 'catalyst':
162*8975f5c5SAndroid Build Coastguard Worker      command.extend([
163*8975f5c5SAndroid Build Coastguard Worker          '--platform',
164*8975f5c5SAndroid Build Coastguard Worker          'macosx',
165*8975f5c5SAndroid Build Coastguard Worker          '--target-device',
166*8975f5c5SAndroid Build Coastguard Worker          'ipad',
167*8975f5c5SAndroid Build Coastguard Worker          '--ui-framework-family',
168*8975f5c5SAndroid Build Coastguard Worker          'uikit',
169*8975f5c5SAndroid Build Coastguard Worker      ])
170*8975f5c5SAndroid Build Coastguard Worker    else:
171*8975f5c5SAndroid Build Coastguard Worker      sys.stderr.write('Unsupported ios environment: %s' % target_environment)
172*8975f5c5SAndroid Build Coastguard Worker      sys.exit(1)
173*8975f5c5SAndroid Build Coastguard Worker  elif platform == 'watchos':
174*8975f5c5SAndroid Build Coastguard Worker    if target_environment == 'simulator':
175*8975f5c5SAndroid Build Coastguard Worker      command.extend([
176*8975f5c5SAndroid Build Coastguard Worker          '--platform',
177*8975f5c5SAndroid Build Coastguard Worker          'watchsimulator',
178*8975f5c5SAndroid Build Coastguard Worker          '--target-device',
179*8975f5c5SAndroid Build Coastguard Worker          'watch',
180*8975f5c5SAndroid Build Coastguard Worker      ])
181*8975f5c5SAndroid Build Coastguard Worker    elif target_environment == 'device':
182*8975f5c5SAndroid Build Coastguard Worker      command.extend([
183*8975f5c5SAndroid Build Coastguard Worker          '--platform',
184*8975f5c5SAndroid Build Coastguard Worker          'watchos',
185*8975f5c5SAndroid Build Coastguard Worker          '--target-device',
186*8975f5c5SAndroid Build Coastguard Worker          'watch',
187*8975f5c5SAndroid Build Coastguard Worker      ])
188*8975f5c5SAndroid Build Coastguard Worker    else:
189*8975f5c5SAndroid Build Coastguard Worker      sys.stderr.write(
190*8975f5c5SAndroid Build Coastguard Worker        'Unsupported watchos environment: %s' % target_environment)
191*8975f5c5SAndroid Build Coastguard Worker      sys.exit(1)
192*8975f5c5SAndroid Build Coastguard Worker
193*8975f5c5SAndroid Build Coastguard Worker  # Unzip any input zipfiles to a temporary directory.
194*8975f5c5SAndroid Build Coastguard Worker  inputs = []
195*8975f5c5SAndroid Build Coastguard Worker  for relative_path in possibly_zipped_inputs:
196*8975f5c5SAndroid Build Coastguard Worker    if os.path.isfile(relative_path) and zipfile.is_zipfile(relative_path):
197*8975f5c5SAndroid Build Coastguard Worker      catalog_name = os.path.basename(relative_path)
198*8975f5c5SAndroid Build Coastguard Worker      unzip_path = os.path.join(temporary_dir, os.path.dirname(relative_path))
199*8975f5c5SAndroid Build Coastguard Worker      with zipfile.ZipFile(relative_path) as z:
200*8975f5c5SAndroid Build Coastguard Worker        invalid_files = [
201*8975f5c5SAndroid Build Coastguard Worker            x for x in z.namelist()
202*8975f5c5SAndroid Build Coastguard Worker            if '..' in x or not x.startswith(catalog_name)
203*8975f5c5SAndroid Build Coastguard Worker        ]
204*8975f5c5SAndroid Build Coastguard Worker        if invalid_files:
205*8975f5c5SAndroid Build Coastguard Worker          sys.stderr.write('Invalid files in zip: %s' % invalid_files)
206*8975f5c5SAndroid Build Coastguard Worker          sys.exit(1)
207*8975f5c5SAndroid Build Coastguard Worker        z.extractall(unzip_path)
208*8975f5c5SAndroid Build Coastguard Worker      inputs.append(os.path.join(unzip_path, catalog_name))
209*8975f5c5SAndroid Build Coastguard Worker    else:
210*8975f5c5SAndroid Build Coastguard Worker      inputs.append(relative_path)
211*8975f5c5SAndroid Build Coastguard Worker
212*8975f5c5SAndroid Build Coastguard Worker  # Scan the input directories for the presence of asset catalog types that
213*8975f5c5SAndroid Build Coastguard Worker  # require special treatment, and if so, add them to the actool command-line.
214*8975f5c5SAndroid Build Coastguard Worker  for relative_path in inputs:
215*8975f5c5SAndroid Build Coastguard Worker
216*8975f5c5SAndroid Build Coastguard Worker    if not os.path.isdir(relative_path):
217*8975f5c5SAndroid Build Coastguard Worker      continue
218*8975f5c5SAndroid Build Coastguard Worker
219*8975f5c5SAndroid Build Coastguard Worker    for file_or_dir_name in os.listdir(relative_path):
220*8975f5c5SAndroid Build Coastguard Worker      if not os.path.isdir(os.path.join(relative_path, file_or_dir_name)):
221*8975f5c5SAndroid Build Coastguard Worker        continue
222*8975f5c5SAndroid Build Coastguard Worker
223*8975f5c5SAndroid Build Coastguard Worker      asset_name, asset_type = os.path.splitext(file_or_dir_name)
224*8975f5c5SAndroid Build Coastguard Worker      if asset_type not in ACTOOL_FLAG_FOR_ASSET_TYPE:
225*8975f5c5SAndroid Build Coastguard Worker        continue
226*8975f5c5SAndroid Build Coastguard Worker
227*8975f5c5SAndroid Build Coastguard Worker      command.extend([ACTOOL_FLAG_FOR_ASSET_TYPE[asset_type], asset_name])
228*8975f5c5SAndroid Build Coastguard Worker
229*8975f5c5SAndroid Build Coastguard Worker  # Always ask actool to generate a partial Info.plist file. If no path
230*8975f5c5SAndroid Build Coastguard Worker  # has been given by the caller, use a temporary file name.
231*8975f5c5SAndroid Build Coastguard Worker  temporary_file = None
232*8975f5c5SAndroid Build Coastguard Worker  if not partial_info_plist:
233*8975f5c5SAndroid Build Coastguard Worker    temporary_file = tempfile.NamedTemporaryFile(suffix='.plist')
234*8975f5c5SAndroid Build Coastguard Worker    partial_info_plist = temporary_file.name
235*8975f5c5SAndroid Build Coastguard Worker
236*8975f5c5SAndroid Build Coastguard Worker  command.extend(['--output-partial-info-plist', partial_info_plist])
237*8975f5c5SAndroid Build Coastguard Worker
238*8975f5c5SAndroid Build Coastguard Worker  # Dictionary used to convert absolute paths back to their relative form
239*8975f5c5SAndroid Build Coastguard Worker  # in the output of actool.
240*8975f5c5SAndroid Build Coastguard Worker  relative_paths = {}
241*8975f5c5SAndroid Build Coastguard Worker
242*8975f5c5SAndroid Build Coastguard Worker  # actool crashes if paths are relative, so convert input and output paths
243*8975f5c5SAndroid Build Coastguard Worker  # to absolute paths, and record the relative paths to fix them back when
244*8975f5c5SAndroid Build Coastguard Worker  # filtering the output.
245*8975f5c5SAndroid Build Coastguard Worker  absolute_output = os.path.abspath(output)
246*8975f5c5SAndroid Build Coastguard Worker  relative_paths[output] = absolute_output
247*8975f5c5SAndroid Build Coastguard Worker  relative_paths[os.path.dirname(output)] = os.path.dirname(absolute_output)
248*8975f5c5SAndroid Build Coastguard Worker  command.extend(['--compile', os.path.dirname(os.path.abspath(output))])
249*8975f5c5SAndroid Build Coastguard Worker
250*8975f5c5SAndroid Build Coastguard Worker  for relative_path in inputs:
251*8975f5c5SAndroid Build Coastguard Worker    absolute_path = os.path.abspath(relative_path)
252*8975f5c5SAndroid Build Coastguard Worker    relative_paths[absolute_path] = relative_path
253*8975f5c5SAndroid Build Coastguard Worker    command.append(absolute_path)
254*8975f5c5SAndroid Build Coastguard Worker
255*8975f5c5SAndroid Build Coastguard Worker  try:
256*8975f5c5SAndroid Build Coastguard Worker    # Run actool and redirect stdout and stderr to the same pipe (as actool
257*8975f5c5SAndroid Build Coastguard Worker    # is confused about what should go to stderr/stdout).
258*8975f5c5SAndroid Build Coastguard Worker    process = subprocess.Popen(command,
259*8975f5c5SAndroid Build Coastguard Worker                               stdout=subprocess.PIPE,
260*8975f5c5SAndroid Build Coastguard Worker                               stderr=subprocess.STDOUT)
261*8975f5c5SAndroid Build Coastguard Worker    stdout = process.communicate()[0].decode('utf-8')
262*8975f5c5SAndroid Build Coastguard Worker
263*8975f5c5SAndroid Build Coastguard Worker    # If the invocation of `actool` failed, copy all the compiler output to
264*8975f5c5SAndroid Build Coastguard Worker    # the standard error stream and exit. See https://crbug.com/1205775 for
265*8975f5c5SAndroid Build Coastguard Worker    # example of compilation that failed with no error message due to filter.
266*8975f5c5SAndroid Build Coastguard Worker    if process.returncode:
267*8975f5c5SAndroid Build Coastguard Worker      for line in stdout.splitlines():
268*8975f5c5SAndroid Build Coastguard Worker        fixed_line = FixAbsolutePathInLine(line, relative_paths)
269*8975f5c5SAndroid Build Coastguard Worker        sys.stderr.write(fixed_line + '\n')
270*8975f5c5SAndroid Build Coastguard Worker      sys.exit(1)
271*8975f5c5SAndroid Build Coastguard Worker
272*8975f5c5SAndroid Build Coastguard Worker    # Filter the output to remove all garbage and to fix the paths. If the
273*8975f5c5SAndroid Build Coastguard Worker    # output is not empty after filtering, then report the compilation as a
274*8975f5c5SAndroid Build Coastguard Worker    # failure (as some version of `actool` report error to stdout, yet exit
275*8975f5c5SAndroid Build Coastguard Worker    # with an return code of zero).
276*8975f5c5SAndroid Build Coastguard Worker    stdout = FilterCompilerOutput(stdout, relative_paths)
277*8975f5c5SAndroid Build Coastguard Worker    if stdout:
278*8975f5c5SAndroid Build Coastguard Worker      sys.stderr.write(stdout)
279*8975f5c5SAndroid Build Coastguard Worker      sys.exit(1)
280*8975f5c5SAndroid Build Coastguard Worker
281*8975f5c5SAndroid Build Coastguard Worker  finally:
282*8975f5c5SAndroid Build Coastguard Worker    if temporary_file:
283*8975f5c5SAndroid Build Coastguard Worker      temporary_file.close()
284*8975f5c5SAndroid Build Coastguard Worker
285*8975f5c5SAndroid Build Coastguard Worker
286*8975f5c5SAndroid Build Coastguard Workerdef Main():
287*8975f5c5SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(
288*8975f5c5SAndroid Build Coastguard Worker      description='compile assets catalog for a bundle')
289*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--platform',
290*8975f5c5SAndroid Build Coastguard Worker                      '-p',
291*8975f5c5SAndroid Build Coastguard Worker                      required=True,
292*8975f5c5SAndroid Build Coastguard Worker                      choices=('mac', 'ios', 'watchos'),
293*8975f5c5SAndroid Build Coastguard Worker                      help='target platform for the compiled assets catalog')
294*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--target-environment',
295*8975f5c5SAndroid Build Coastguard Worker                      '-e',
296*8975f5c5SAndroid Build Coastguard Worker                      default='',
297*8975f5c5SAndroid Build Coastguard Worker                      choices=('simulator', 'device', 'catalyst'),
298*8975f5c5SAndroid Build Coastguard Worker                      help='target environment for the compiled assets catalog')
299*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument(
300*8975f5c5SAndroid Build Coastguard Worker      '--minimum-deployment-target',
301*8975f5c5SAndroid Build Coastguard Worker      '-t',
302*8975f5c5SAndroid Build Coastguard Worker      required=True,
303*8975f5c5SAndroid Build Coastguard Worker      help='minimum deployment target for the compiled assets catalog')
304*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--output',
305*8975f5c5SAndroid Build Coastguard Worker                      '-o',
306*8975f5c5SAndroid Build Coastguard Worker                      required=True,
307*8975f5c5SAndroid Build Coastguard Worker                      help='path to the compiled assets catalog')
308*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--compress-pngs',
309*8975f5c5SAndroid Build Coastguard Worker                      '-c',
310*8975f5c5SAndroid Build Coastguard Worker                      action='store_true',
311*8975f5c5SAndroid Build Coastguard Worker                      default=False,
312*8975f5c5SAndroid Build Coastguard Worker                      help='recompress PNGs while compiling assets catalog')
313*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--product-type',
314*8975f5c5SAndroid Build Coastguard Worker                      '-T',
315*8975f5c5SAndroid Build Coastguard Worker                      help='type of the containing bundle')
316*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('--partial-info-plist',
317*8975f5c5SAndroid Build Coastguard Worker                      '-P',
318*8975f5c5SAndroid Build Coastguard Worker                      help='path to partial info plist to create')
319*8975f5c5SAndroid Build Coastguard Worker  parser.add_argument('inputs',
320*8975f5c5SAndroid Build Coastguard Worker                      nargs='+',
321*8975f5c5SAndroid Build Coastguard Worker                      help='path to input assets catalog sources')
322*8975f5c5SAndroid Build Coastguard Worker  args = parser.parse_args()
323*8975f5c5SAndroid Build Coastguard Worker
324*8975f5c5SAndroid Build Coastguard Worker  if os.path.basename(args.output) != 'Assets.car':
325*8975f5c5SAndroid Build Coastguard Worker    sys.stderr.write('output should be path to compiled asset catalog, not '
326*8975f5c5SAndroid Build Coastguard Worker                     'to the containing bundle: %s\n' % (args.output, ))
327*8975f5c5SAndroid Build Coastguard Worker    sys.exit(1)
328*8975f5c5SAndroid Build Coastguard Worker
329*8975f5c5SAndroid Build Coastguard Worker  if os.path.exists(args.output):
330*8975f5c5SAndroid Build Coastguard Worker    if os.path.isfile(args.output):
331*8975f5c5SAndroid Build Coastguard Worker      os.unlink(args.output)
332*8975f5c5SAndroid Build Coastguard Worker    else:
333*8975f5c5SAndroid Build Coastguard Worker      shutil.rmtree(args.output)
334*8975f5c5SAndroid Build Coastguard Worker
335*8975f5c5SAndroid Build Coastguard Worker  with tempfile.TemporaryDirectory() as temporary_dir:
336*8975f5c5SAndroid Build Coastguard Worker    CompileAssetCatalog(args.output, args.platform, args.target_environment,
337*8975f5c5SAndroid Build Coastguard Worker                        args.product_type, args.minimum_deployment_target,
338*8975f5c5SAndroid Build Coastguard Worker                        args.inputs, args.compress_pngs,
339*8975f5c5SAndroid Build Coastguard Worker                        args.partial_info_plist, temporary_dir)
340*8975f5c5SAndroid Build Coastguard Worker
341*8975f5c5SAndroid Build Coastguard Worker
342*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__':
343*8975f5c5SAndroid Build Coastguard Worker  sys.exit(Main())
344