OLD | NEW |
| (Empty) |
1 #!/usr/bin/python | |
2 # | |
3 # Copyright (C) 2013 Google Inc. All rights reserved. | |
4 # | |
5 # Redistribution and use in source and binary forms, with or without | |
6 # modification, are permitted provided that the following conditions are | |
7 # met: | |
8 # | |
9 # * Redistributions of source code must retain the above copyright | |
10 # notice, this list of conditions and the following disclaimer. | |
11 # * Redistributions in binary form must reproduce the above | |
12 # copyright notice, this list of conditions and the following disclaimer | |
13 # in the documentation and/or other materials provided with the | |
14 # distribution. | |
15 # * Neither the name of Google Inc. nor the names of its | |
16 # contributors may be used to endorse or promote products derived from | |
17 # this software without specific prior written permission. | |
18 # | |
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | |
31 import optparse | |
32 import os | |
33 import cPickle as pickle | |
34 import posixpath | |
35 import re | |
36 import string | |
37 | |
38 module_path = os.path.dirname(__file__) | |
39 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir)) | |
40 | |
41 INHERITED_EXTENDED_ATTRIBUTES = set([ | |
42 'ActiveDOMObject', | |
43 'DependentLifetime', | |
44 'WillBeGarbageCollected', | |
45 ]) | |
46 | |
47 | |
48 # interfaces_info is *exported* (in a pickle), and should only contain data | |
49 # about an interface that contains paths or is needed by *other* interfaces, | |
50 # i.e., file layout data (to abstract the compiler from file paths) or | |
51 # public data (to avoid having to read other interfaces unnecessarily). | |
52 # It should *not* contain full information about an interface (e.g., all | |
53 # extended attributes), as this would cause unnecessary rebuilds. | |
54 interfaces_info = {} | |
55 | |
56 # Auxiliary variables (not visible to future build steps) | |
57 partial_interface_files = {} | |
58 parent_interfaces = {} | |
59 extended_attributes_by_interface = {} # interface name -> extended attributes | |
60 | |
61 | |
62 class IdlBadFilenameError(Exception): | |
63 """Raised if an IDL filename disagrees with the interface name in the file."
"" | |
64 pass | |
65 | |
66 | |
67 class IdlInterfaceFileNotFoundError(Exception): | |
68 """Raised if the IDL file implementing an interface cannot be found.""" | |
69 pass | |
70 | |
71 | |
72 def parse_options(): | |
73 usage = 'Usage: %prog [options] [generated1.idl]...' | |
74 parser = optparse.OptionParser(usage=usage) | |
75 parser.add_option('--event-names-file', help='output file') | |
76 parser.add_option('--idl-files-list', help='file listing IDL files') | |
77 parser.add_option('--interface-dependencies-file', help='output file') | |
78 parser.add_option('--interfaces-info-file', help='output pickle file') | |
79 parser.add_option('--window-constructors-file', help='output file') | |
80 parser.add_option('--workerglobalscope-constructors-file', help='output file
') | |
81 parser.add_option('--sharedworkerglobalscope-constructors-file', help='outpu
t file') | |
82 parser.add_option('--dedicatedworkerglobalscope-constructors-file', help='ou
tput file') | |
83 parser.add_option('--serviceworkerglobalscope-constructors-file', help='outp
ut file') | |
84 parser.add_option('--write-file-only-if-changed', type='int', help='if true,
do not write an output file if it would be identical to the existing one, which
avoids unnecessary rebuilds in ninja') | |
85 options, args = parser.parse_args() | |
86 if options.event_names_file is None: | |
87 parser.error('Must specify an output file using --event-names-file.') | |
88 if options.interface_dependencies_file is None: | |
89 parser.error('Must specify an output file using --interface-dependencies
-file.') | |
90 if options.interfaces_info_file is None: | |
91 parser.error('Must specify an output file using --interfaces-info-file.'
) | |
92 if options.window_constructors_file is None: | |
93 parser.error('Must specify an output file using --window-constructors-fi
le.') | |
94 if options.workerglobalscope_constructors_file is None: | |
95 parser.error('Must specify an output file using --workerglobalscope-cons
tructors-file.') | |
96 if options.sharedworkerglobalscope_constructors_file is None: | |
97 parser.error('Must specify an output file using --sharedworkerglobalscop
e-constructors-file.') | |
98 if options.dedicatedworkerglobalscope_constructors_file is None: | |
99 parser.error('Must specify an output file using --dedicatedworkerglobals
cope-constructors-file.') | |
100 if options.serviceworkerglobalscope_constructors_file is None: | |
101 parser.error('Must specify an output file using --serviceworkerglobalsco
pe-constructors-file.') | |
102 if options.idl_files_list is None: | |
103 parser.error('Must specify a file listing IDL files using --idl-files-li
st.') | |
104 if options.write_file_only_if_changed is None: | |
105 parser.error('Must specify whether file is only written if changed using
--write-file-only-if-changed.') | |
106 options.write_file_only_if_changed = bool(options.write_file_only_if_changed
) | |
107 return options, args | |
108 | |
109 | |
110 ################################################################################ | |
111 # Basic file reading/writing | |
112 ################################################################################ | |
113 | |
114 def get_file_contents(idl_filename): | |
115 with open(idl_filename) as idl_file: | |
116 lines = idl_file.readlines() | |
117 return ''.join(lines) | |
118 | |
119 | |
120 def write_file(new_lines, destination_filename, only_if_changed): | |
121 if only_if_changed and os.path.isfile(destination_filename): | |
122 with open(destination_filename) as destination_file: | |
123 if destination_file.readlines() == new_lines: | |
124 return | |
125 with open(destination_filename, 'w') as destination_file: | |
126 destination_file.write(''.join(new_lines)) | |
127 | |
128 | |
129 def write_pickle_file(pickle_filename, data, only_if_changed): | |
130 if only_if_changed and os.path.isfile(pickle_filename): | |
131 with open(pickle_filename) as pickle_file: | |
132 if pickle.load(pickle_file) == data: | |
133 return | |
134 with open(pickle_filename, 'w') as pickle_file: | |
135 pickle.dump(data, pickle_file) | |
136 | |
137 | |
138 ################################################################################ | |
139 # IDL parsing | |
140 # | |
141 # We use regular expressions for parsing; this is incorrect (Web IDL is not a | |
142 # regular language), but simple and sufficient in practice. | |
143 # Leading and trailing context (e.g. following '{') used to avoid false matches. | |
144 ################################################################################ | |
145 | |
146 def get_partial_interface_name_from_idl(file_contents): | |
147 match = re.search(r'partial\s+interface\s+(\w+)\s*{', file_contents) | |
148 return match and match.group(1) | |
149 | |
150 | |
151 # identifier-A implements identifier-B; | |
152 # http://www.w3.org/TR/WebIDL/#idl-implements-statements | |
153 def get_implemented_interfaces_from_idl(file_contents, interface_name): | |
154 def get_implemented(left_identifier, right_identifier): | |
155 # identifier-A must be the current interface | |
156 if left_identifier != interface_name: | |
157 raise IdlBadFilenameError("Identifier on the left of the 'implements
' statement should be %s in %s.idl, but found %s" % (interface_name, interface_n
ame, left_identifier)) | |
158 return right_identifier | |
159 | |
160 implements_re = (r'^\s*' | |
161 r'(\w+)\s+' | |
162 r'implements\s+' | |
163 r'(\w+)\s*' | |
164 r';') | |
165 implements_matches = re.finditer(implements_re, file_contents, re.MULTILINE) | |
166 implements_pairs = [(match.group(1), match.group(2)) | |
167 for match in implements_matches] | |
168 return [get_implemented(left, right) for left, right in implements_pairs] | |
169 | |
170 | |
171 def is_callback_interface_from_idl(file_contents): | |
172 match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents) | |
173 return bool(match) | |
174 | |
175 | |
176 def get_parent_interface(file_contents): | |
177 match = re.search(r'interface\s+' | |
178 r'\w+\s*' | |
179 r':\s*(\w+)\s*' | |
180 r'{', | |
181 file_contents) | |
182 return match and match.group(1) | |
183 | |
184 | |
185 def get_interface_extended_attributes_from_idl(file_contents): | |
186 match = re.search(r'\[(.*)\]\s*' | |
187 r'((callback|partial)\s+)?' | |
188 r'(interface|exception)\s+' | |
189 r'\w+\s*' | |
190 r'(:\s*\w+\s*)?' | |
191 r'{', | |
192 file_contents, flags=re.DOTALL) | |
193 if not match: | |
194 return {} | |
195 # Strip comments | |
196 # re.compile needed b/c Python 2.6 doesn't support flags in re.sub | |
197 single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE) | |
198 block_comment_re = re.compile(r'/\*.*?\*/', flags=re.MULTILINE | re.DOTALL) | |
199 extended_attributes_string = re.sub(single_line_comment_re, '', match.group(
1)) | |
200 extended_attributes_string = re.sub(block_comment_re, '', extended_attribute
s_string) | |
201 extended_attributes = {} | |
202 # FIXME: this splitting is WRONG: it fails on ExtendedAttributeArgList like | |
203 # 'NamedConstructor=Foo(a, b)' | |
204 parts = [extended_attribute.strip() | |
205 for extended_attribute in extended_attributes_string.split(',') | |
206 # Discard empty parts, which may exist due to trailing comma | |
207 if extended_attribute.strip()] | |
208 for part in parts: | |
209 name, _, value = map(string.strip, part.partition('=')) | |
210 extended_attributes[name] = value | |
211 return extended_attributes | |
212 | |
213 | |
214 def get_put_forward_interfaces_from_idl(file_contents): | |
215 put_forwards_pattern = (r'\[[^\]]*PutForwards=[^\]]*\]\s+' | |
216 r'readonly\s+' | |
217 r'attribute\s+' | |
218 r'(\w+)') | |
219 return sorted(set(match.group(1) | |
220 for match in re.finditer(put_forwards_pattern, | |
221 file_contents, | |
222 flags=re.DOTALL))) | |
223 | |
224 | |
225 ################################################################################ | |
226 # Write files | |
227 ################################################################################ | |
228 | |
229 def write_dependencies_file(dependencies_filename, only_if_changed): | |
230 """Write the interface dependencies file. | |
231 | |
232 The format is as follows: | |
233 | |
234 Document.idl P.idl | |
235 Event.idl | |
236 Window.idl Q.idl R.idl S.idl | |
237 ... | |
238 | |
239 The above indicates that: | |
240 Document.idl depends on P.idl, | |
241 Event.idl depends on no other IDL files, and | |
242 Window.idl depends on Q.idl, R.idl, and S.idl. | |
243 | |
244 An IDL that is a dependency of another IDL (e.g. P.idl) does not have its | |
245 own line in the dependency file. | |
246 """ | |
247 # FIXME: remove text format once Perl gone (Python uses pickle) | |
248 dependencies_list = sorted( | |
249 (interface_info['full_path'], sorted(interface_info['dependencies_full_p
aths'])) | |
250 for interface_info in interfaces_info.values()) | |
251 lines = ['%s %s\n' % (idl_file, ' '.join(dependency_files)) | |
252 for idl_file, dependency_files in dependencies_list] | |
253 write_file(lines, dependencies_filename, only_if_changed) | |
254 | |
255 | |
256 def write_event_names_file(destination_filename, only_if_changed): | |
257 # Generate event names for all interfaces that inherit from Event, | |
258 # including Event itself. | |
259 event_names = set( | |
260 interface_name | |
261 for interface_name, interface_info in interfaces_info.iteritems() | |
262 if (interface_name == 'Event' or | |
263 ('ancestors' in interface_info and | |
264 interface_info['ancestors'][-1] == 'Event'))) | |
265 | |
266 def extended_attribute_string(name): | |
267 value = extended_attributes[name] | |
268 if name == 'RuntimeEnabled': | |
269 value += 'Enabled' | |
270 return name + '=' + value | |
271 | |
272 source_dir, _ = os.path.split(os.getcwd()) | |
273 lines = [] | |
274 lines.append('namespace="Event"\n') | |
275 lines.append('\n') | |
276 for filename, extended_attributes in sorted( | |
277 (interface_info['full_path'], | |
278 extended_attributes_by_interface[interface_name]) | |
279 for interface_name, interface_info in interfaces_info.iteritems() | |
280 if interface_name in event_names): | |
281 refined_filename, _ = os.path.splitext(os.path.relpath(filename, source_
dir)) | |
282 refined_filename = refined_filename.replace(os.sep, posixpath.sep) | |
283 extended_attributes_list = [ | |
284 extended_attribute_string(name) | |
285 for name in 'Conditional', 'ImplementedAs', 'RuntimeEnabled' | |
286 if name in extended_attributes] | |
287 lines.append('%s %s\n' % (refined_filename, ', '.join(extended_attribute
s_list))) | |
288 write_file(lines, destination_filename, only_if_changed) | |
289 | |
290 | |
291 def write_global_constructors_partial_interface(interface_name, destination_file
name, constructor_attributes_list, only_if_changed): | |
292 lines = (['partial interface %s {\n' % interface_name] + | |
293 [' %s;\n' % constructor_attribute | |
294 for constructor_attribute in sorted(constructor_attributes_list)]
+ | |
295 ['};\n']) | |
296 write_file(lines, destination_filename, only_if_changed) | |
297 | |
298 | |
299 ################################################################################ | |
300 # Dependency resolution | |
301 ################################################################################ | |
302 | |
303 def include_path(idl_filename, implemented_as=None): | |
304 """Returns relative path to header file in POSIX format; used in includes. | |
305 | |
306 POSIX format is used for consistency of output, so reference tests are | |
307 platform-independent. | |
308 """ | |
309 relative_path_local = os.path.relpath(idl_filename, source_path) | |
310 relative_dir_local = os.path.dirname(relative_path_local) | |
311 relative_dir_posix = relative_dir_local.replace(os.path.sep, posixpath.sep) | |
312 | |
313 idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename)) | |
314 cpp_class_name = implemented_as or idl_file_basename | |
315 | |
316 return posixpath.join(relative_dir_posix, cpp_class_name + '.h') | |
317 | |
318 | |
319 def add_paths_to_partials_dict(partial_interface_name, full_path, this_include_p
ath=None): | |
320 paths_dict = partial_interface_files.setdefault(partial_interface_name, | |
321 {'full_paths': [], | |
322 'include_paths': []}) | |
323 paths_dict['full_paths'].append(full_path) | |
324 if this_include_path: | |
325 paths_dict['include_paths'].append(this_include_path) | |
326 | |
327 | |
328 def generate_dependencies(idl_filename): | |
329 """Compute dependencies for IDL file, returning True if main (non-partial) i
nterface""" | |
330 full_path = os.path.realpath(idl_filename) | |
331 idl_file_contents = get_file_contents(full_path) | |
332 | |
333 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) | |
334 implemented_as = extended_attributes.get('ImplementedAs') | |
335 # FIXME: remove [NoHeader] once switch to Python | |
336 this_include_path = (include_path(idl_filename, implemented_as) | |
337 if 'NoHeader' not in extended_attributes else None) | |
338 | |
339 # Handle partial interfaces | |
340 partial_interface_name = get_partial_interface_name_from_idl(idl_file_conten
ts) | |
341 if partial_interface_name: | |
342 add_paths_to_partials_dict(partial_interface_name, full_path, this_inclu
de_path) | |
343 return False | |
344 | |
345 # If not a partial interface, the basename is the interface name | |
346 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) | |
347 | |
348 interfaces_info[interface_name] = { | |
349 'full_path': full_path, | |
350 'implements_interfaces': get_implemented_interfaces_from_idl(idl_file_co
ntents, interface_name), | |
351 'is_callback_interface': is_callback_interface_from_idl(idl_file_content
s), | |
352 # Interfaces that are referenced (used as types) and that we introspect | |
353 # during code generation (beyond interface-level data ([ImplementedAs], | |
354 # is_callback_interface, ancestors, and inherited extended attributes): | |
355 # deep dependencies. | |
356 # These cause rebuilds of referrers, due to the dependency, so these | |
357 # should be minimized; currently only targets of [PutForwards]. | |
358 'referenced_interfaces': get_put_forward_interfaces_from_idl(idl_file_co
ntents), | |
359 } | |
360 if this_include_path: | |
361 interfaces_info[interface_name]['include_path'] = this_include_path | |
362 if implemented_as: | |
363 interfaces_info[interface_name]['implemented_as'] = implemented_as | |
364 | |
365 return True | |
366 | |
367 | |
368 def generate_constructor_attribute_list(interface_name, extended_attributes): | |
369 extended_attributes_list = [ | |
370 name + '=' + extended_attributes[name] | |
371 for name in 'Conditional', 'PerContextEnabled', 'RuntimeEnabled' | |
372 if name in extended_attributes] | |
373 if extended_attributes_list: | |
374 extended_string = '[%s] ' % ', '.join(extended_attributes_list) | |
375 else: | |
376 extended_string = '' | |
377 | |
378 attribute_string = 'attribute {interface_name}Constructor {interface_name}'.
format(interface_name=interface_name) | |
379 attributes_list = [extended_string + attribute_string] | |
380 | |
381 # In addition to the regular property, for every [NamedConstructor] | |
382 # extended attribute on an interface, a corresponding property MUST exist | |
383 # on the ECMAScript global object. | |
384 if 'NamedConstructor' in extended_attributes: | |
385 named_constructor = extended_attributes['NamedConstructor'] | |
386 # Extract function name, namely everything before opening '(' | |
387 constructor_name = re.sub(r'\(.*', '', named_constructor) | |
388 # Note the reduplicated 'ConstructorConstructor' | |
389 attribute_string = 'attribute %sConstructorConstructor %s' % (interface_
name, constructor_name) | |
390 attributes_list.append(extended_string + attribute_string) | |
391 | |
392 return attributes_list | |
393 | |
394 | |
395 def record_global_constructors_and_extended_attributes(idl_filename, global_cons
tructors): | |
396 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) | |
397 full_path = os.path.realpath(idl_filename) | |
398 idl_file_contents = get_file_contents(full_path) | |
399 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) | |
400 | |
401 # Record extended attributes | |
402 extended_attributes_by_interface[interface_name] = extended_attributes | |
403 | |
404 # Record global constructors | |
405 if (not is_callback_interface_from_idl(idl_file_contents) and | |
406 'NoInterfaceObject' not in extended_attributes): | |
407 global_contexts = extended_attributes.get('GlobalContext', 'Window').spl
it('&') | |
408 new_constructor_list = generate_constructor_attribute_list(interface_nam
e, extended_attributes) | |
409 for global_object in global_contexts: | |
410 global_constructors[global_object].extend(new_constructor_list) | |
411 | |
412 # Record parents | |
413 parent = get_parent_interface(idl_file_contents) | |
414 if parent: | |
415 parent_interfaces[interface_name] = parent | |
416 | |
417 | |
418 def record_extended_attributes(idl_filename): | |
419 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) | |
420 full_path = os.path.realpath(idl_filename) | |
421 idl_file_contents = get_file_contents(full_path) | |
422 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) | |
423 extended_attributes_by_interface[interface_name] = extended_attributes | |
424 | |
425 | |
426 def generate_ancestors_and_inherited_extended_attributes(interface_name): | |
427 interface_info = interfaces_info[interface_name] | |
428 interface_extended_attributes = extended_attributes_by_interface[interface_n
ame] | |
429 inherited_extended_attributes = dict( | |
430 (key, value) | |
431 for key, value in interface_extended_attributes.iteritems() | |
432 if key in INHERITED_EXTENDED_ATTRIBUTES) | |
433 | |
434 def generate_ancestors(interface_name): | |
435 while interface_name in parent_interfaces: | |
436 interface_name = parent_interfaces[interface_name] | |
437 yield interface_name | |
438 | |
439 ancestors = list(generate_ancestors(interface_name)) | |
440 if not ancestors: | |
441 if inherited_extended_attributes: | |
442 interface_info['inherited_extended_attributes'] = inherited_extended
_attributes | |
443 return | |
444 | |
445 interface_info['ancestors'] = ancestors | |
446 for ancestor in ancestors: | |
447 # Extended attributes are missing if an ancestor is an interface that | |
448 # we're not processing, notably real IDL files if only processing test | |
449 # IDL files, or generated support files. | |
450 ancestor_extended_attributes = extended_attributes_by_interface.get(ance
stor, {}) | |
451 inherited_extended_attributes.update(dict( | |
452 (key, value) | |
453 for key, value in ancestor_extended_attributes.iteritems() | |
454 if key in INHERITED_EXTENDED_ATTRIBUTES)) | |
455 if inherited_extended_attributes: | |
456 interface_info['inherited_extended_attributes'] = inherited_extended_att
ributes | |
457 | |
458 | |
459 def parse_idl_files(idl_files, global_constructors_filenames): | |
460 """Compute dependencies between IDL files, and return constructors on global
objects. | |
461 | |
462 Primary effect is computing info about main interfaces, stored in global | |
463 interfaces_info. | |
464 The keys are the interfaces for which bindings are generated; | |
465 this does not include interfaces implemented by another interface. | |
466 | |
467 Returns: | |
468 global_constructors: | |
469 dict of global objects -> list of constructors on that object | |
470 """ | |
471 global_constructors = dict([ | |
472 (global_object, []) | |
473 for global_object in global_constructors_filenames]) | |
474 | |
475 # Generate dependencies, and (for main IDL files), record | |
476 # global_constructors and extended_attributes_by_interface. | |
477 for idl_filename in idl_files: | |
478 # Test skips partial interfaces | |
479 if generate_dependencies(idl_filename): | |
480 record_global_constructors_and_extended_attributes(idl_filename, glo
bal_constructors) | |
481 | |
482 for interface_name in interfaces_info: | |
483 generate_ancestors_and_inherited_extended_attributes(interface_name) | |
484 | |
485 # Add constructors on global objects to partial interfaces | |
486 # These are all partial interfaces, but the files are dynamically generated, | |
487 # so they need to be handled separately from static partial interfaces. | |
488 for global_object, constructor_filename in global_constructors_filenames.ite
ritems(): | |
489 if global_object in interfaces_info: | |
490 # No include path needed, as already included in the header file | |
491 add_paths_to_partials_dict(global_object, constructor_filename) | |
492 | |
493 # An IDL file's dependencies are partial interface files that extend it, | |
494 # and files for other interfaces that this interfaces implements. | |
495 for interface_name, interface_info in interfaces_info.iteritems(): | |
496 partial_interfaces_full_paths, partial_interfaces_include_paths = ( | |
497 (partial_interface_files[interface_name]['full_paths'], | |
498 partial_interface_files[interface_name]['include_paths']) | |
499 if interface_name in partial_interface_files else ([], [])) | |
500 | |
501 implemented_interfaces = interface_info['implements_interfaces'] | |
502 try: | |
503 implemented_interfaces_full_paths = [ | |
504 interfaces_info[interface]['full_path'] | |
505 for interface in implemented_interfaces] | |
506 implemented_interfaces_include_paths = [ | |
507 interfaces_info[interface]['include_path'] | |
508 for interface in implemented_interfaces | |
509 if 'include_path' in interfaces_info[interface]] | |
510 except KeyError as key_name: | |
511 raise IdlInterfaceFileNotFoundError('Could not find the IDL file whe
re the following implemented interface is defined: %s' % key_name) | |
512 | |
513 interface_info['dependencies_full_paths'] = ( | |
514 partial_interfaces_full_paths + | |
515 implemented_interfaces_full_paths) | |
516 interface_info['dependencies_include_paths'] = ( | |
517 partial_interfaces_include_paths + | |
518 implemented_interfaces_include_paths) | |
519 | |
520 return global_constructors | |
521 | |
522 | |
523 ################################################################################ | |
524 | |
525 def main(): | |
526 options, args = parse_options() | |
527 | |
528 # Static IDL files are passed in a file (generated at GYP time), due to OS | |
529 # command line length limits | |
530 with open(options.idl_files_list) as idl_files_list: | |
531 idl_files = [line.rstrip('\n') for line in idl_files_list] | |
532 # Generated IDL files are passed at the command line, since these are in the | |
533 # build directory, which is determined at build time, not GYP time, so these | |
534 # cannot be included in the file listing static files | |
535 idl_files.extend(args) | |
536 | |
537 only_if_changed = options.write_file_only_if_changed | |
538 global_constructors_filenames = { | |
539 'Window': options.window_constructors_file, | |
540 'WorkerGlobalScope': options.workerglobalscope_constructors_file, | |
541 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_
file, | |
542 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru
ctors_file, | |
543 'ServiceWorkerGlobalScope': options.serviceworkerglobalscope_constructor
s_file, | |
544 } | |
545 | |
546 global_constructors = parse_idl_files(idl_files, global_constructors_filenam
es) | |
547 | |
548 write_dependencies_file(options.interface_dependencies_file, only_if_changed
) | |
549 write_pickle_file(options.interfaces_info_file, interfaces_info, only_if_cha
nged) | |
550 for interface_name, filename in global_constructors_filenames.iteritems(): | |
551 if interface_name in interfaces_info: | |
552 write_global_constructors_partial_interface(interface_name, filename
, global_constructors[interface_name], only_if_changed) | |
553 write_event_names_file(options.event_names_file, only_if_changed) | |
554 | |
555 | |
556 if __name__ == '__main__': | |
557 main() | |
OLD | NEW |