3 # Copyright 2014 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 """Compute global objects.
9 Global objects are defined by interfaces with [Global] or [PrimaryGlobal] on
10 their definition: http://heycam.github.io/webidl/#Global
12 Design document: http://www.chromium.org/developers/design-documents/idl-build
17 import cPickle
as pickle
20 from utilities
import get_file_contents
, idl_filename_to_interface_name
, get_interface_extended_attributes_from_idl
, read_file_to_list
, read_pickle_files
, write_pickle_file
22 GLOBAL_EXTENDED_ATTRIBUTES
= frozenset([
29 usage
= 'Usage: %prog [options] [GlobalObjectsComponent.pickle]... [GlobalObjects.pickle]'
30 parser
= optparse
.OptionParser(usage
=usage
)
31 parser
.add_option('--idl-files-list', help='file listing IDL files')
32 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')
34 options
, args
= parser
.parse_args()
36 if options
.idl_files_list
is None:
37 parser
.error('Must specify a file listing IDL files using --idl-files-list.')
38 if options
.write_file_only_if_changed
is None:
39 parser
.error('Must specify whether output files are only written if changed using --write-file-only-if-changed.')
40 options
.write_file_only_if_changed
= bool(options
.write_file_only_if_changed
)
42 parser
.error('Must specify an output pickle filename as argument, '
43 'optionally preceeded by input pickle filenames.')
48 def dict_union(dicts
):
49 return dict((k
, v
) for d
in dicts
for k
, v
in d
.iteritems())
52 def idl_file_to_global_names(idl_filename
):
53 """Returns global names, if any, for an IDL file.
55 If the [Global] or [PrimaryGlobal] extended attribute is declared with an
56 identifier list argument, then those identifiers are the interface's global
57 names; otherwise, the interface has a single global name, which is the
58 interface's identifier (http://heycam.github.io/webidl/#Global).
60 interface_name
= idl_filename_to_interface_name(idl_filename
)
61 full_path
= os
.path
.realpath(idl_filename
)
62 idl_file_contents
= get_file_contents(full_path
)
63 extended_attributes
= get_interface_extended_attributes_from_idl(idl_file_contents
)
65 global_keys
= GLOBAL_EXTENDED_ATTRIBUTES
.intersection(
66 extended_attributes
.iterkeys())
69 if len(global_keys
) > 1:
70 raise ValueError('The [Global] and [PrimaryGlobal] extended attributes '
71 'MUST NOT be declared on the same interface.')
72 global_key
= next(iter(global_keys
))
74 global_value
= extended_attributes
[global_key
]
76 return global_value
.strip('()').split(',')
77 return [interface_name
]
80 def idl_files_to_interface_name_global_names(idl_files
):
81 """Yields pairs (interface_name, global_names) found in IDL files."""
82 for idl_filename
in idl_files
:
83 interface_name
= idl_filename_to_interface_name(idl_filename
)
84 global_names
= idl_file_to_global_names(idl_filename
)
86 yield interface_name
, global_names
89 ################################################################################
92 options
, args
= parse_options()
93 # args = Input1, Input2, ..., Output
94 output_global_objects_filename
= args
.pop()
95 interface_name_global_names
= dict_union(
96 existing_interface_name_global_names
97 for existing_interface_name_global_names
in read_pickle_files(args
))
99 # Input IDL files are passed in a file, due to OS command line length
100 # limits. This is generated at GYP time, which is ok b/c files are static.
101 idl_files
= read_file_to_list(options
.idl_files_list
)
102 interface_name_global_names
.update(
103 idl_files_to_interface_name_global_names(idl_files
))
105 write_pickle_file(output_global_objects_filename
,
106 interface_name_global_names
,
107 options
.write_file_only_if_changed
)
110 if __name__
== '__main__':