1*8975f5c5SAndroid Build Coastguard Worker# Copyright 2023 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 collections 7*8975f5c5SAndroid Build Coastguard Workerimport contextlib 8*8975f5c5SAndroid Build Coastguard Workerimport hashlib 9*8975f5c5SAndroid Build Coastguard Workerimport io 10*8975f5c5SAndroid Build Coastguard Workerimport json 11*8975f5c5SAndroid Build Coastguard Workerimport multiprocessing 12*8975f5c5SAndroid Build Coastguard Workerimport os 13*8975f5c5SAndroid Build Coastguard Workerimport re 14*8975f5c5SAndroid Build Coastguard Workerimport shutil 15*8975f5c5SAndroid Build Coastguard Workerimport subprocess 16*8975f5c5SAndroid Build Coastguard Workerimport sys 17*8975f5c5SAndroid Build Coastguard Workerimport tempfile 18*8975f5c5SAndroid Build Coastguard Worker 19*8975f5c5SAndroid Build Coastguard Worker 20*8975f5c5SAndroid Build Coastguard Workerclass ArgumentForwarder(object): 21*8975f5c5SAndroid Build Coastguard Worker """Class used to abstract forwarding arguments from to the swiftc compiler. 22*8975f5c5SAndroid Build Coastguard Worker 23*8975f5c5SAndroid Build Coastguard Worker Arguments: 24*8975f5c5SAndroid Build Coastguard Worker - arg_name: string corresponding to the argument to pass to the compiler 25*8975f5c5SAndroid Build Coastguard Worker - arg_join: function taking the compiler name and returning whether the 26*8975f5c5SAndroid Build Coastguard Worker argument value is attached to the argument or separated 27*8975f5c5SAndroid Build Coastguard Worker - to_swift: function taking the argument value and returning whether it 28*8975f5c5SAndroid Build Coastguard Worker must be passed to the swift compiler 29*8975f5c5SAndroid Build Coastguard Worker - to_clang: function taking the argument value and returning whether it 30*8975f5c5SAndroid Build Coastguard Worker must be passed to the clang compiler 31*8975f5c5SAndroid Build Coastguard Worker """ 32*8975f5c5SAndroid Build Coastguard Worker 33*8975f5c5SAndroid Build Coastguard Worker def __init__(self, arg_name, arg_join, to_swift, to_clang): 34*8975f5c5SAndroid Build Coastguard Worker self._arg_name = arg_name 35*8975f5c5SAndroid Build Coastguard Worker self._arg_join = arg_join 36*8975f5c5SAndroid Build Coastguard Worker self._to_swift = to_swift 37*8975f5c5SAndroid Build Coastguard Worker self._to_clang = to_clang 38*8975f5c5SAndroid Build Coastguard Worker 39*8975f5c5SAndroid Build Coastguard Worker def forward(self, swiftc_args, values, target_triple): 40*8975f5c5SAndroid Build Coastguard Worker if not values: 41*8975f5c5SAndroid Build Coastguard Worker return 42*8975f5c5SAndroid Build Coastguard Worker 43*8975f5c5SAndroid Build Coastguard Worker is_catalyst = target_triple.endswith('macabi') 44*8975f5c5SAndroid Build Coastguard Worker for value in values: 45*8975f5c5SAndroid Build Coastguard Worker if self._to_swift(value): 46*8975f5c5SAndroid Build Coastguard Worker if self._arg_join('swift'): 47*8975f5c5SAndroid Build Coastguard Worker swiftc_args.append(f'{self._arg_name}{value}') 48*8975f5c5SAndroid Build Coastguard Worker else: 49*8975f5c5SAndroid Build Coastguard Worker swiftc_args.append(self._arg_name) 50*8975f5c5SAndroid Build Coastguard Worker swiftc_args.append(value) 51*8975f5c5SAndroid Build Coastguard Worker 52*8975f5c5SAndroid Build Coastguard Worker if self._to_clang(value) and not is_catalyst: 53*8975f5c5SAndroid Build Coastguard Worker if self._arg_join('clang'): 54*8975f5c5SAndroid Build Coastguard Worker swiftc_args.append('-Xcc') 55*8975f5c5SAndroid Build Coastguard Worker swiftc_args.append(f'{self._arg_name}{value}') 56*8975f5c5SAndroid Build Coastguard Worker else: 57*8975f5c5SAndroid Build Coastguard Worker swiftc_args.append('-Xcc') 58*8975f5c5SAndroid Build Coastguard Worker swiftc_args.append(self._arg_name) 59*8975f5c5SAndroid Build Coastguard Worker swiftc_args.append('-Xcc') 60*8975f5c5SAndroid Build Coastguard Worker swiftc_args.append(value) 61*8975f5c5SAndroid Build Coastguard Worker 62*8975f5c5SAndroid Build Coastguard Worker 63*8975f5c5SAndroid Build Coastguard Workerclass IncludeArgumentForwarder(ArgumentForwarder): 64*8975f5c5SAndroid Build Coastguard Worker """Argument forwarder for -I and -isystem.""" 65*8975f5c5SAndroid Build Coastguard Worker 66*8975f5c5SAndroid Build Coastguard Worker def __init__(self, arg_name): 67*8975f5c5SAndroid Build Coastguard Worker ArgumentForwarder.__init__(self, 68*8975f5c5SAndroid Build Coastguard Worker arg_name, 69*8975f5c5SAndroid Build Coastguard Worker arg_join=lambda _: len(arg_name) == 1, 70*8975f5c5SAndroid Build Coastguard Worker to_swift=lambda _: arg_name != '-isystem', 71*8975f5c5SAndroid Build Coastguard Worker to_clang=lambda _: True) 72*8975f5c5SAndroid Build Coastguard Worker 73*8975f5c5SAndroid Build Coastguard Worker 74*8975f5c5SAndroid Build Coastguard Workerclass FrameworkArgumentForwarder(ArgumentForwarder): 75*8975f5c5SAndroid Build Coastguard Worker """Argument forwarder for -F and -Fsystem.""" 76*8975f5c5SAndroid Build Coastguard Worker 77*8975f5c5SAndroid Build Coastguard Worker def __init__(self, arg_name): 78*8975f5c5SAndroid Build Coastguard Worker ArgumentForwarder.__init__(self, 79*8975f5c5SAndroid Build Coastguard Worker arg_name, 80*8975f5c5SAndroid Build Coastguard Worker arg_join=lambda _: len(arg_name) == 1, 81*8975f5c5SAndroid Build Coastguard Worker to_swift=lambda _: True, 82*8975f5c5SAndroid Build Coastguard Worker to_clang=lambda _: True) 83*8975f5c5SAndroid Build Coastguard Worker 84*8975f5c5SAndroid Build Coastguard Worker 85*8975f5c5SAndroid Build Coastguard Workerclass DefineArgumentForwarder(ArgumentForwarder): 86*8975f5c5SAndroid Build Coastguard Worker """Argument forwarder for -D.""" 87*8975f5c5SAndroid Build Coastguard Worker 88*8975f5c5SAndroid Build Coastguard Worker def __init__(self, arg_name): 89*8975f5c5SAndroid Build Coastguard Worker ArgumentForwarder.__init__(self, 90*8975f5c5SAndroid Build Coastguard Worker arg_name, 91*8975f5c5SAndroid Build Coastguard Worker arg_join=lambda _: _ == 'clang', 92*8975f5c5SAndroid Build Coastguard Worker to_swift=lambda _: '=' not in _, 93*8975f5c5SAndroid Build Coastguard Worker to_clang=lambda _: True) 94*8975f5c5SAndroid Build Coastguard Worker 95*8975f5c5SAndroid Build Coastguard Worker 96*8975f5c5SAndroid Build Coastguard Worker# Dictionary mapping argument names to their ArgumentForwarder. 97*8975f5c5SAndroid Build Coastguard WorkerARGUMENT_FORWARDER_FOR_ATTR = ( 98*8975f5c5SAndroid Build Coastguard Worker ('include_dirs', IncludeArgumentForwarder('-I')), 99*8975f5c5SAndroid Build Coastguard Worker ('system_include_dirs', IncludeArgumentForwarder('-isystem')), 100*8975f5c5SAndroid Build Coastguard Worker ('framework_dirs', FrameworkArgumentForwarder('-F')), 101*8975f5c5SAndroid Build Coastguard Worker ('system_framework_dirs', FrameworkArgumentForwarder('-Fsystem')), 102*8975f5c5SAndroid Build Coastguard Worker ('defines', DefineArgumentForwarder('-D')), 103*8975f5c5SAndroid Build Coastguard Worker) 104*8975f5c5SAndroid Build Coastguard Worker 105*8975f5c5SAndroid Build Coastguard Worker# Regexp used to parse #import lines. 106*8975f5c5SAndroid Build Coastguard WorkerIMPORT_LINE_REGEXP = re.compile('#import "([^"]*)"') 107*8975f5c5SAndroid Build Coastguard Worker 108*8975f5c5SAndroid Build Coastguard Worker 109*8975f5c5SAndroid Build Coastguard Workerclass FileWriter(contextlib.AbstractContextManager): 110*8975f5c5SAndroid Build Coastguard Worker """ 111*8975f5c5SAndroid Build Coastguard Worker FileWriter is a file-like object that only write data to disk if changed. 112*8975f5c5SAndroid Build Coastguard Worker 113*8975f5c5SAndroid Build Coastguard Worker This object implements the context manager protocols and thus can be used 114*8975f5c5SAndroid Build Coastguard Worker in a with-clause. The data is written to disk when the context is exited, 115*8975f5c5SAndroid Build Coastguard Worker and only if the content is different from current file content. 116*8975f5c5SAndroid Build Coastguard Worker 117*8975f5c5SAndroid Build Coastguard Worker with FileWriter(path) as stream: 118*8975f5c5SAndroid Build Coastguard Worker stream.write('...') 119*8975f5c5SAndroid Build Coastguard Worker 120*8975f5c5SAndroid Build Coastguard Worker If the with-clause ends with an exception, no data is written to the disk 121*8975f5c5SAndroid Build Coastguard Worker and any existing file is left untouched. 122*8975f5c5SAndroid Build Coastguard Worker """ 123*8975f5c5SAndroid Build Coastguard Worker 124*8975f5c5SAndroid Build Coastguard Worker def __init__(self, filepath, encoding='utf8'): 125*8975f5c5SAndroid Build Coastguard Worker self._stringio = io.StringIO() 126*8975f5c5SAndroid Build Coastguard Worker self._filepath = filepath 127*8975f5c5SAndroid Build Coastguard Worker self._encoding = encoding 128*8975f5c5SAndroid Build Coastguard Worker 129*8975f5c5SAndroid Build Coastguard Worker def __exit__(self, exc_type, exc_value, traceback): 130*8975f5c5SAndroid Build Coastguard Worker if exc_type or exc_value or traceback: 131*8975f5c5SAndroid Build Coastguard Worker return 132*8975f5c5SAndroid Build Coastguard Worker 133*8975f5c5SAndroid Build Coastguard Worker new_content = self._stringio.getvalue() 134*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(self._filepath): 135*8975f5c5SAndroid Build Coastguard Worker with open(self._filepath, encoding=self._encoding) as stream: 136*8975f5c5SAndroid Build Coastguard Worker old_content = stream.read() 137*8975f5c5SAndroid Build Coastguard Worker 138*8975f5c5SAndroid Build Coastguard Worker if old_content == new_content: 139*8975f5c5SAndroid Build Coastguard Worker return 140*8975f5c5SAndroid Build Coastguard Worker 141*8975f5c5SAndroid Build Coastguard Worker with open(self._filepath, 'w', encoding=self._encoding) as stream: 142*8975f5c5SAndroid Build Coastguard Worker stream.write(new_content) 143*8975f5c5SAndroid Build Coastguard Worker 144*8975f5c5SAndroid Build Coastguard Worker def write(self, data): 145*8975f5c5SAndroid Build Coastguard Worker self._stringio.write(data) 146*8975f5c5SAndroid Build Coastguard Worker 147*8975f5c5SAndroid Build Coastguard Worker 148*8975f5c5SAndroid Build Coastguard Worker@contextlib.contextmanager 149*8975f5c5SAndroid Build Coastguard Workerdef existing_directory(path): 150*8975f5c5SAndroid Build Coastguard Worker """Returns a context manager wrapping an existing directory.""" 151*8975f5c5SAndroid Build Coastguard Worker yield path 152*8975f5c5SAndroid Build Coastguard Worker 153*8975f5c5SAndroid Build Coastguard Worker 154*8975f5c5SAndroid Build Coastguard Workerdef create_stamp_file(path): 155*8975f5c5SAndroid Build Coastguard Worker """Writes an empty stamp file at path.""" 156*8975f5c5SAndroid Build Coastguard Worker with FileWriter(path) as stream: 157*8975f5c5SAndroid Build Coastguard Worker stream.write('') 158*8975f5c5SAndroid Build Coastguard Worker 159*8975f5c5SAndroid Build Coastguard Worker 160*8975f5c5SAndroid Build Coastguard Workerdef create_build_cache_dir(args, build_signature): 161*8975f5c5SAndroid Build Coastguard Worker """Creates the build cache directory according to `args`. 162*8975f5c5SAndroid Build Coastguard Worker 163*8975f5c5SAndroid Build Coastguard Worker This function returns an object that implements the context manager 164*8975f5c5SAndroid Build Coastguard Worker protocol and thus can be used in a with-clause. If -derived-data-dir 165*8975f5c5SAndroid Build Coastguard Worker argument is not used, the returned directory is a temporary directory 166*8975f5c5SAndroid Build Coastguard Worker that will be deleted when the with-clause is exited. 167*8975f5c5SAndroid Build Coastguard Worker """ 168*8975f5c5SAndroid Build Coastguard Worker if not args.derived_data_dir: 169*8975f5c5SAndroid Build Coastguard Worker return tempfile.TemporaryDirectory() 170*8975f5c5SAndroid Build Coastguard Worker 171*8975f5c5SAndroid Build Coastguard Worker # The derived data cache can be quite large, so delete any obsolete 172*8975f5c5SAndroid Build Coastguard Worker # files or directories. 173*8975f5c5SAndroid Build Coastguard Worker stamp_name = f'{args.module_name}.stamp' 174*8975f5c5SAndroid Build Coastguard Worker if os.path.isdir(args.derived_data_dir): 175*8975f5c5SAndroid Build Coastguard Worker for name in os.listdir(args.derived_data_dir): 176*8975f5c5SAndroid Build Coastguard Worker if name not in (build_signature, stamp_name): 177*8975f5c5SAndroid Build Coastguard Worker path = os.path.join(args.derived_data_dir, name) 178*8975f5c5SAndroid Build Coastguard Worker if os.path.isdir(path): 179*8975f5c5SAndroid Build Coastguard Worker shutil.rmtree(path) 180*8975f5c5SAndroid Build Coastguard Worker else: 181*8975f5c5SAndroid Build Coastguard Worker os.unlink(path) 182*8975f5c5SAndroid Build Coastguard Worker 183*8975f5c5SAndroid Build Coastguard Worker ensure_directory(args.derived_data_dir) 184*8975f5c5SAndroid Build Coastguard Worker create_stamp_file(os.path.join(args.derived_data_dir, stamp_name)) 185*8975f5c5SAndroid Build Coastguard Worker 186*8975f5c5SAndroid Build Coastguard Worker return existing_directory( 187*8975f5c5SAndroid Build Coastguard Worker ensure_directory(os.path.join(args.derived_data_dir, build_signature))) 188*8975f5c5SAndroid Build Coastguard Worker 189*8975f5c5SAndroid Build Coastguard Worker 190*8975f5c5SAndroid Build Coastguard Workerdef ensure_directory(path): 191*8975f5c5SAndroid Build Coastguard Worker """Creates directory at `path` if it does not exists.""" 192*8975f5c5SAndroid Build Coastguard Worker if not os.path.isdir(path): 193*8975f5c5SAndroid Build Coastguard Worker os.makedirs(path) 194*8975f5c5SAndroid Build Coastguard Worker return path 195*8975f5c5SAndroid Build Coastguard Worker 196*8975f5c5SAndroid Build Coastguard Worker 197*8975f5c5SAndroid Build Coastguard Workerdef build_signature(env, args): 198*8975f5c5SAndroid Build Coastguard Worker """Generates the build signature from `env` and `args`. 199*8975f5c5SAndroid Build Coastguard Worker 200*8975f5c5SAndroid Build Coastguard Worker This allow re-using the derived data dir between builds while still 201*8975f5c5SAndroid Build Coastguard Worker forcing the data to be recreated from scratch in case of significant 202*8975f5c5SAndroid Build Coastguard Worker changes to the build settings (different arguments or tool versions). 203*8975f5c5SAndroid Build Coastguard Worker """ 204*8975f5c5SAndroid Build Coastguard Worker m = hashlib.sha1() 205*8975f5c5SAndroid Build Coastguard Worker for key in sorted(env): 206*8975f5c5SAndroid Build Coastguard Worker if key.endswith('_VERSION') or key == 'DEVELOPER_DIR': 207*8975f5c5SAndroid Build Coastguard Worker m.update(f'{key}={env[key]}'.encode('utf8')) 208*8975f5c5SAndroid Build Coastguard Worker for i, arg in enumerate(args): 209*8975f5c5SAndroid Build Coastguard Worker m.update(f'{i}={arg}'.encode('utf8')) 210*8975f5c5SAndroid Build Coastguard Worker return m.hexdigest() 211*8975f5c5SAndroid Build Coastguard Worker 212*8975f5c5SAndroid Build Coastguard Worker 213*8975f5c5SAndroid Build Coastguard Workerdef generate_source_output_file_map_fragment(args, filename): 214*8975f5c5SAndroid Build Coastguard Worker """Generates source OutputFileMap.json fragment according to `args`. 215*8975f5c5SAndroid Build Coastguard Worker 216*8975f5c5SAndroid Build Coastguard Worker Create the fragment for a single .swift source file for OutputFileMap. 217*8975f5c5SAndroid Build Coastguard Worker The output depends on whether -whole-module-optimization argument is 218*8975f5c5SAndroid Build Coastguard Worker used or not. 219*8975f5c5SAndroid Build Coastguard Worker """ 220*8975f5c5SAndroid Build Coastguard Worker assert os.path.splitext(filename)[1] == '.swift', filename 221*8975f5c5SAndroid Build Coastguard Worker basename = os.path.splitext(os.path.basename(filename))[0] 222*8975f5c5SAndroid Build Coastguard Worker rel_name = os.path.join(args.target_out_dir, basename) 223*8975f5c5SAndroid Build Coastguard Worker out_name = rel_name 224*8975f5c5SAndroid Build Coastguard Worker 225*8975f5c5SAndroid Build Coastguard Worker fragment = { 226*8975f5c5SAndroid Build Coastguard Worker 'index-unit-output-path': f'/{rel_name}.o', 227*8975f5c5SAndroid Build Coastguard Worker 'object': f'{out_name}.o', 228*8975f5c5SAndroid Build Coastguard Worker } 229*8975f5c5SAndroid Build Coastguard Worker 230*8975f5c5SAndroid Build Coastguard Worker if not args.whole_module_optimization: 231*8975f5c5SAndroid Build Coastguard Worker fragment.update({ 232*8975f5c5SAndroid Build Coastguard Worker 'const-values': f'{out_name}.swiftconstvalues', 233*8975f5c5SAndroid Build Coastguard Worker 'dependencies': f'{out_name}.d', 234*8975f5c5SAndroid Build Coastguard Worker 'diagnostics': f'{out_name}.dia', 235*8975f5c5SAndroid Build Coastguard Worker 'swift-dependencies': f'{out_name}.swiftdeps', 236*8975f5c5SAndroid Build Coastguard Worker }) 237*8975f5c5SAndroid Build Coastguard Worker 238*8975f5c5SAndroid Build Coastguard Worker return fragment 239*8975f5c5SAndroid Build Coastguard Worker 240*8975f5c5SAndroid Build Coastguard Worker 241*8975f5c5SAndroid Build Coastguard Workerdef generate_module_output_file_map_fragment(args): 242*8975f5c5SAndroid Build Coastguard Worker """Generates module OutputFileMap.json fragment according to `args`. 243*8975f5c5SAndroid Build Coastguard Worker 244*8975f5c5SAndroid Build Coastguard Worker Create the fragment for the module itself for OutputFileMap. The output 245*8975f5c5SAndroid Build Coastguard Worker depends on whether -whole-module-optimization argument is used or not. 246*8975f5c5SAndroid Build Coastguard Worker """ 247*8975f5c5SAndroid Build Coastguard Worker out_name = os.path.join(args.target_out_dir, args.module_name) 248*8975f5c5SAndroid Build Coastguard Worker 249*8975f5c5SAndroid Build Coastguard Worker if args.whole_module_optimization: 250*8975f5c5SAndroid Build Coastguard Worker fragment = { 251*8975f5c5SAndroid Build Coastguard Worker 'const-values': f'{out_name}.swiftconstvalues', 252*8975f5c5SAndroid Build Coastguard Worker 'dependencies': f'{out_name}.d', 253*8975f5c5SAndroid Build Coastguard Worker 'diagnostics': f'{out_name}.dia', 254*8975f5c5SAndroid Build Coastguard Worker 'swift-dependencies': f'{out_name}.swiftdeps', 255*8975f5c5SAndroid Build Coastguard Worker } 256*8975f5c5SAndroid Build Coastguard Worker else: 257*8975f5c5SAndroid Build Coastguard Worker fragment = { 258*8975f5c5SAndroid Build Coastguard Worker 'emit-module-dependencies': f'{out_name}.d', 259*8975f5c5SAndroid Build Coastguard Worker 'emit-module-diagnostics': f'{out_name}.dia', 260*8975f5c5SAndroid Build Coastguard Worker 'swift-dependencies': f'{out_name}.swiftdeps', 261*8975f5c5SAndroid Build Coastguard Worker } 262*8975f5c5SAndroid Build Coastguard Worker 263*8975f5c5SAndroid Build Coastguard Worker return fragment 264*8975f5c5SAndroid Build Coastguard Worker 265*8975f5c5SAndroid Build Coastguard Worker 266*8975f5c5SAndroid Build Coastguard Workerdef generate_output_file_map(args): 267*8975f5c5SAndroid Build Coastguard Worker """Generates OutputFileMap.json according to `args`. 268*8975f5c5SAndroid Build Coastguard Worker 269*8975f5c5SAndroid Build Coastguard Worker Returns the mapping as a python dictionary that can be serialized to 270*8975f5c5SAndroid Build Coastguard Worker disk as JSON. 271*8975f5c5SAndroid Build Coastguard Worker """ 272*8975f5c5SAndroid Build Coastguard Worker output_file_map = {'': generate_module_output_file_map_fragment(args)} 273*8975f5c5SAndroid Build Coastguard Worker for filename in args.sources: 274*8975f5c5SAndroid Build Coastguard Worker fragment = generate_source_output_file_map_fragment(args, filename) 275*8975f5c5SAndroid Build Coastguard Worker output_file_map[filename] = fragment 276*8975f5c5SAndroid Build Coastguard Worker return output_file_map 277*8975f5c5SAndroid Build Coastguard Worker 278*8975f5c5SAndroid Build Coastguard Worker 279*8975f5c5SAndroid Build Coastguard Workerdef fix_generated_header(header_path, output_path, src_dir, gen_dir): 280*8975f5c5SAndroid Build Coastguard Worker """Fix the Objective-C header generated by the Swift compiler. 281*8975f5c5SAndroid Build Coastguard Worker 282*8975f5c5SAndroid Build Coastguard Worker The Swift compiler assumes that the generated Objective-C header will be 283*8975f5c5SAndroid Build Coastguard Worker imported from code compiled with module support enabled (-fmodules). The 284*8975f5c5SAndroid Build Coastguard Worker generated code thus uses @import and provides no fallback if modules are 285*8975f5c5SAndroid Build Coastguard Worker not enabled. 286*8975f5c5SAndroid Build Coastguard Worker 287*8975f5c5SAndroid Build Coastguard Worker The Swift compiler also uses absolute path when including the bridging 288*8975f5c5SAndroid Build Coastguard Worker header or another module's generated header. This causes issues with the 289*8975f5c5SAndroid Build Coastguard Worker distributed compiler (i.e. reclient or siso) who expects all paths to be 290*8975f5c5SAndroid Build Coastguard Worker relative to the build directory 291*8975f5c5SAndroid Build Coastguard Worker 292*8975f5c5SAndroid Build Coastguard Worker This method fix the generated header to use relative path for #import 293*8975f5c5SAndroid Build Coastguard Worker and to use #import instead of @import when using system frameworks. 294*8975f5c5SAndroid Build Coastguard Worker 295*8975f5c5SAndroid Build Coastguard Worker The header is read at `header_path` and written to `output_path`. 296*8975f5c5SAndroid Build Coastguard Worker """ 297*8975f5c5SAndroid Build Coastguard Worker 298*8975f5c5SAndroid Build Coastguard Worker header_contents = [] 299*8975f5c5SAndroid Build Coastguard Worker with open(header_path, 'r', encoding='utf8') as header_file: 300*8975f5c5SAndroid Build Coastguard Worker 301*8975f5c5SAndroid Build Coastguard Worker imports_section = None 302*8975f5c5SAndroid Build Coastguard Worker for line in header_file: 303*8975f5c5SAndroid Build Coastguard Worker # Handle #import lines. 304*8975f5c5SAndroid Build Coastguard Worker match = IMPORT_LINE_REGEXP.match(line) 305*8975f5c5SAndroid Build Coastguard Worker if match: 306*8975f5c5SAndroid Build Coastguard Worker import_path = match.group(1) 307*8975f5c5SAndroid Build Coastguard Worker for root in (gen_dir, src_dir): 308*8975f5c5SAndroid Build Coastguard Worker if import_path.startswith(root): 309*8975f5c5SAndroid Build Coastguard Worker import_path = os.path.relpath(import_path, root) 310*8975f5c5SAndroid Build Coastguard Worker if import_path != match.group(1): 311*8975f5c5SAndroid Build Coastguard Worker span = match.span(1) 312*8975f5c5SAndroid Build Coastguard Worker line = line[:span[0]] + import_path + line[span[1]:] 313*8975f5c5SAndroid Build Coastguard Worker 314*8975f5c5SAndroid Build Coastguard Worker # Handle @import lines. 315*8975f5c5SAndroid Build Coastguard Worker if line.startswith('#if __has_feature(objc_modules)'): 316*8975f5c5SAndroid Build Coastguard Worker assert imports_section is None 317*8975f5c5SAndroid Build Coastguard Worker imports_section = (len(header_contents) + 1, 1) 318*8975f5c5SAndroid Build Coastguard Worker elif imports_section: 319*8975f5c5SAndroid Build Coastguard Worker section_start, nesting_level = imports_section 320*8975f5c5SAndroid Build Coastguard Worker if line.startswith('#if'): 321*8975f5c5SAndroid Build Coastguard Worker imports_section = (section_start, nesting_level + 1) 322*8975f5c5SAndroid Build Coastguard Worker elif line.startswith('#endif'): 323*8975f5c5SAndroid Build Coastguard Worker if nesting_level > 1: 324*8975f5c5SAndroid Build Coastguard Worker imports_section = (section_start, nesting_level - 1) 325*8975f5c5SAndroid Build Coastguard Worker else: 326*8975f5c5SAndroid Build Coastguard Worker imports_section = None 327*8975f5c5SAndroid Build Coastguard Worker section_end = len(header_contents) 328*8975f5c5SAndroid Build Coastguard Worker header_contents.append('#else\n') 329*8975f5c5SAndroid Build Coastguard Worker for index in range(section_start, section_end): 330*8975f5c5SAndroid Build Coastguard Worker l = header_contents[index] 331*8975f5c5SAndroid Build Coastguard Worker if l.startswith('@import'): 332*8975f5c5SAndroid Build Coastguard Worker name = l.split()[1].split(';')[0] 333*8975f5c5SAndroid Build Coastguard Worker if name != 'ObjectiveC': 334*8975f5c5SAndroid Build Coastguard Worker header_contents.append(f'#import <{name}/{name}.h>\n') 335*8975f5c5SAndroid Build Coastguard Worker else: 336*8975f5c5SAndroid Build Coastguard Worker header_contents.append(l) 337*8975f5c5SAndroid Build Coastguard Worker 338*8975f5c5SAndroid Build Coastguard Worker header_contents.append(line) 339*8975f5c5SAndroid Build Coastguard Worker 340*8975f5c5SAndroid Build Coastguard Worker with FileWriter(output_path) as header_file: 341*8975f5c5SAndroid Build Coastguard Worker for line in header_contents: 342*8975f5c5SAndroid Build Coastguard Worker header_file.write(line) 343*8975f5c5SAndroid Build Coastguard Worker 344*8975f5c5SAndroid Build Coastguard Worker 345*8975f5c5SAndroid Build Coastguard Workerdef invoke_swift_compiler(args, extras_args, build_cache_dir, output_file_map): 346*8975f5c5SAndroid Build Coastguard Worker """Invokes Swift compiler to compile module according to `args`. 347*8975f5c5SAndroid Build Coastguard Worker 348*8975f5c5SAndroid Build Coastguard Worker The `build_cache_dir` and `output_file_map` should be path to existing 349*8975f5c5SAndroid Build Coastguard Worker directory to use for writing intermediate build artifact (optionally 350*8975f5c5SAndroid Build Coastguard Worker a temporary directory) and path to $module-OutputFileMap.json file that 351*8975f5c5SAndroid Build Coastguard Worker lists the outputs to generate for the module and each source file. 352*8975f5c5SAndroid Build Coastguard Worker 353*8975f5c5SAndroid Build Coastguard Worker If -fix-module-imports argument is passed, the generated header for the 354*8975f5c5SAndroid Build Coastguard Worker module is written to a temporary location and then modified to replace 355*8975f5c5SAndroid Build Coastguard Worker @import by corresponding #import. 356*8975f5c5SAndroid Build Coastguard Worker """ 357*8975f5c5SAndroid Build Coastguard Worker 358*8975f5c5SAndroid Build Coastguard Worker # Write the $module.SwiftFileList file. 359*8975f5c5SAndroid Build Coastguard Worker swift_file_list_path = os.path.join(args.target_out_dir, 360*8975f5c5SAndroid Build Coastguard Worker f'{args.module_name}.SwiftFileList') 361*8975f5c5SAndroid Build Coastguard Worker 362*8975f5c5SAndroid Build Coastguard Worker with FileWriter(swift_file_list_path) as stream: 363*8975f5c5SAndroid Build Coastguard Worker for filename in sorted(args.sources): 364*8975f5c5SAndroid Build Coastguard Worker stream.write(f'"{filename}"\n') 365*8975f5c5SAndroid Build Coastguard Worker 366*8975f5c5SAndroid Build Coastguard Worker header_path = args.header_path 367*8975f5c5SAndroid Build Coastguard Worker if args.fix_generated_header: 368*8975f5c5SAndroid Build Coastguard Worker header_path = os.path.join(build_cache_dir, os.path.basename(header_path)) 369*8975f5c5SAndroid Build Coastguard Worker 370*8975f5c5SAndroid Build Coastguard Worker swiftc_args = [ 371*8975f5c5SAndroid Build Coastguard Worker '-parse-as-library', 372*8975f5c5SAndroid Build Coastguard Worker '-module-name', 373*8975f5c5SAndroid Build Coastguard Worker args.module_name, 374*8975f5c5SAndroid Build Coastguard Worker f'@{swift_file_list_path}', 375*8975f5c5SAndroid Build Coastguard Worker '-sdk', 376*8975f5c5SAndroid Build Coastguard Worker args.sdk_path, 377*8975f5c5SAndroid Build Coastguard Worker '-target', 378*8975f5c5SAndroid Build Coastguard Worker args.target_triple, 379*8975f5c5SAndroid Build Coastguard Worker '-swift-version', 380*8975f5c5SAndroid Build Coastguard Worker args.swift_version, 381*8975f5c5SAndroid Build Coastguard Worker '-c', 382*8975f5c5SAndroid Build Coastguard Worker '-output-file-map', 383*8975f5c5SAndroid Build Coastguard Worker output_file_map, 384*8975f5c5SAndroid Build Coastguard Worker '-save-temps', 385*8975f5c5SAndroid Build Coastguard Worker '-no-color-diagnostics', 386*8975f5c5SAndroid Build Coastguard Worker '-serialize-diagnostics', 387*8975f5c5SAndroid Build Coastguard Worker '-emit-dependencies', 388*8975f5c5SAndroid Build Coastguard Worker '-emit-module', 389*8975f5c5SAndroid Build Coastguard Worker '-emit-module-path', 390*8975f5c5SAndroid Build Coastguard Worker os.path.join(args.target_out_dir, f'{args.module_name}.swiftmodule'), 391*8975f5c5SAndroid Build Coastguard Worker '-emit-objc-header', 392*8975f5c5SAndroid Build Coastguard Worker '-emit-objc-header-path', 393*8975f5c5SAndroid Build Coastguard Worker header_path, 394*8975f5c5SAndroid Build Coastguard Worker '-working-directory', 395*8975f5c5SAndroid Build Coastguard Worker os.getcwd(), 396*8975f5c5SAndroid Build Coastguard Worker '-index-store-path', 397*8975f5c5SAndroid Build Coastguard Worker ensure_directory(os.path.join(build_cache_dir, 'Index.noindex')), 398*8975f5c5SAndroid Build Coastguard Worker '-module-cache-path', 399*8975f5c5SAndroid Build Coastguard Worker ensure_directory(os.path.join(build_cache_dir, 'ModuleCache.noindex')), 400*8975f5c5SAndroid Build Coastguard Worker '-pch-output-dir', 401*8975f5c5SAndroid Build Coastguard Worker ensure_directory(os.path.join(build_cache_dir, 'PrecompiledHeaders')), 402*8975f5c5SAndroid Build Coastguard Worker ] 403*8975f5c5SAndroid Build Coastguard Worker 404*8975f5c5SAndroid Build Coastguard Worker # Handle optional -bridge-header flag. 405*8975f5c5SAndroid Build Coastguard Worker if args.bridge_header: 406*8975f5c5SAndroid Build Coastguard Worker swiftc_args.extend(('-import-objc-header', args.bridge_header)) 407*8975f5c5SAndroid Build Coastguard Worker 408*8975f5c5SAndroid Build Coastguard Worker # Handle swift const values extraction. 409*8975f5c5SAndroid Build Coastguard Worker swiftc_args.extend(['-emit-const-values']) 410*8975f5c5SAndroid Build Coastguard Worker swiftc_args.extend([ 411*8975f5c5SAndroid Build Coastguard Worker '-Xfrontend', 412*8975f5c5SAndroid Build Coastguard Worker '-const-gather-protocols-file', 413*8975f5c5SAndroid Build Coastguard Worker '-Xfrontend', 414*8975f5c5SAndroid Build Coastguard Worker args.const_gather_protocols_file, 415*8975f5c5SAndroid Build Coastguard Worker ]) 416*8975f5c5SAndroid Build Coastguard Worker 417*8975f5c5SAndroid Build Coastguard Worker # Handle -I, -F, -isystem, -Fsystem and -D arguments. 418*8975f5c5SAndroid Build Coastguard Worker for (attr_name, forwarder) in ARGUMENT_FORWARDER_FOR_ATTR: 419*8975f5c5SAndroid Build Coastguard Worker forwarder.forward(swiftc_args, getattr(args, attr_name), args.target_triple) 420*8975f5c5SAndroid Build Coastguard Worker 421*8975f5c5SAndroid Build Coastguard Worker # Handle -whole-module-optimization flag. 422*8975f5c5SAndroid Build Coastguard Worker num_threads = max(1, multiprocessing.cpu_count() // 2) 423*8975f5c5SAndroid Build Coastguard Worker if args.whole_module_optimization: 424*8975f5c5SAndroid Build Coastguard Worker swiftc_args.extend([ 425*8975f5c5SAndroid Build Coastguard Worker '-whole-module-optimization', 426*8975f5c5SAndroid Build Coastguard Worker '-no-emit-module-separately-wmo', 427*8975f5c5SAndroid Build Coastguard Worker '-num-threads', 428*8975f5c5SAndroid Build Coastguard Worker f'{num_threads}', 429*8975f5c5SAndroid Build Coastguard Worker ]) 430*8975f5c5SAndroid Build Coastguard Worker else: 431*8975f5c5SAndroid Build Coastguard Worker swiftc_args.extend([ 432*8975f5c5SAndroid Build Coastguard Worker '-enable-batch-mode', 433*8975f5c5SAndroid Build Coastguard Worker '-incremental', 434*8975f5c5SAndroid Build Coastguard Worker '-experimental-emit-module-separately', 435*8975f5c5SAndroid Build Coastguard Worker '-disable-cmo', 436*8975f5c5SAndroid Build Coastguard Worker f'-j{num_threads}', 437*8975f5c5SAndroid Build Coastguard Worker ]) 438*8975f5c5SAndroid Build Coastguard Worker 439*8975f5c5SAndroid Build Coastguard Worker # Handle -file-prefix-map flag. 440*8975f5c5SAndroid Build Coastguard Worker if args.file_prefix_map: 441*8975f5c5SAndroid Build Coastguard Worker swiftc_args.extend([ 442*8975f5c5SAndroid Build Coastguard Worker '-file-prefix-map', 443*8975f5c5SAndroid Build Coastguard Worker args.file_prefix_map, 444*8975f5c5SAndroid Build Coastguard Worker ]) 445*8975f5c5SAndroid Build Coastguard Worker 446*8975f5c5SAndroid Build Coastguard Worker swift_toolchain_path = args.swift_toolchain_path 447*8975f5c5SAndroid Build Coastguard Worker if not swift_toolchain_path: 448*8975f5c5SAndroid Build Coastguard Worker swift_toolchain_path = os.path.join(os.path.dirname(args.sdk_path), 449*8975f5c5SAndroid Build Coastguard Worker 'XcodeDefault.xctoolchain') 450*8975f5c5SAndroid Build Coastguard Worker if not os.path.isdir(swift_toolchain_path): 451*8975f5c5SAndroid Build Coastguard Worker swift_toolchain_path = '' 452*8975f5c5SAndroid Build Coastguard Worker 453*8975f5c5SAndroid Build Coastguard Worker command = [f'{swift_toolchain_path}/usr/bin/swiftc'] + swiftc_args 454*8975f5c5SAndroid Build Coastguard Worker if extras_args: 455*8975f5c5SAndroid Build Coastguard Worker command.extend(extras_args) 456*8975f5c5SAndroid Build Coastguard Worker 457*8975f5c5SAndroid Build Coastguard Worker process = subprocess.Popen(command) 458*8975f5c5SAndroid Build Coastguard Worker process.communicate() 459*8975f5c5SAndroid Build Coastguard Worker 460*8975f5c5SAndroid Build Coastguard Worker if process.returncode: 461*8975f5c5SAndroid Build Coastguard Worker sys.exit(process.returncode) 462*8975f5c5SAndroid Build Coastguard Worker 463*8975f5c5SAndroid Build Coastguard Worker if args.fix_generated_header: 464*8975f5c5SAndroid Build Coastguard Worker fix_generated_header(header_path, 465*8975f5c5SAndroid Build Coastguard Worker args.header_path, 466*8975f5c5SAndroid Build Coastguard Worker src_dir=os.path.abspath(args.src_dir) + os.path.sep, 467*8975f5c5SAndroid Build Coastguard Worker gen_dir=os.path.abspath(args.gen_dir) + os.path.sep) 468*8975f5c5SAndroid Build Coastguard Worker 469*8975f5c5SAndroid Build Coastguard Worker 470*8975f5c5SAndroid Build Coastguard Workerdef generate_depfile(args, output_file_map): 471*8975f5c5SAndroid Build Coastguard Worker """Generates compilation depfile according to `args`. 472*8975f5c5SAndroid Build Coastguard Worker 473*8975f5c5SAndroid Build Coastguard Worker Parses all intermediate depfile generated by the Swift compiler and 474*8975f5c5SAndroid Build Coastguard Worker replaces absolute path by relative paths (since ninja compares paths 475*8975f5c5SAndroid Build Coastguard Worker as strings and does not resolve relative paths to absolute). 476*8975f5c5SAndroid Build Coastguard Worker 477*8975f5c5SAndroid Build Coastguard Worker Converts path to the SDK and toolchain files to the sdk/xcode_link 478*8975f5c5SAndroid Build Coastguard Worker symlinks if possible and available. 479*8975f5c5SAndroid Build Coastguard Worker """ 480*8975f5c5SAndroid Build Coastguard Worker xcode_paths = {} 481*8975f5c5SAndroid Build Coastguard Worker if os.path.islink(args.sdk_path): 482*8975f5c5SAndroid Build Coastguard Worker xcode_links = os.path.dirname(args.sdk_path) 483*8975f5c5SAndroid Build Coastguard Worker for link_name in os.listdir(xcode_links): 484*8975f5c5SAndroid Build Coastguard Worker link_path = os.path.join(xcode_links, link_name) 485*8975f5c5SAndroid Build Coastguard Worker if os.path.islink(link_path): 486*8975f5c5SAndroid Build Coastguard Worker xcode_paths[os.path.realpath(link_path) + os.sep] = link_path + os.sep 487*8975f5c5SAndroid Build Coastguard Worker 488*8975f5c5SAndroid Build Coastguard Worker out_dir = os.getcwd() + os.path.sep 489*8975f5c5SAndroid Build Coastguard Worker src_dir = os.path.abspath(args.src_dir) + os.path.sep 490*8975f5c5SAndroid Build Coastguard Worker 491*8975f5c5SAndroid Build Coastguard Worker depfile_content = collections.defaultdict(set) 492*8975f5c5SAndroid Build Coastguard Worker for value in output_file_map.values(): 493*8975f5c5SAndroid Build Coastguard Worker partial_depfile_path = value.get('dependencies', None) 494*8975f5c5SAndroid Build Coastguard Worker if partial_depfile_path: 495*8975f5c5SAndroid Build Coastguard Worker with open(partial_depfile_path, encoding='utf8') as stream: 496*8975f5c5SAndroid Build Coastguard Worker for line in stream: 497*8975f5c5SAndroid Build Coastguard Worker output, inputs = line.split(' : ', 2) 498*8975f5c5SAndroid Build Coastguard Worker output = os.path.relpath(output, out_dir) 499*8975f5c5SAndroid Build Coastguard Worker 500*8975f5c5SAndroid Build Coastguard Worker # The depfile format uses '\' to quote space in filename. Split the 501*8975f5c5SAndroid Build Coastguard Worker # list of file while respecting this convention. 502*8975f5c5SAndroid Build Coastguard Worker for path in re.split(r'(?<!\\) ', inputs): 503*8975f5c5SAndroid Build Coastguard Worker for xcode_path in xcode_paths: 504*8975f5c5SAndroid Build Coastguard Worker if path.startswith(xcode_path): 505*8975f5c5SAndroid Build Coastguard Worker path = xcode_paths[xcode_path] + path[len(xcode_path):] 506*8975f5c5SAndroid Build Coastguard Worker if path.startswith(src_dir) or path.startswith(out_dir): 507*8975f5c5SAndroid Build Coastguard Worker path = os.path.relpath(path, out_dir) 508*8975f5c5SAndroid Build Coastguard Worker depfile_content[output].add(path) 509*8975f5c5SAndroid Build Coastguard Worker 510*8975f5c5SAndroid Build Coastguard Worker with FileWriter(args.depfile_path) as stream: 511*8975f5c5SAndroid Build Coastguard Worker for output, inputs in sorted(depfile_content.items()): 512*8975f5c5SAndroid Build Coastguard Worker stream.write(f'{output}: {" ".join(sorted(inputs))}\n') 513*8975f5c5SAndroid Build Coastguard Worker 514*8975f5c5SAndroid Build Coastguard Worker 515*8975f5c5SAndroid Build Coastguard Workerdef compile_module(args, extras_args, build_signature): 516*8975f5c5SAndroid Build Coastguard Worker """Compiles Swift module according to `args`.""" 517*8975f5c5SAndroid Build Coastguard Worker for path in (args.target_out_dir, os.path.dirname(args.header_path)): 518*8975f5c5SAndroid Build Coastguard Worker ensure_directory(path) 519*8975f5c5SAndroid Build Coastguard Worker 520*8975f5c5SAndroid Build Coastguard Worker # Write the $module-OutputFileMap.json file. 521*8975f5c5SAndroid Build Coastguard Worker output_file_map = generate_output_file_map(args) 522*8975f5c5SAndroid Build Coastguard Worker output_file_map_path = os.path.join(args.target_out_dir, 523*8975f5c5SAndroid Build Coastguard Worker f'{args.module_name}-OutputFileMap.json') 524*8975f5c5SAndroid Build Coastguard Worker 525*8975f5c5SAndroid Build Coastguard Worker with FileWriter(output_file_map_path) as stream: 526*8975f5c5SAndroid Build Coastguard Worker json.dump(output_file_map, stream, indent=' ', sort_keys=True) 527*8975f5c5SAndroid Build Coastguard Worker 528*8975f5c5SAndroid Build Coastguard Worker # Invoke Swift compiler. 529*8975f5c5SAndroid Build Coastguard Worker with create_build_cache_dir(args, build_signature) as build_cache_dir: 530*8975f5c5SAndroid Build Coastguard Worker invoke_swift_compiler(args, 531*8975f5c5SAndroid Build Coastguard Worker extras_args, 532*8975f5c5SAndroid Build Coastguard Worker build_cache_dir=build_cache_dir, 533*8975f5c5SAndroid Build Coastguard Worker output_file_map=output_file_map_path) 534*8975f5c5SAndroid Build Coastguard Worker 535*8975f5c5SAndroid Build Coastguard Worker # Generate the depfile. 536*8975f5c5SAndroid Build Coastguard Worker generate_depfile(args, output_file_map) 537*8975f5c5SAndroid Build Coastguard Worker 538*8975f5c5SAndroid Build Coastguard Worker 539*8975f5c5SAndroid Build Coastguard Workerdef main(args): 540*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser(allow_abbrev=False, add_help=False) 541*8975f5c5SAndroid Build Coastguard Worker 542*8975f5c5SAndroid Build Coastguard Worker # Required arguments. 543*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--module-name', 544*8975f5c5SAndroid Build Coastguard Worker required=True, 545*8975f5c5SAndroid Build Coastguard Worker help='name of the Swift module') 546*8975f5c5SAndroid Build Coastguard Worker 547*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--src-dir', 548*8975f5c5SAndroid Build Coastguard Worker required=True, 549*8975f5c5SAndroid Build Coastguard Worker help='path to the source directory') 550*8975f5c5SAndroid Build Coastguard Worker 551*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--gen-dir', 552*8975f5c5SAndroid Build Coastguard Worker required=True, 553*8975f5c5SAndroid Build Coastguard Worker help='path to the gen directory root') 554*8975f5c5SAndroid Build Coastguard Worker 555*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--target-out-dir', 556*8975f5c5SAndroid Build Coastguard Worker required=True, 557*8975f5c5SAndroid Build Coastguard Worker help='path to the object directory') 558*8975f5c5SAndroid Build Coastguard Worker 559*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--header-path', 560*8975f5c5SAndroid Build Coastguard Worker required=True, 561*8975f5c5SAndroid Build Coastguard Worker help='path to the generated header file') 562*8975f5c5SAndroid Build Coastguard Worker 563*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--bridge-header', 564*8975f5c5SAndroid Build Coastguard Worker required=True, 565*8975f5c5SAndroid Build Coastguard Worker help='path to the Objective-C bridge header file') 566*8975f5c5SAndroid Build Coastguard Worker 567*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--depfile-path', 568*8975f5c5SAndroid Build Coastguard Worker required=True, 569*8975f5c5SAndroid Build Coastguard Worker help='path to the output dependency file') 570*8975f5c5SAndroid Build Coastguard Worker 571*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--const-gather-protocols-file', 572*8975f5c5SAndroid Build Coastguard Worker required=True, 573*8975f5c5SAndroid Build Coastguard Worker help='path to file containing const values protocols') 574*8975f5c5SAndroid Build Coastguard Worker 575*8975f5c5SAndroid Build Coastguard Worker # Optional arguments. 576*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--derived-data-dir', 577*8975f5c5SAndroid Build Coastguard Worker help='path to the derived data directory') 578*8975f5c5SAndroid Build Coastguard Worker 579*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--fix-generated-header', 580*8975f5c5SAndroid Build Coastguard Worker default=False, 581*8975f5c5SAndroid Build Coastguard Worker action='store_true', 582*8975f5c5SAndroid Build Coastguard Worker help='fix imports in generated header') 583*8975f5c5SAndroid Build Coastguard Worker 584*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--swift-toolchain-path', 585*8975f5c5SAndroid Build Coastguard Worker default='', 586*8975f5c5SAndroid Build Coastguard Worker help='path to the Swift toolchain to use') 587*8975f5c5SAndroid Build Coastguard Worker 588*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--whole-module-optimization', 589*8975f5c5SAndroid Build Coastguard Worker default=False, 590*8975f5c5SAndroid Build Coastguard Worker action='store_true', 591*8975f5c5SAndroid Build Coastguard Worker help='enable whole module optimisation') 592*8975f5c5SAndroid Build Coastguard Worker 593*8975f5c5SAndroid Build Coastguard Worker # Required arguments (forwarded to the Swift compiler). 594*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-target', 595*8975f5c5SAndroid Build Coastguard Worker required=True, 596*8975f5c5SAndroid Build Coastguard Worker dest='target_triple', 597*8975f5c5SAndroid Build Coastguard Worker help='generate code for the given target') 598*8975f5c5SAndroid Build Coastguard Worker 599*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-sdk', 600*8975f5c5SAndroid Build Coastguard Worker required=True, 601*8975f5c5SAndroid Build Coastguard Worker dest='sdk_path', 602*8975f5c5SAndroid Build Coastguard Worker help='path to the iOS SDK') 603*8975f5c5SAndroid Build Coastguard Worker 604*8975f5c5SAndroid Build Coastguard Worker # Optional arguments (forwarded to the Swift compiler). 605*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-I', 606*8975f5c5SAndroid Build Coastguard Worker action='append', 607*8975f5c5SAndroid Build Coastguard Worker dest='include_dirs', 608*8975f5c5SAndroid Build Coastguard Worker help='add directory to header search path') 609*8975f5c5SAndroid Build Coastguard Worker 610*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-isystem', 611*8975f5c5SAndroid Build Coastguard Worker action='append', 612*8975f5c5SAndroid Build Coastguard Worker dest='system_include_dirs', 613*8975f5c5SAndroid Build Coastguard Worker help='add directory to system header search path') 614*8975f5c5SAndroid Build Coastguard Worker 615*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-F', 616*8975f5c5SAndroid Build Coastguard Worker action='append', 617*8975f5c5SAndroid Build Coastguard Worker dest='framework_dirs', 618*8975f5c5SAndroid Build Coastguard Worker help='add directory to framework search path') 619*8975f5c5SAndroid Build Coastguard Worker 620*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-Fsystem', 621*8975f5c5SAndroid Build Coastguard Worker action='append', 622*8975f5c5SAndroid Build Coastguard Worker dest='system_framework_dirs', 623*8975f5c5SAndroid Build Coastguard Worker help='add directory to system framework search path') 624*8975f5c5SAndroid Build Coastguard Worker 625*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-D', 626*8975f5c5SAndroid Build Coastguard Worker action='append', 627*8975f5c5SAndroid Build Coastguard Worker dest='defines', 628*8975f5c5SAndroid Build Coastguard Worker help='add preprocessor define') 629*8975f5c5SAndroid Build Coastguard Worker 630*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-swift-version', 631*8975f5c5SAndroid Build Coastguard Worker default='5', 632*8975f5c5SAndroid Build Coastguard Worker help='version of the Swift language') 633*8975f5c5SAndroid Build Coastguard Worker 634*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 635*8975f5c5SAndroid Build Coastguard Worker '-file-prefix-map', 636*8975f5c5SAndroid Build Coastguard Worker help='remap source paths in debug, coverage, and index info') 637*8975f5c5SAndroid Build Coastguard Worker 638*8975f5c5SAndroid Build Coastguard Worker # Positional arguments. 639*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('sources', 640*8975f5c5SAndroid Build Coastguard Worker nargs='+', 641*8975f5c5SAndroid Build Coastguard Worker help='Swift source files to compile') 642*8975f5c5SAndroid Build Coastguard Worker 643*8975f5c5SAndroid Build Coastguard Worker parsed, extras = parser.parse_known_args(args) 644*8975f5c5SAndroid Build Coastguard Worker compile_module(parsed, extras, build_signature(os.environ, args)) 645*8975f5c5SAndroid Build Coastguard Worker 646*8975f5c5SAndroid Build Coastguard Worker 647*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 648*8975f5c5SAndroid Build Coastguard Worker sys.exit(main(sys.argv[1:])) 649