Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Creates windows and posix stub files for a given set of signatures. | 6 """Creates windows and posix stub files for a given set of signatures. |
| 7 | 7 |
| 8 For libraries that need to be loaded outside of the standard executable startup | 8 For libraries that need to be loaded outside of the standard executable startup |
| 9 path mechanism, stub files need to be generated for the wanted functions. In | 9 path mechanism, stub files need to be generated for the wanted functions. In |
| 10 windows, this is done via "def" files and the delay load mechanism. On a posix | 10 windows, this is done via "def" files and the delay load mechanism. On a posix |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 # Trailing characters should have a substring matching the form (.*). That | 69 # Trailing characters should have a substring matching the form (.*). That |
| 70 # is considered the arguments. | 70 # is considered the arguments. |
| 71 SIGNATURE_REGEX = re.compile('(?P<return_type>.+?)' | 71 SIGNATURE_REGEX = re.compile('(?P<return_type>.+?)' |
| 72 '(?P<name>[_a-zA-Z][_a-zA-Z0-9]+)\s*' | 72 '(?P<name>[_a-zA-Z][_a-zA-Z0-9]+)\s*' |
| 73 '\((?P<params>.*?)\)') | 73 '\((?P<params>.*?)\)') |
| 74 | 74 |
| 75 # Used for generating C++ identifiers. | 75 # Used for generating C++ identifiers. |
| 76 INVALID_C_IDENT_CHARS = re.compile('[^_a-zA-Z0-9]') | 76 INVALID_C_IDENT_CHARS = re.compile('[^_a-zA-Z0-9]') |
| 77 | 77 |
| 78 # Constants defning the supported file types options. | 78 # Constants defning the supported file types options. |
| 79 FILE_TYPE_WIN = 'windows_lib' | 79 FILE_TYPE_WIN_X86 = 'windows_lib' |
| 80 FILE_TYPE_WIN_X64 = 'windows_lib_x64' | |
| 80 FILE_TYPE_POSIX_STUB = 'posix_stubs' | 81 FILE_TYPE_POSIX_STUB = 'posix_stubs' |
| 81 FILE_TYPE_WIN_DEF = 'windows_def' | 82 FILE_TYPE_WIN_DEF = 'windows_def' |
| 82 | 83 |
| 83 # Template for generating a stub function definition. Includes a forward | 84 # Template for generating a stub function definition. Includes a forward |
| 84 # declaration marking the symbol as weak. This template takes the following | 85 # declaration marking the symbol as weak. This template takes the following |
| 85 # named parameters. | 86 # named parameters. |
| 86 # return_type: The return type. | 87 # return_type: The return type. |
| 87 # name: The name of the function. | 88 # name: The name of the function. |
| 88 # params: The parameters to the function. | 89 # params: The parameters to the function. |
| 89 # return_prefix: 'return ' if this function is not void. '' otherwise. | 90 # return_prefix: 'return ' if this function is not void. '' otherwise. |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 """Invoke |args| as command via subprocess.Popen, filtering lines starting | 446 """Invoke |args| as command via subprocess.Popen, filtering lines starting |
| 446 with |filter|.""" | 447 with |filter|.""" |
| 447 popen = subprocess.Popen(args, stdout=subprocess.PIPE) | 448 popen = subprocess.Popen(args, stdout=subprocess.PIPE) |
| 448 out, _ = popen.communicate() | 449 out, _ = popen.communicate() |
| 449 for line in out.splitlines(): | 450 for line in out.splitlines(): |
| 450 if not filter or not line.startswith(filter): | 451 if not filter or not line.startswith(filter): |
| 451 write_to.write(line + '\n') | 452 write_to.write(line + '\n') |
| 452 return popen.returncode | 453 return popen.returncode |
| 453 | 454 |
| 454 | 455 |
| 455 def CreateWindowsLib(module_name, signatures, intermediate_dir, outdir_path): | 456 def CreateWindowsLib(module_name, signatures, intermediate_dir, outdir_path, |
| 457 machine): | |
| 456 """Creates a windows library file. | 458 """Creates a windows library file. |
| 457 | 459 |
| 458 Calling this function will create a lib file in the outdir_path that exports | 460 Calling this function will create a lib file in the outdir_path that exports |
| 459 the signatures passed into the object. A temporary def file will be created | 461 the signatures passed into the object. A temporary def file will be created |
| 460 in the intermediate_dir. | 462 in the intermediate_dir. |
| 461 | 463 |
| 462 Args: | 464 Args: |
| 463 module_name: The name of the module we are writing a stub for. | 465 module_name: The name of the module we are writing a stub for. |
| 464 signatures: The list of signature hashes, as produced by ParseSignatures, | 466 signatures: The list of signature hashes, as produced by ParseSignatures, |
| 465 to create stubs for. | 467 to create stubs for. |
| 466 intermediate_dir: The directory where the generated .def files should go. | 468 intermediate_dir: The directory where the generated .def files should go. |
| 467 outdir_path: The directory where generated .lib files should go. | 469 outdir_path: The directory where generated .lib files should go. |
| 470 machine: String holding the machine type, 'X86' or 'X64'. | |
| 468 | 471 |
| 469 Raises: | 472 Raises: |
| 470 SubprocessError: If invoking the windows "lib" tool fails, this is raised | 473 SubprocessError: If invoking the windows "lib" tool fails, this is raised |
| 471 with the error code. | 474 with the error code. |
| 472 """ | 475 """ |
| 473 def_file_path = os.path.join(intermediate_dir, | 476 def_file_path = os.path.join(intermediate_dir, |
| 474 module_name + '.def') | 477 module_name + '.def') |
| 475 lib_file_path = os.path.join(outdir_path, | 478 lib_file_path = os.path.join(outdir_path, |
| 476 module_name + '.lib') | 479 module_name + '.lib') |
| 477 outfile = open(def_file_path, 'w') | 480 outfile = open(def_file_path, 'w') |
| 478 try: | 481 try: |
| 479 WriteWindowsDefFile(module_name, signatures, outfile) | 482 WriteWindowsDefFile(module_name, signatures, outfile) |
| 480 finally: | 483 finally: |
| 481 outfile.close() | 484 outfile.close() |
| 482 | 485 |
| 483 # Invoke the "lib" program on Windows to create stub .lib files for the | 486 # Invoke the "lib" program on Windows to create stub .lib files for the |
| 484 # generated definitions. These .lib files can then be used during | 487 # generated definitions. These .lib files can then be used during |
| 485 # delayloading of the dynamic libraries. | 488 # delayloading of the dynamic libraries. |
| 486 ret = QuietRun(['lib', '/nologo', '/machine:X86', | 489 ret = QuietRun(['lib', '/nologo', |
| 490 '/machine:' + machine, | |
| 487 '/def:' + def_file_path, | 491 '/def:' + def_file_path, |
| 488 '/out:' + lib_file_path], | 492 '/out:' + lib_file_path], |
| 489 filter=' Creating library') | 493 filter=' Creating library') |
| 490 if ret != 0: | 494 if ret != 0: |
| 491 raise SubprocessError( | 495 raise SubprocessError( |
| 492 'Failed creating %s for %s' % (lib_file_path, def_file_path), | 496 'Failed creating %s for %s' % (lib_file_path, def_file_path), |
| 493 ret) | 497 ret) |
| 494 | 498 |
| 495 | 499 |
| 496 class PosixStubWriter(object): | 500 class PosixStubWriter(object): |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 874 help='Output location.') | 878 help='Output location.') |
| 875 parser.add_option('-i', | 879 parser.add_option('-i', |
| 876 '--intermediate_dir', | 880 '--intermediate_dir', |
| 877 dest='intermediate_dir', | 881 dest='intermediate_dir', |
| 878 default=None, | 882 default=None, |
| 879 help=('Location of intermediate files. Ignored for %s type' | 883 help=('Location of intermediate files. Ignored for %s type' |
| 880 % FILE_TYPE_WIN_DEF)) | 884 % FILE_TYPE_WIN_DEF)) |
| 881 parser.add_option('-t', | 885 parser.add_option('-t', |
| 882 '--type', | 886 '--type', |
| 883 dest='type', | 887 dest='type', |
| 884 default=None, | 888 default=None, |
|
DaleCurtis
2013/02/01 19:07:40
I think you'll need to keep the old FILE_TYPE_WIN
wolenetz
2013/02/01 19:16:21
The neat bit about this change is that I actually
| |
| 885 help=('Type of file. Valid types are "%s" or "%s" or "%s"' % | 889 help=('Type of file. Valid types are "%s" or "%s" or "%s" ' |
| 886 (FILE_TYPE_POSIX_STUB, FILE_TYPE_WIN, | 890 'or "%s"' % |
| 887 FILE_TYPE_WIN_DEF))) | 891 (FILE_TYPE_POSIX_STUB, FILE_TYPE_WIN_X86, |
| 892 FILE_TYPE_WIN_X64, FILE_TYPE_WIN_DEF))) | |
| 888 parser.add_option('-s', | 893 parser.add_option('-s', |
| 889 '--stubfile_name', | 894 '--stubfile_name', |
| 890 dest='stubfile_name', | 895 dest='stubfile_name', |
| 891 default=None, | 896 default=None, |
| 892 help=('Name of posix_stubs output file. Only valid with ' | 897 help=('Name of posix_stubs output file. Only valid with ' |
| 893 '%s type.' % FILE_TYPE_POSIX_STUB)) | 898 '%s type.' % FILE_TYPE_POSIX_STUB)) |
| 894 parser.add_option('-p', | 899 parser.add_option('-p', |
| 895 '--path_from_source', | 900 '--path_from_source', |
| 896 dest='path_from_source', | 901 dest='path_from_source', |
| 897 default=None, | 902 default=None, |
| 898 help=('The relative path from the project root that the ' | 903 help=('The relative path from the project root that the ' |
| 899 'generated file should consider itself part of (eg. ' | 904 'generated file should consider itself part of (eg. ' |
| 900 'third_party/ffmpeg). This is used to generate the ' | 905 'third_party/ffmpeg). This is used to generate the ' |
| 901 'header guard and namespace for our initializer ' | 906 'header guard and namespace for our initializer ' |
| 902 'functions and does NOT affect the physical output ' | 907 'functions and does NOT affect the physical output ' |
| 903 'location of the file like -o does. Ignored for ' | 908 'location of the file like -o does. Ignored for ' |
| 904 ' %s type.' % FILE_TYPE_WIN)) | 909 '%s and %s types.' % |
| 910 (FILE_TYPE_WIN_X86, FILE_TYPE_WIN_X64))) | |
| 905 parser.add_option('-e', | 911 parser.add_option('-e', |
| 906 '--extra_stub_header', | 912 '--extra_stub_header', |
| 907 dest='extra_stub_header', | 913 dest='extra_stub_header', |
| 908 default=None, | 914 default=None, |
| 909 help=('File to insert after the system includes in the ' | 915 help=('File to insert after the system includes in the ' |
| 910 'generated stub implemenation file. Ignored for ' | 916 'generated stub implemenation file. Ignored for ' |
| 911 '%s type.' % FILE_TYPE_WIN)) | 917 '%s and %s types.' % |
| 918 (FILE_TYPE_WIN_X86, FILE_TYPE_WIN_X64))) | |
| 912 parser.add_option('-m', | 919 parser.add_option('-m', |
| 913 '--module_name', | 920 '--module_name', |
| 914 dest='module_name', | 921 dest='module_name', |
| 915 default=None, | 922 default=None, |
| 916 help=('Name of output DLL or LIB for DEF creation using ' | 923 help=('Name of output DLL or LIB for DEF creation using ' |
| 917 '%s type.' % FILE_TYPE_WIN_DEF)) | 924 '%s type.' % FILE_TYPE_WIN_DEF)) |
| 918 | 925 |
| 919 return parser | 926 return parser |
| 920 | 927 |
| 921 | 928 |
| 922 def ParseOptions(): | 929 def ParseOptions(): |
| 923 """Parses the options and terminates program if they are not sane. | 930 """Parses the options and terminates program if they are not sane. |
| 924 | 931 |
| 925 Returns: | 932 Returns: |
| 926 The pair (optparse.OptionValues, [string]), that is the output of | 933 The pair (optparse.OptionValues, [string]), that is the output of |
| 927 a successful call to parser.parse_args(). | 934 a successful call to parser.parse_args(). |
| 928 """ | 935 """ |
| 929 parser = CreateOptionParser() | 936 parser = CreateOptionParser() |
| 930 options, args = parser.parse_args() | 937 options, args = parser.parse_args() |
| 931 | 938 |
| 932 if not args: | 939 if not args: |
| 933 parser.error('No inputs specified') | 940 parser.error('No inputs specified') |
| 934 | 941 |
| 935 if options.out_dir is None: | 942 if options.out_dir is None: |
| 936 parser.error('Output location not specified') | 943 parser.error('Output location not specified') |
| 937 | 944 |
| 938 if (options.type not in | 945 if (options.type not in |
| 939 [FILE_TYPE_WIN, FILE_TYPE_POSIX_STUB, FILE_TYPE_WIN_DEF]): | 946 [FILE_TYPE_WIN_X86, FILE_TYPE_WIN_X64, FILE_TYPE_POSIX_STUB, |
| 947 FILE_TYPE_WIN_DEF]): | |
| 940 parser.error('Invalid output file type: %s' % options.type) | 948 parser.error('Invalid output file type: %s' % options.type) |
| 941 | 949 |
| 942 if options.type == FILE_TYPE_POSIX_STUB: | 950 if options.type == FILE_TYPE_POSIX_STUB: |
| 943 if options.stubfile_name is None: | 951 if options.stubfile_name is None: |
| 944 parser.error('Output file name needed for %s' % FILE_TYPE_POSIX_STUB) | 952 parser.error('Output file name needed for %s' % FILE_TYPE_POSIX_STUB) |
| 945 if options.path_from_source is None: | 953 if options.path_from_source is None: |
| 946 parser.error('Path from source needed for %s' % FILE_TYPE_POSIX_STUB) | 954 parser.error('Path from source needed for %s' % FILE_TYPE_POSIX_STUB) |
| 947 | 955 |
| 948 if options.type == FILE_TYPE_WIN_DEF: | 956 if options.type == FILE_TYPE_WIN_DEF: |
| 949 if options.module_name is None: | 957 if options.module_name is None: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 981 intermediate_dir = os.path.normpath(options.intermediate_dir) | 989 intermediate_dir = os.path.normpath(options.intermediate_dir) |
| 982 if intermediate_dir is None: | 990 if intermediate_dir is None: |
| 983 intermediate_dir = out_dir | 991 intermediate_dir = out_dir |
| 984 | 992 |
| 985 EnsureDirExists(out_dir) | 993 EnsureDirExists(out_dir) |
| 986 EnsureDirExists(intermediate_dir) | 994 EnsureDirExists(intermediate_dir) |
| 987 | 995 |
| 988 return out_dir, intermediate_dir | 996 return out_dir, intermediate_dir |
| 989 | 997 |
| 990 | 998 |
| 991 def CreateWindowsLibForSigFiles(sig_files, out_dir, intermediate_dir): | 999 def CreateWindowsLibForSigFiles(sig_files, out_dir, intermediate_dir, machine): |
| 992 """For each signature file, create a windows lib. | 1000 """For each signature file, create a windows lib. |
| 993 | 1001 |
| 994 Args: | 1002 Args: |
| 995 sig_files: Array of strings with the paths to each signature file. | 1003 sig_files: Array of strings with the paths to each signature file. |
| 996 out_dir: String holding path to directory where the generated libs go. | 1004 out_dir: String holding path to directory where the generated libs go. |
| 997 intermediate_dir: String holding path to directory generated intermdiate | 1005 intermediate_dir: String holding path to directory generated intermdiate |
| 998 artifacts. | 1006 artifacts. |
| 1007 machine: String holding the machine type, 'X86' or 'X64'. | |
| 999 """ | 1008 """ |
| 1000 for input_path in sig_files: | 1009 for input_path in sig_files: |
| 1001 infile = open(input_path, 'r') | 1010 infile = open(input_path, 'r') |
| 1002 try: | 1011 try: |
| 1003 signatures = ParseSignatures(infile) | 1012 signatures = ParseSignatures(infile) |
| 1004 module_name = ExtractModuleName(os.path.basename(input_path)) | 1013 module_name = ExtractModuleName(os.path.basename(input_path)) |
| 1005 CreateWindowsLib(module_name, signatures, intermediate_dir, out_dir) | 1014 CreateWindowsLib(module_name, signatures, intermediate_dir, out_dir, |
| 1015 machine) | |
| 1006 finally: | 1016 finally: |
| 1007 infile.close() | 1017 infile.close() |
| 1008 | 1018 |
| 1009 | 1019 |
| 1010 def CreateWindowsDefForSigFiles(sig_files, out_dir, module_name): | 1020 def CreateWindowsDefForSigFiles(sig_files, out_dir, module_name): |
| 1011 """For all signature files, create a single windows def file. | 1021 """For all signature files, create a single windows def file. |
| 1012 | 1022 |
| 1013 Args: | 1023 Args: |
| 1014 sig_files: Array of strings with the paths to each signature file. | 1024 sig_files: Array of strings with the paths to each signature file. |
| 1015 out_dir: String holding path to directory where the generated def goes. | 1025 out_dir: String holding path to directory where the generated def goes. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1098 PosixStubWriter.WriteHeaderContents(module_names, namespace, | 1108 PosixStubWriter.WriteHeaderContents(module_names, namespace, |
| 1099 header_guard, header_file) | 1109 header_guard, header_file) |
| 1100 finally: | 1110 finally: |
| 1101 header_file.close() | 1111 header_file.close() |
| 1102 | 1112 |
| 1103 | 1113 |
| 1104 def main(): | 1114 def main(): |
| 1105 options, args = ParseOptions() | 1115 options, args = ParseOptions() |
| 1106 out_dir, intermediate_dir = CreateOutputDirectories(options) | 1116 out_dir, intermediate_dir = CreateOutputDirectories(options) |
| 1107 | 1117 |
| 1108 if options.type == FILE_TYPE_WIN: | 1118 if options.type == FILE_TYPE_WIN_X86: |
| 1109 CreateWindowsLibForSigFiles(args, out_dir, intermediate_dir) | 1119 CreateWindowsLibForSigFiles(args, out_dir, intermediate_dir, 'X86') |
| 1120 elif options.type == FILE_TYPE_WIN_X64: | |
| 1121 CreateWindowsLibForSigFiles(args, out_dir, intermediate_dir, 'X64') | |
| 1110 elif options.type == FILE_TYPE_POSIX_STUB: | 1122 elif options.type == FILE_TYPE_POSIX_STUB: |
| 1111 CreatePosixStubsForSigFiles(args, options.stubfile_name, out_dir, | 1123 CreatePosixStubsForSigFiles(args, options.stubfile_name, out_dir, |
| 1112 intermediate_dir, options.path_from_source, | 1124 intermediate_dir, options.path_from_source, |
| 1113 options.extra_stub_header) | 1125 options.extra_stub_header) |
| 1114 elif options.type == FILE_TYPE_WIN_DEF: | 1126 elif options.type == FILE_TYPE_WIN_DEF: |
| 1115 CreateWindowsDefForSigFiles(args, out_dir, options.module_name) | 1127 CreateWindowsDefForSigFiles(args, out_dir, options.module_name) |
| 1116 | 1128 |
| 1117 | 1129 |
| 1118 if __name__ == '__main__': | 1130 if __name__ == '__main__': |
| 1119 main() | 1131 main() |
| OLD | NEW |