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

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

Issue 618373003: [bindings] partial interfaces should not violate componentization (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 2 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) 2009 Google Inc. All rights reserved. 3 # Copyright (C) 2009 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 19 matching lines...) Expand all
30 # 30 #
31 # Copyright (c) 2009 The Chromium Authors. All rights reserved. 31 # Copyright (c) 2009 The Chromium Authors. All rights reserved.
32 # Use of this source code is governed by a BSD-style license that can be 32 # Use of this source code is governed by a BSD-style license that can be
33 # found in the LICENSE file. 33 # found in the LICENSE file.
34 34
35 """Generate aggregate .cpp files that include multiple V8 binding .cpp files. 35 """Generate aggregate .cpp files that include multiple V8 binding .cpp files.
36 36
37 This can be a single output file, to preserve symbol space; or multiple output 37 This can be a single output file, to preserve symbol space; or multiple output
38 files, to reduce maximum compilation unit size and allow parallel compilation. 38 files, to reduce maximum compilation unit size and allow parallel compilation.
39 39
40 Usage:
41 aggregate_generated_bindings.py COMPONENT_DIR IDL_FILES_LIST -- OUTPUT_FILE1 OUT PUT_FILE2 ...
42
43 COMPONENT_DIR is the relative directory of a component, e.g., 'core', 'modules'.
44 IDL_FILES_LIST is a text file containing the IDL file paths, so the command
45 line doesn't exceed OS length limits.
46 OUTPUT_FILE1 etc. are filenames of output files.
47
48 Design doc: http://www.chromium.org/developers/design-documents/idl-build 40 Design doc: http://www.chromium.org/developers/design-documents/idl-build
49 """ 41 """
50 42
43 import cPickle as pickle
51 import errno 44 import errno
45 from optparse import OptionParser
52 import os 46 import os
53 import re 47 import re
54 import sys 48 import sys
55 49
56 from utilities import idl_filename_to_interface_name, read_idl_files_list_from_f ile 50 from idl_reader import IdlReader
51 from utilities import idl_filename_to_component, idl_filename_to_interface_name, read_idl_files_list_from_file
57 52
58 # A regexp for finding Conditional attributes in interface definitions. 53 # A regexp for finding Conditional attributes in interface definitions.
59 CONDITIONAL_PATTERN = re.compile( 54 CONDITIONAL_PATTERN = re.compile(
60 r'\[' 55 r'\['
61 r'[^\]]*' 56 r'[^\]]*'
62 r'Conditional=([\_0-9a-zA-Z]*)' 57 r'Conditional=([\_0-9a-zA-Z]*)'
63 r'[^\]]*' 58 r'[^\]]*'
64 r'\]\s*' 59 r'\]\s*'
65 r'((callback|partial)\s+)?' 60 r'((callback|partial)\s+)?'
66 r'interface\s+' 61 r'interface\s+'
(...skipping 26 matching lines...) Expand all
93 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 88 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
94 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 89 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
95 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 90 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
96 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 91 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
97 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 92 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
98 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 93 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
99 */ 94 */
100 """ 95 """
101 96
102 97
98 def parse_options():
99 usage = 'Usage: %prog [options] OUTPUT_FILE1 OUTPUT_FILE2 ...'
100 parser = OptionParser(usage=usage)
101 parser.add_option('--cache-directory',
102 help='cache directory, defaults to output directory')
103 parser.add_option('--idl-files-list', help="a text file containing the IDL f ile paths, so the command line doesn't exceed OS length limits.")
104 parser.add_option('--component-dir', help="the relative directory of a compo nent, e.g., 'core', 'modules'")
105 parser.add_option('--partial', type='int', help='if true, aggregates partial interface code, e.g. V8XXXPartial.cpp')
bashi 2014/10/10 09:48:11 --partial -> --aggregate-partial-interfaces How a
tasak 2014/10/10 11:43:40 Removed this flag.
106 parser.add_option('--interfaces-info')
107 parser.add_option('--write-file-only-if-changed', type='int')
108 # ensure output comes last, so command line easy to parse via regexes
109 parser.disable_interspersed_args()
110
111 options, args = parser.parse_args()
112 if options.idl_files_list is None:
113 parser.error('Must specify idl files list file using --idl-files-list.')
114 if options.component_dir is None:
115 parser.error('Must specify component directory using --component-dir.')
116 if options.partial:
117 if options.interfaces_info is None:
118 parser.error('Must specify interfaces info using --interfaces-info-f ile because of --partial.')
119 options.partial = True
120 else:
121 options.partial = False
122 options.write_file_only_if_changed = bool(options.write_file_only_if_changed )
123 if len(args) == 0:
124 parser.error('Must specify exactly more than 1 output file as argument, but %d given.' % len(args))
bashi 2014/10/10 09:48:11 'Must specify one or more output files...' ?
tasak 2014/10/10 11:43:40 Done.
125 return options, args[0:]
126
127
128 def format_conditional(conditional):
129 """Wraps conditional with ENABLE() and replace '&','|' with '&&','||' if
130 more than one conditional is specified."""
131 def wrap_with_enable(s):
132 if s in ['|', '&']:
133 return s * 2
134 return 'ENABLE(' + s + ')'
135 return ' '.join(map(wrap_with_enable, conditional))
136
137
103 def extract_conditional(idl_file_path): 138 def extract_conditional(idl_file_path):
104 """Find [Conditional] interface extended attribute.""" 139 """Find [Conditional] interface extended attribute."""
105 with open(idl_file_path) as idl_file: 140 with open(idl_file_path) as idl_file:
106 idl_contents = idl_file.read() 141 idl_contents = idl_file.read()
107 142
108 match = CONDITIONAL_PATTERN.search(idl_contents) 143 match = CONDITIONAL_PATTERN.search(idl_contents)
109 if not match: 144 if not match:
110 return None 145 return None
111 return match.group(1) 146 return match.group(1)
112 147
(...skipping 15 matching lines...) Expand all
128 163
129 meta_data = { 164 meta_data = {
130 'conditional': extract_conditional(file_path), 165 'conditional': extract_conditional(file_path),
131 'name': interface_name, 166 'name': interface_name,
132 } 167 }
133 meta_data_list.append(meta_data) 168 meta_data_list.append(meta_data)
134 169
135 return meta_data_list 170 return meta_data_list
136 171
137 172
138 def generate_content(component_dir, files_meta_data_this_partition): 173 def generate_content(component_dir, partial, files_meta_data_this_partition):
139 # Add fixed content. 174 # Add fixed content.
140 output = [COPYRIGHT_TEMPLATE, 175 output = [COPYRIGHT_TEMPLATE,
141 '#define NO_IMPLICIT_ATOMICSTRING\n\n'] 176 '#define NO_IMPLICIT_ATOMICSTRING\n\n']
142 177
143 # List all includes segmented by if and endif. 178 # List all includes segmented by if and endif.
144 prev_conditional = None 179 prev_conditional = None
145 files_meta_data_this_partition.sort(key=lambda e: e['conditional']) 180 files_meta_data_this_partition.sort(key=lambda e: e['conditional'])
146 for meta_data in files_meta_data_this_partition: 181 for meta_data in files_meta_data_this_partition:
147 conditional = meta_data['conditional'] 182 conditional = meta_data['conditional']
148 if prev_conditional != conditional: 183 if prev_conditional != conditional:
149 if prev_conditional: 184 if prev_conditional:
150 output.append('#endif\n') 185 output.append('#endif\n')
151 if conditional: 186 if conditional:
152 output.append('\n#if ENABLE(%s)\n' % conditional) 187 output.append('\n#if ENABLE(%s)\n' % conditional)
153 prev_conditional = conditional 188 prev_conditional = conditional
154 189
155 output.append('#include "bindings/%s/v8/V8%s.cpp"\n' % 190 output.append('#include "bindings/%s/v8/V8%s%s.cpp"\n' %
156 (component_dir, meta_data['name'])) 191 (component_dir, meta_data['name'], 'Partial' if partial el se ''))
157 192
158 if prev_conditional: 193 if prev_conditional:
159 output.append('#endif\n') 194 output.append('#endif\n')
160 195
161 return ''.join(output) 196 return ''.join(output)
162 197
163 198
164 def write_content(content, output_file_name): 199 def write_content(content, output_file_name):
165 parent_path, file_name = os.path.split(output_file_name) 200 parent_path, file_name = os.path.split(output_file_name)
166 if not os.path.exists(parent_path): 201 if not os.path.exists(parent_path):
167 print 'Creating directory: %s' % parent_path 202 print 'Creating directory: %s' % parent_path
168 os.makedirs(parent_path) 203 os.makedirs(parent_path)
169 with open(output_file_name, 'w') as f: 204 with open(output_file_name, 'w') as f:
170 f.write(content) 205 f.write(content)
171 206
172 207
208 def filter_partial_interface(idl_filenames, interfaces_info, cache_directory):
209 reader = IdlReader(interfaces_info, cache_directory)
210
211 patched_idl_filenames = []
212 for idl_filename in idl_filenames:
213 interface_name = idl_filename_to_interface_name(idl_filename)
214 component = idl_filename_to_component(idl_filename)
bashi 2014/10/10 09:48:11 Can |component| be different from options.componen
tasak 2014/10/10 11:43:40 Yes. To aggregate partial interface code, idl_file
215 definitions = reader.read_idl_definitions(idl_filename)
216 if len(definitions.keys()) == 1 and definitions[component]:
bashi 2014/10/10 09:48:11 Could you elaborate on this condition?
tasak 2014/10/10 11:43:40 Removed. Instead, added "raise exception" when a g
217 continue
218
219 patched_idl_filenames.append(idl_filename)
220
221 return patched_idl_filenames
222
223
173 def main(args): 224 def main(args):
174 if len(args) <= 4: 225 options, output_file_names = parse_options()
175 raise Exception('Expected at least 5 arguments.')
176 component_dir = args[1]
177 input_file_name = args[2]
178 in_out_break_index = args.index('--')
179 output_file_names = args[in_out_break_index + 1:]
180 226
181 idl_file_names = read_idl_files_list_from_file(input_file_name) 227 idl_file_names = read_idl_files_list_from_file(options.idl_files_list)
228 if options.partial:
229 with open(options.interfaces_info) as interfaces_info_file:
230 interfaces_info = pickle.load(interfaces_info_file)
231 idl_file_names = filter_partial_interface(idl_file_names, interfaces_inf o, options.cache_directory)
232
182 files_meta_data = extract_meta_data(idl_file_names) 233 files_meta_data = extract_meta_data(idl_file_names)
183 total_partitions = len(output_file_names) 234 total_partitions = len(output_file_names)
184 for partition, file_name in enumerate(output_file_names): 235 for partition, file_name in enumerate(output_file_names):
185 files_meta_data_this_partition = [ 236 files_meta_data_this_partition = [
186 meta_data for meta_data in files_meta_data 237 meta_data for meta_data in files_meta_data
187 if hash(meta_data['name']) % total_partitions == partition] 238 if hash(meta_data['name']) % total_partitions == partition]
188 file_contents = generate_content(component_dir, 239 file_contents = generate_content(options.component_dir,
240 options.partial,
189 files_meta_data_this_partition) 241 files_meta_data_this_partition)
190 write_content(file_contents, file_name) 242 write_content(file_contents, file_name)
191 243
192 244
193 if __name__ == '__main__': 245 if __name__ == '__main__':
194 sys.exit(main(sys.argv)) 246 sys.exit(main(sys.argv))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698