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