OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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)) |
OLD | NEW |