| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (C) 2013 Google Inc. All rights reserved. | 2 # Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 # | 3 # |
| 4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
| 5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
| 6 # met: | 6 # met: |
| 7 # | 7 # |
| 8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
| 9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
| 10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 | 52 |
| 53 def parse_options(): | 53 def parse_options(): |
| 54 parser = OptionParser() | 54 parser = OptionParser() |
| 55 parser.add_option('--cache-directory', | 55 parser.add_option('--cache-directory', |
| 56 help='cache directory, defaults to output directory') | 56 help='cache directory, defaults to output directory') |
| 57 parser.add_option('--generate-impl', | 57 parser.add_option('--generate-impl', |
| 58 action="store_true", default=False) | 58 action="store_true", default=False) |
| 59 parser.add_option('--output-directory') | 59 parser.add_option('--output-directory') |
| 60 parser.add_option('--impl-output-directory') | 60 parser.add_option('--impl-output-directory') |
| 61 parser.add_option('--info-dir') | 61 parser.add_option('--info-dir') |
| 62 parser.add_option('--write-file-only-if-changed', type='int') | |
| 63 # FIXME: We should always explicitly specify --target-component and | 62 # FIXME: We should always explicitly specify --target-component and |
| 64 # remove the default behavior. | 63 # remove the default behavior. |
| 65 parser.add_option('--target-component', | 64 parser.add_option('--target-component', |
| 66 type='choice', | 65 type='choice', |
| 67 choices=['core', 'modules'], | 66 choices=['core', 'modules'], |
| 68 help='target component to generate code, defaults to ' | 67 help='target component to generate code, defaults to ' |
| 69 'component of input idl file') | 68 'component of input idl file') |
| 70 # ensure output comes last, so command line easy to parse via regexes | 69 # ensure output comes last, so command line easy to parse via regexes |
| 71 parser.disable_interspersed_args() | 70 parser.disable_interspersed_args() |
| 72 | 71 |
| 73 options, args = parser.parse_args() | 72 options, args = parser.parse_args() |
| 74 if options.output_directory is None: | 73 if options.output_directory is None: |
| 75 parser.error('Must specify output directory using --output-directory.') | 74 parser.error('Must specify output directory using --output-directory.') |
| 76 options.write_file_only_if_changed = bool(options.write_file_only_if_changed
) | |
| 77 if len(args) != 1: | 75 if len(args) != 1: |
| 78 parser.error('Must specify exactly 1 input file as argument, but %d give
n.' % len(args)) | 76 parser.error('Must specify exactly 1 input file as argument, but %d give
n.' % len(args)) |
| 79 idl_filename = os.path.realpath(args[0]) | 77 idl_filename = os.path.realpath(args[0]) |
| 80 return options, idl_filename | 78 return options, idl_filename |
| 81 | 79 |
| 82 | 80 |
| 83 def idl_filename_to_interface_name(idl_filename): | 81 def idl_filename_to_interface_name(idl_filename): |
| 84 basename = os.path.basename(idl_filename) | 82 basename = os.path.basename(idl_filename) |
| 85 interface_name, _ = os.path.splitext(basename) | 83 interface_name, _ = os.path.splitext(basename) |
| 86 return interface_name | 84 return interface_name |
| 87 | 85 |
| 88 | 86 |
| 89 class IdlCompiler(object): | 87 class IdlCompiler(object): |
| 90 """Abstract Base Class for IDL compilers. | 88 """Abstract Base Class for IDL compilers. |
| 91 | 89 |
| 92 In concrete classes: | 90 In concrete classes: |
| 93 * self.code_generator must be set, implementing generate_code() | 91 * self.code_generator must be set, implementing generate_code() |
| 94 (returning a list of output code), and | 92 (returning a list of output code), and |
| 95 * compile_file() must be implemented (handling output filenames). | 93 * compile_file() must be implemented (handling output filenames). |
| 96 """ | 94 """ |
| 97 __metaclass__ = abc.ABCMeta | 95 __metaclass__ = abc.ABCMeta |
| 98 | 96 |
| 99 def __init__(self, output_directory, cache_directory=None, | 97 def __init__(self, output_directory, cache_directory=None, |
| 100 code_generator=None, info_provider=None, | 98 code_generator=None, info_provider=None, |
| 101 only_if_changed=False, target_component=None): | 99 target_component=None): |
| 102 """ | 100 """ |
| 103 Args: | 101 Args: |
| 104 output_directory: directory to put output files. | 102 output_directory: directory to put output files. |
| 105 cache_directory: directory which contains PLY caches. | 103 cache_directory: directory which contains PLY caches. |
| 106 code_generator: code generator to be used. | 104 code_generator: code generator to be used. |
| 107 info_provider: component-specific information provider. | 105 info_provider: component-specific information provider. |
| 108 only_if_changed: True when the compiler should only write output files | |
| 109 when the contents are changed. | |
| 110 target_component: component to be processed. | 106 target_component: component to be processed. |
| 111 """ | 107 """ |
| 112 self.cache_directory = cache_directory | 108 self.cache_directory = cache_directory |
| 113 self.code_generator = code_generator | 109 self.code_generator = code_generator |
| 114 self.info_provider = info_provider | 110 self.info_provider = info_provider |
| 115 self.only_if_changed = only_if_changed | |
| 116 self.output_directory = output_directory | 111 self.output_directory = output_directory |
| 117 self.target_component = target_component | 112 self.target_component = target_component |
| 118 self.reader = IdlReader(info_provider.interfaces_info, cache_directory) | 113 self.reader = IdlReader(info_provider.interfaces_info, cache_directory) |
| 119 | 114 |
| 120 def compile_and_write(self, idl_filename): | 115 def compile_and_write(self, idl_filename): |
| 121 interface_name = idl_filename_to_interface_name(idl_filename) | 116 interface_name = idl_filename_to_interface_name(idl_filename) |
| 122 definitions = self.reader.read_idl_definitions(idl_filename) | 117 definitions = self.reader.read_idl_definitions(idl_filename) |
| 123 target_definitions = definitions[self.target_component] | 118 target_definitions = definitions[self.target_component] |
| 124 output_code_list = self.code_generator.generate_code( | 119 output_code_list = self.code_generator.generate_code( |
| 125 target_definitions, interface_name) | 120 target_definitions, interface_name) |
| 126 for output_path, output_code in output_code_list: | 121 for output_path, output_code in output_code_list: |
| 127 write_file(output_code, output_path, self.only_if_changed) | 122 write_file(output_code, output_path) |
| 128 | 123 |
| 129 @abc.abstractmethod | 124 @abc.abstractmethod |
| 130 def compile_file(self, idl_filename): | 125 def compile_file(self, idl_filename): |
| 131 pass | 126 pass |
| 132 | 127 |
| 133 | 128 |
| 134 class IdlCompilerV8(IdlCompiler): | 129 class IdlCompilerV8(IdlCompiler): |
| 135 def __init__(self, *args, **kwargs): | 130 def __init__(self, *args, **kwargs): |
| 136 IdlCompiler.__init__(self, *args, **kwargs) | 131 IdlCompiler.__init__(self, *args, **kwargs) |
| 137 self.code_generator = CodeGeneratorV8(self.info_provider, | 132 self.code_generator = CodeGeneratorV8(self.info_provider, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 152 self.compile_and_write(idl_filename) | 147 self.compile_and_write(idl_filename) |
| 153 | 148 |
| 154 | 149 |
| 155 def generate_bindings(options, input_filename): | 150 def generate_bindings(options, input_filename): |
| 156 info_provider = create_component_info_provider( | 151 info_provider = create_component_info_provider( |
| 157 options.info_dir, options.target_component) | 152 options.info_dir, options.target_component) |
| 158 idl_compiler = IdlCompilerV8( | 153 idl_compiler = IdlCompilerV8( |
| 159 options.output_directory, | 154 options.output_directory, |
| 160 cache_directory=options.cache_directory, | 155 cache_directory=options.cache_directory, |
| 161 info_provider=info_provider, | 156 info_provider=info_provider, |
| 162 only_if_changed=options.write_file_only_if_changed, | |
| 163 target_component=options.target_component) | 157 target_component=options.target_component) |
| 164 idl_compiler.compile_file(input_filename) | 158 idl_compiler.compile_file(input_filename) |
| 165 | 159 |
| 166 | 160 |
| 167 def generate_dictionary_impl(options, input_filename): | 161 def generate_dictionary_impl(options, input_filename): |
| 168 info_provider = create_component_info_provider( | 162 info_provider = create_component_info_provider( |
| 169 options.info_dir, options.target_component) | 163 options.info_dir, options.target_component) |
| 170 idl_compiler = IdlCompilerDictionaryImpl( | 164 idl_compiler = IdlCompilerDictionaryImpl( |
| 171 options.impl_output_directory, | 165 options.impl_output_directory, |
| 172 cache_directory=options.cache_directory, | 166 cache_directory=options.cache_directory, |
| 173 info_provider=info_provider, | 167 info_provider=info_provider, |
| 174 only_if_changed=options.write_file_only_if_changed, | |
| 175 target_component=options.target_component) | 168 target_component=options.target_component) |
| 176 | 169 |
| 177 idl_filenames = read_idl_files_list_from_file(input_filename, | 170 idl_filenames = read_idl_files_list_from_file(input_filename, |
| 178 is_gyp_format=True) | 171 is_gyp_format=True) |
| 179 for idl_filename in idl_filenames: | 172 for idl_filename in idl_filenames: |
| 180 idl_compiler.compile_file(idl_filename) | 173 idl_compiler.compile_file(idl_filename) |
| 181 | 174 |
| 182 | 175 |
| 183 def generate_union_type_containers(options): | 176 def generate_union_type_containers(options): |
| 184 info_provider = create_component_info_provider( | 177 info_provider = create_component_info_provider( |
| 185 options.info_dir, options.target_component) | 178 options.info_dir, options.target_component) |
| 186 if not info_provider.interfaces_info: | 179 if not info_provider.interfaces_info: |
| 187 raise Exception('Interfaces info is required to generate ' | 180 raise Exception('Interfaces info is required to generate ' |
| 188 'union types containers') | 181 'union types containers') |
| 189 generator = CodeGeneratorUnionType( | 182 generator = CodeGeneratorUnionType( |
| 190 info_provider, | 183 info_provider, |
| 191 options.cache_directory, | 184 options.cache_directory, |
| 192 options.output_directory, | 185 options.output_directory, |
| 193 options.target_component) | 186 options.target_component) |
| 194 output_code_list = generator.generate_code() | 187 output_code_list = generator.generate_code() |
| 195 for output_path, output_code in output_code_list: | 188 for output_path, output_code in output_code_list: |
| 196 write_file(output_code, output_path, options.write_file_only_if_changed) | 189 write_file(output_code, output_path) |
| 197 | 190 |
| 198 | 191 |
| 199 def generate_callback_function_impl(options): | 192 def generate_callback_function_impl(options): |
| 200 info_provider = create_component_info_provider( | 193 info_provider = create_component_info_provider( |
| 201 options.info_dir, options.target_component) | 194 options.info_dir, options.target_component) |
| 202 generator = CodeGeneratorCallbackFunction( | 195 generator = CodeGeneratorCallbackFunction( |
| 203 info_provider, | 196 info_provider, |
| 204 options.cache_directory, | 197 options.cache_directory, |
| 205 options.output_directory, | 198 options.output_directory, |
| 206 options.target_component) | 199 options.target_component) |
| 207 output_code_list = generator.generate_code() | 200 output_code_list = generator.generate_code() |
| 208 for output_path, output_code in output_code_list: | 201 for output_path, output_code in output_code_list: |
| 209 write_file(output_code, output_path, options.write_file_only_if_changed) | 202 write_file(output_code, output_path) |
| 210 | 203 |
| 211 | 204 |
| 212 def main(): | 205 def main(): |
| 213 options, input_filename = parse_options() | 206 options, input_filename = parse_options() |
| 214 if options.generate_impl: | 207 if options.generate_impl: |
| 215 # |input_filename| should be a file which contains a list of IDL | 208 # |input_filename| should be a file which contains a list of IDL |
| 216 # dictionary paths. | 209 # dictionary paths. |
| 217 generate_dictionary_impl(options, input_filename) | 210 generate_dictionary_impl(options, input_filename) |
| 218 generate_union_type_containers(options) | 211 generate_union_type_containers(options) |
| 219 generate_callback_function_impl(options) | 212 generate_callback_function_impl(options) |
| 220 else: | 213 else: |
| 221 # |input_filename| should be a path of an IDL file. | 214 # |input_filename| should be a path of an IDL file. |
| 222 generate_bindings(options, input_filename) | 215 generate_bindings(options, input_filename) |
| 223 | 216 |
| 224 | 217 |
| 225 if __name__ == '__main__': | 218 if __name__ == '__main__': |
| 226 sys.exit(main()) | 219 sys.exit(main()) |
| OLD | NEW |