16d528ed9Sopenharmony_ci#!/usr/bin/python3 26d528ed9Sopenharmony_ci 36d528ed9Sopenharmony_ci 46d528ed9Sopenharmony_ciimport argparse 56d528ed9Sopenharmony_ciimport collections 66d528ed9Sopenharmony_ciimport json 76d528ed9Sopenharmony_ciimport os 86d528ed9Sopenharmony_ciimport subprocess 96d528ed9Sopenharmony_ciimport sys 106d528ed9Sopenharmony_ciimport tempfile 116d528ed9Sopenharmony_ci 126d528ed9Sopenharmony_ci 136d528ed9Sopenharmony_ciclass OrderedSet(collections.OrderedDict): 146d528ed9Sopenharmony_ci 156d528ed9Sopenharmony_ci def add(self, value): 166d528ed9Sopenharmony_ci self[value] = True 176d528ed9Sopenharmony_ci 186d528ed9Sopenharmony_ci 196d528ed9Sopenharmony_cidef compile_module(module, sources, settings, extras, tmpdir): 206d528ed9Sopenharmony_ci output_file_map = {} 216d528ed9Sopenharmony_ci if settings.whole_module_optimization: 226d528ed9Sopenharmony_ci output_file_map[''] = { 236d528ed9Sopenharmony_ci 'object': os.path.join(settings.object_dir, module + '.o'), 246d528ed9Sopenharmony_ci 'dependencies': os.path.join(tmpdir, module + '.d'), 256d528ed9Sopenharmony_ci } 266d528ed9Sopenharmony_ci else: 276d528ed9Sopenharmony_ci for source in sources: 286d528ed9Sopenharmony_ci name, _ = os.path.splitext(os.path.basename(source)) 296d528ed9Sopenharmony_ci output_file_map[source] = { 306d528ed9Sopenharmony_ci 'object': os.path.join(settings.object_dir, name + '.o'), 316d528ed9Sopenharmony_ci 'dependencies': os.path.join(tmpdir, name + '.d'), 326d528ed9Sopenharmony_ci } 336d528ed9Sopenharmony_ci 346d528ed9Sopenharmony_ci for key in ('module_path', 'header_path', 'depfile'): 356d528ed9Sopenharmony_ci path = getattr(settings, key) 366d528ed9Sopenharmony_ci if os.path.exists(path): 376d528ed9Sopenharmony_ci os.unlink(path) 386d528ed9Sopenharmony_ci if key == 'module_path': 396d528ed9Sopenharmony_ci for ext in '.swiftdoc', '.swiftsourceinfo': 406d528ed9Sopenharmony_ci path = os.path.splitext(getattr(settings, key))[0] + ext 416d528ed9Sopenharmony_ci if os.path.exists(path): 426d528ed9Sopenharmony_ci os.unlink(path) 436d528ed9Sopenharmony_ci directory = os.path.dirname(path) 446d528ed9Sopenharmony_ci if not os.path.exists(directory): 456d528ed9Sopenharmony_ci os.makedirs(directory) 466d528ed9Sopenharmony_ci 476d528ed9Sopenharmony_ci if not os.path.exists(settings.object_dir): 486d528ed9Sopenharmony_ci os.makedirs(settings.object_dir) 496d528ed9Sopenharmony_ci 506d528ed9Sopenharmony_ci for key in output_file_map: 516d528ed9Sopenharmony_ci path = output_file_map[key]['object'] 526d528ed9Sopenharmony_ci if os.path.exists(path): 536d528ed9Sopenharmony_ci os.unlink(path) 546d528ed9Sopenharmony_ci 556d528ed9Sopenharmony_ci output_file_map_path = os.path.join(tmpdir, module + '.json') 566d528ed9Sopenharmony_ci with open(output_file_map_path, 'w') as output_file_map_file: 576d528ed9Sopenharmony_ci output_file_map_file.write(json.dumps(output_file_map)) 586d528ed9Sopenharmony_ci output_file_map_file.flush() 596d528ed9Sopenharmony_ci 606d528ed9Sopenharmony_ci extra_args = [] 616d528ed9Sopenharmony_ci if settings.bridge_header: 626d528ed9Sopenharmony_ci extra_args.extend([ 636d528ed9Sopenharmony_ci '-import-objc-header', 646d528ed9Sopenharmony_ci os.path.abspath(settings.bridge_header), 656d528ed9Sopenharmony_ci ]) 666d528ed9Sopenharmony_ci 676d528ed9Sopenharmony_ci if settings.whole_module_optimization: 686d528ed9Sopenharmony_ci extra_args.append('-whole-module-optimization') 696d528ed9Sopenharmony_ci 706d528ed9Sopenharmony_ci if settings.target: 716d528ed9Sopenharmony_ci extra_args.extend([ 726d528ed9Sopenharmony_ci '-target', 736d528ed9Sopenharmony_ci settings.target, 746d528ed9Sopenharmony_ci ]) 756d528ed9Sopenharmony_ci 766d528ed9Sopenharmony_ci if settings.sdk: 776d528ed9Sopenharmony_ci extra_args.extend([ 786d528ed9Sopenharmony_ci '-sdk', 796d528ed9Sopenharmony_ci os.path.abspath(settings.sdk), 806d528ed9Sopenharmony_ci ]) 816d528ed9Sopenharmony_ci 826d528ed9Sopenharmony_ci if settings.include_dirs: 836d528ed9Sopenharmony_ci for include_dir in settings.include_dirs: 846d528ed9Sopenharmony_ci extra_args.append('-I' + include_dir) 856d528ed9Sopenharmony_ci 866d528ed9Sopenharmony_ci process = subprocess.Popen( 876d528ed9Sopenharmony_ci ['swiftc', 886d528ed9Sopenharmony_ci '-parse-as-library', 896d528ed9Sopenharmony_ci '-module-name', 906d528ed9Sopenharmony_ci module, 916d528ed9Sopenharmony_ci '-emit-object', 926d528ed9Sopenharmony_ci '-emit-dependencies', 936d528ed9Sopenharmony_ci '-emit-module', 946d528ed9Sopenharmony_ci '-emit-module-path', 956d528ed9Sopenharmony_ci settings.module_path, 966d528ed9Sopenharmony_ci '-emit-objc-header', 976d528ed9Sopenharmony_ci '-emit-objc-header-path', 986d528ed9Sopenharmony_ci settings.header_path, 996d528ed9Sopenharmony_ci '-output-file-map', 1006d528ed9Sopenharmony_ci output_file_map_path, 1016d528ed9Sopenharmony_ci ] + extra_args + extras + sources, 1026d528ed9Sopenharmony_ci stdout=subprocess.PIPE, stderr=subprocess.PIPE, 1036d528ed9Sopenharmony_ci universal_newlines=True) 1046d528ed9Sopenharmony_ci 1056d528ed9Sopenharmony_ci stdout, stderr = process.communicate() 1066d528ed9Sopenharmony_ci if process.returncode: 1076d528ed9Sopenharmony_ci sys.stdout.write(stdout) 1086d528ed9Sopenharmony_ci sys.stderr.write(stderr) 1096d528ed9Sopenharmony_ci sys.exit(process.returncode) 1106d528ed9Sopenharmony_ci 1116d528ed9Sopenharmony_ci 1126d528ed9Sopenharmony_ci depfile_content = collections.OrderedDict() 1136d528ed9Sopenharmony_ci for key in output_file_map: 1146d528ed9Sopenharmony_ci for line in open(output_file_map[key]['dependencies']): 1156d528ed9Sopenharmony_ci output, inputs = line.split(' : ', 2) 1166d528ed9Sopenharmony_ci _, ext = os.path.splitext(output) 1176d528ed9Sopenharmony_ci if ext == '.o': 1186d528ed9Sopenharmony_ci key = output 1196d528ed9Sopenharmony_ci else: 1206d528ed9Sopenharmony_ci key = os.path.splitext(settings.module_path)[0] + ext 1216d528ed9Sopenharmony_ci if key not in depfile_content: 1226d528ed9Sopenharmony_ci depfile_content[key] = OrderedSet() 1236d528ed9Sopenharmony_ci for path in inputs.split(): 1246d528ed9Sopenharmony_ci depfile_content[key].add(path) 1256d528ed9Sopenharmony_ci 1266d528ed9Sopenharmony_ci with open(settings.depfile, 'w') as depfile: 1276d528ed9Sopenharmony_ci for key in depfile_content: 1286d528ed9Sopenharmony_ci if not settings.depfile_filter or key in settings.depfile_filter: 1296d528ed9Sopenharmony_ci inputs = depfile_content[key] 1306d528ed9Sopenharmony_ci depfile.write('%s : %s\n' % (key, ' '.join(inputs))) 1316d528ed9Sopenharmony_ci 1326d528ed9Sopenharmony_ci 1336d528ed9Sopenharmony_cidef main(args): 1346d528ed9Sopenharmony_ci parser = argparse.ArgumentParser(add_help=False) 1356d528ed9Sopenharmony_ci parser.add_argument( 1366d528ed9Sopenharmony_ci '--module-name', 1376d528ed9Sopenharmony_ci help='name of the Swift module') 1386d528ed9Sopenharmony_ci parser.add_argument( 1396d528ed9Sopenharmony_ci '--include', '-I', action='append', dest='include_dirs', 1406d528ed9Sopenharmony_ci help='add directory to header search path') 1416d528ed9Sopenharmony_ci parser.add_argument( 1426d528ed9Sopenharmony_ci 'sources', nargs='+', 1436d528ed9Sopenharmony_ci help='Swift source file to compile') 1446d528ed9Sopenharmony_ci parser.add_argument( 1456d528ed9Sopenharmony_ci '--whole-module-optimization', action='store_true', 1466d528ed9Sopenharmony_ci help='enable whole module optimization') 1476d528ed9Sopenharmony_ci parser.add_argument( 1486d528ed9Sopenharmony_ci '--object-dir', '-o', 1496d528ed9Sopenharmony_ci help='path to the generated object files directory') 1506d528ed9Sopenharmony_ci parser.add_argument( 1516d528ed9Sopenharmony_ci '--module-path', '-m', 1526d528ed9Sopenharmony_ci help='path to the generated module file') 1536d528ed9Sopenharmony_ci parser.add_argument( 1546d528ed9Sopenharmony_ci '--header-path', '-h', 1556d528ed9Sopenharmony_ci help='path to the generated header file') 1566d528ed9Sopenharmony_ci parser.add_argument( 1576d528ed9Sopenharmony_ci '--bridge-header', '-b', 1586d528ed9Sopenharmony_ci help='path to the Objective-C bridge header') 1596d528ed9Sopenharmony_ci parser.add_argument( 1606d528ed9Sopenharmony_ci '--depfile', '-d', 1616d528ed9Sopenharmony_ci help='path to the generated depfile') 1626d528ed9Sopenharmony_ci parser.add_argument( 1636d528ed9Sopenharmony_ci '--depfile-filter', action='append', 1646d528ed9Sopenharmony_ci help='limit depfile to those files') 1656d528ed9Sopenharmony_ci parser.add_argument( 1666d528ed9Sopenharmony_ci '--target', action='store', 1676d528ed9Sopenharmony_ci help='generate code for the given target <triple>') 1686d528ed9Sopenharmony_ci parser.add_argument( 1696d528ed9Sopenharmony_ci '--sdk', action='store', 1706d528ed9Sopenharmony_ci help='compile against sdk') 1716d528ed9Sopenharmony_ci 1726d528ed9Sopenharmony_ci parsed, extras = parser.parse_known_args(args) 1736d528ed9Sopenharmony_ci with tempfile.TemporaryDirectory() as tmpdir: 1746d528ed9Sopenharmony_ci compile_module( 1756d528ed9Sopenharmony_ci parsed.module_name, 1766d528ed9Sopenharmony_ci parsed.sources, 1776d528ed9Sopenharmony_ci parsed, 1786d528ed9Sopenharmony_ci extras, 1796d528ed9Sopenharmony_ci tmpdir) 1806d528ed9Sopenharmony_ci 1816d528ed9Sopenharmony_ci 1826d528ed9Sopenharmony_ciif __name__ == '__main__': 1836d528ed9Sopenharmony_ci sys.exit(main(sys.argv[1:])) 184