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