Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(505)

Side by Side Diff: Source/bindings/scripts/compute_interfaces_info_overall.py

Issue 300273005: Bindings build: split compute_interfaces_info into 2 stages (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Remove debugging Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # 2 #
3 # Copyright (C) 2013 Google Inc. All rights reserved. 3 # Copyright (C) 2013 Google Inc. All rights reserved.
4 # 4 #
5 # Redistribution and use in source and binary forms, with or without 5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are 6 # modification, are permitted provided that the following conditions are
7 # met: 7 # met:
8 # 8 #
9 # * Redistributions of source code must retain the above copyright 9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer. 10 # notice, this list of conditions and the following disclaimer.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 'dependencies_include_paths': paths for use in C++ #include directives 70 'dependencies_include_paths': paths for use in C++ #include directives
71 71
72 Note that all of these are stable information, unlikely to change without 72 Note that all of these are stable information, unlikely to change without
73 moving or deleting files (hence requiring a full rebuild anyway) or significant 73 moving or deleting files (hence requiring a full rebuild anyway) or significant
74 code changes (for inherited extended attributes). 74 code changes (for inherited extended attributes).
75 75
76 Design doc: http://www.chromium.org/developers/design-documents/idl-build 76 Design doc: http://www.chromium.org/developers/design-documents/idl-build
77 """ 77 """
78 78
79 from collections import defaultdict 79 from collections import defaultdict
80 import cPickle as pickle
80 import optparse 81 import optparse
81 import os
82 import posixpath
83 import sys 82 import sys
84 83
85 from utilities import get_file_contents, write_pickle_file, get_interface_extend ed_attributes_from_idl, is_callback_interface_from_idl, get_partial_interface_na me_from_idl, get_implements_from_idl, get_parent_interface, get_put_forward_inte rfaces_from_idl 84 from utilities import write_pickle_file
86
87 module_path = os.path.dirname(__file__)
88 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir))
89 85
90 INHERITED_EXTENDED_ATTRIBUTES = set([ 86 INHERITED_EXTENDED_ATTRIBUTES = set([
91 'ActiveDOMObject', 87 'ActiveDOMObject',
92 'DependentLifetime', 88 'DependentLifetime',
93 'GarbageCollected', 89 'GarbageCollected',
94 'WillBeGarbageCollected', 90 'WillBeGarbageCollected',
95 ]) 91 ])
96 92
97 # Main variable (filled in and exported) 93 # Main variable (filled in and exported)
98 interfaces_info = {} 94 interfaces_info = {}
99 95
100 # Auxiliary variables (not visible to future build steps) 96 # Auxiliary variables (not visible to future build steps)
101 partial_interface_files = defaultdict(lambda: { 97 partial_interface_files = defaultdict(lambda: {
102 'full_paths': [], 98 'full_paths': [],
103 'include_paths': [], 99 'include_paths': [],
104 }) 100 })
105 parent_interfaces = {} 101 parent_interfaces = {}
106 inherited_extended_attributes_by_interface = {} # interface name -> extended at tributes 102 inherited_extended_attributes_by_interface = {} # interface name -> extended at tributes
107 103
108 104
109 class IdlInterfaceFileNotFoundError(Exception): 105 class IdlInterfaceFileNotFoundError(Exception):
110 """Raised if the IDL file implementing an interface cannot be found.""" 106 """Raised if the IDL file implementing an interface cannot be found."""
111 pass 107 pass
112 108
113 109
114 def parse_options(): 110 def parse_options():
115 usage = 'Usage: %prog [options] [generated1.idl]...' 111 usage = 'Usage: %prog [InfoIndividual.pickle]... [Info.pickle]'
116 parser = optparse.OptionParser(usage=usage) 112 parser = optparse.OptionParser(usage=usage)
117 parser.add_option('--idl-files-list', help='file listing IDL files')
118 parser.add_option('--interfaces-info-file', help='output pickle file')
119 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') 113 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')
120 114
121 options, args = parser.parse_args() 115 options, args = parser.parse_args()
122 if options.interfaces_info_file is None:
123 parser.error('Must specify an output file using --interfaces-info-file.' )
124 if options.idl_files_list is None:
125 parser.error('Must specify a file listing IDL files using --idl-files-li st.')
126 if options.write_file_only_if_changed is None: 116 if options.write_file_only_if_changed is None:
127 parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.') 117 parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
128 options.write_file_only_if_changed = bool(options.write_file_only_if_changed ) 118 options.write_file_only_if_changed = bool(options.write_file_only_if_changed )
129 return options, args 119 return options, args
130 120
131 121
132 ################################################################################ 122 ################################################################################
133 # Computations 123 # Computations
134 ################################################################################ 124 ################################################################################
135 125
136 def include_path(idl_filename, implemented_as=None):
137 """Returns relative path to header file in POSIX format; used in includes.
138
139 POSIX format is used for consistency of output, so reference tests are
140 platform-independent.
141 """
142 relative_path_local = os.path.relpath(idl_filename, source_path)
143 relative_dir_local = os.path.dirname(relative_path_local)
144 relative_dir_posix = relative_dir_local.replace(os.path.sep, posixpath.sep)
145
146 idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename))
147 cpp_class_name = implemented_as or idl_file_basename
148
149 return posixpath.join(relative_dir_posix, cpp_class_name + '.h')
150
151
152 def add_paths_to_partials_dict(partial_interface_name, full_path, this_include_p ath=None):
153 paths_dict = partial_interface_files[partial_interface_name]
154 paths_dict['full_paths'].append(full_path)
155 if this_include_path:
156 paths_dict['include_paths'].append(this_include_path)
157
158
159 def compute_individual_info(idl_filename):
160 full_path = os.path.realpath(idl_filename)
161 idl_file_contents = get_file_contents(full_path)
162
163 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co ntents)
164 implemented_as = extended_attributes.get('ImplementedAs')
165 this_include_path = include_path(idl_filename, implemented_as)
166
167 # Handle partial interfaces
168 partial_interface_name = get_partial_interface_name_from_idl(idl_file_conten ts)
169 if partial_interface_name:
170 add_paths_to_partials_dict(partial_interface_name, full_path, this_inclu de_path)
171 return
172
173 # If not a partial interface, the basename is the interface name
174 interface_name, _ = os.path.splitext(os.path.basename(idl_filename))
175
176 # 'implements' statements can be included in either the file for the
177 # implement*ing* interface (lhs of 'implements') or implement*ed* interface
178 # (rhs of 'implements'). Store both for now, then merge to implement*ing*
179 # interface later.
180 left_interfaces, right_interfaces = get_implements_from_idl(idl_file_content s, interface_name)
181
182 interfaces_info[interface_name] = {
183 'full_path': full_path,
184 'implemented_as': implemented_as,
185 'implemented_by_interfaces': left_interfaces, # private, merged to next
186 'implements_interfaces': right_interfaces,
187 'include_path': this_include_path,
188 # FIXME: temporary private field, while removing old treatement of
189 # 'implements': http://crbug.com/360435
190 'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterface' in extended_attributes,
191 'is_callback_interface': is_callback_interface_from_idl(idl_file_content s),
192 # Interfaces that are referenced (used as types) and that we introspect
193 # during code generation (beyond interface-level data ([ImplementedAs],
194 # is_callback_interface, ancestors, and inherited extended attributes):
195 # deep dependencies.
196 # These cause rebuilds of referrers, due to the dependency, so these
197 # should be minimized; currently only targets of [PutForwards].
198 'referenced_interfaces': get_put_forward_interfaces_from_idl(idl_file_co ntents),
199 }
200
201 # Record inheritance information
202 inherited_extended_attributes_by_interface[interface_name] = dict(
203 (key, value)
204 for key, value in extended_attributes.iteritems()
205 if key in INHERITED_EXTENDED_ATTRIBUTES)
206 parent = get_parent_interface(idl_file_contents)
207 if parent:
208 parent_interfaces[interface_name] = parent
209
210 126
211 def compute_inheritance_info(interface_name): 127 def compute_inheritance_info(interface_name):
212 """Compute inheritance information, namely ancestors and inherited extended attributes.""" 128 """Compute inheritance information, namely ancestors and inherited extended attributes."""
213 def generate_ancestors(interface_name): 129 def generate_ancestors(interface_name):
214 while interface_name in parent_interfaces: 130 while interface_name in parent_interfaces:
215 interface_name = parent_interfaces[interface_name] 131 interface_name = parent_interfaces[interface_name]
216 yield interface_name 132 yield interface_name
217 133
218 ancestors = list(generate_ancestors(interface_name)) 134 ancestors = list(generate_ancestors(interface_name))
219 inherited_extended_attributes = inherited_extended_attributes_by_interface[i nterface_name] 135 inherited_extended_attributes = inherited_extended_attributes_by_interface[i nterface_name]
220 for ancestor in ancestors: 136 for ancestor in ancestors:
221 # Ancestors may not be present, notably if an ancestor is a generated 137 # Ancestors may not be present, notably if an ancestor is a generated
222 # IDL file and we are running this script from run-bindings-tests, 138 # IDL file and we are running this script from run-bindings-tests,
223 # where we don't generate these files. 139 # where we don't generate these files.
224 ancestor_extended_attributes = inherited_extended_attributes_by_interfac e.get(ancestor, {}) 140 ancestor_extended_attributes = inherited_extended_attributes_by_interfac e.get(ancestor, {})
225 inherited_extended_attributes.update(ancestor_extended_attributes) 141 inherited_extended_attributes.update(ancestor_extended_attributes)
226 142
227 interfaces_info[interface_name].update({ 143 interfaces_info[interface_name].update({
228 'ancestors': ancestors, 144 'ancestors': ancestors,
229 'inherited_extended_attributes': inherited_extended_attributes, 145 'inherited_extended_attributes': inherited_extended_attributes,
230 }) 146 })
231 147
232 148
233 def compute_interfaces_info(idl_files): 149 def compute_interfaces_info_overall(interfaces_info_individual_filenames):
234 """Compute information about IDL files. 150 """Compute information about IDL files.
235 151
236 Information is stored in global interfaces_info. 152 Information is stored in global interfaces_info.
237 """ 153 """
238 # Compute information for individual files 154 # Read in individual info from files
239 for idl_filename in idl_files: 155 for interfaces_info_individual_filename in interfaces_info_individual_filena mes:
240 compute_individual_info(idl_filename) 156 with open(interfaces_info_individual_filename) as interfaces_info_indivi dual_file:
157 info = pickle.load(interfaces_info_individual_file)
158 interfaces_info.update(info['interfaces_info'])
159 partial_interface_files.update(info['partial_interface_files'])
160
161 # Record inheritance information individually
162 for interface_name, interface_info in interfaces_info.iteritems():
163 extended_attributes = interface_info['extended_attributes']
164 inherited_extended_attributes_by_interface[interface_name] = dict(
165 (key, value)
166 for key, value in extended_attributes.iteritems()
167 if key in INHERITED_EXTENDED_ATTRIBUTES)
168 parent = interface_info['parent']
169 if parent:
170 parent_interfaces[interface_name] = parent
241 171
242 # Once all individual files handled, can compute inheritance information 172 # Once all individual files handled, can compute inheritance information
243 # and dependencies 173 # and dependencies
244 174
245 # Compute inheritance info 175 # Compute inheritance info
246 for interface_name in interfaces_info: 176 for interface_name in interfaces_info:
247 compute_inheritance_info(interface_name) 177 compute_inheritance_info(interface_name)
248 178
249 # Compute dependencies 179 # Compute dependencies
250 # Move implements info from implement*ed* interface (rhs of 'implements') 180 # Move implements info from implement*ed* interface (rhs of 'implements')
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 218
289 interface_info.update({ 219 interface_info.update({
290 'dependencies_full_paths': (partial_interfaces_full_paths + 220 'dependencies_full_paths': (partial_interfaces_full_paths +
291 implemented_interfaces_full_paths), 221 implemented_interfaces_full_paths),
292 'dependencies_include_paths': (partial_interfaces_include_paths + 222 'dependencies_include_paths': (partial_interfaces_include_paths +
293 implemented_interfaces_include_paths) , 223 implemented_interfaces_include_paths) ,
294 }) 224 })
295 225
296 # Clean up temporary private information 226 # Clean up temporary private information
297 for interface_info in interfaces_info.itervalues(): 227 for interface_info in interfaces_info.itervalues():
228 del interface_info['extended_attributes']
298 del interface_info['is_legacy_treat_as_partial_interface'] 229 del interface_info['is_legacy_treat_as_partial_interface']
230 del interface_info['parent']
299 231
300 232
301 ################################################################################ 233 ################################################################################
302 234
303 def main(): 235 def main():
304 options, args = parse_options() 236 options, args = parse_options()
237 # args = Input1, Input2, ..., Output
238 interfaces_info_filename = args.pop()
305 239
306 # Static IDL files are passed in a file (generated at GYP time), due to OS 240 compute_interfaces_info_overall(args)
307 # command line length limits 241 write_pickle_file(interfaces_info_filename,
308 with open(options.idl_files_list) as idl_files_list:
309 idl_files = [line.rstrip('\n') for line in idl_files_list]
310 # Generated IDL files are passed at the command line, since these are in the
311 # build directory, which is determined at build time, not GYP time, so these
312 # cannot be included in the file listing static files
313 idl_files.extend(args)
314
315 compute_interfaces_info(idl_files)
316 write_pickle_file(options.interfaces_info_file,
317 interfaces_info, 242 interfaces_info,
318 options.write_file_only_if_changed) 243 options.write_file_only_if_changed)
319 244
320 245
321 if __name__ == '__main__': 246 if __name__ == '__main__':
322 sys.exit(main()) 247 sys.exit(main())
OLDNEW
« no previous file with comments | « Source/bindings/scripts/compute_interfaces_info_individual.py ('k') | Source/bindings/scripts/utilities.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698