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 |