OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """The frontend for the Mojo bindings system.""" | 6 """The frontend for the Mojo bindings system.""" |
7 | 7 |
8 | 8 |
9 import argparse | 9 import argparse |
10 import imp | 10 import imp |
11 import json | |
11 import os | 12 import os |
12 import pprint | 13 import pprint |
14 import re | |
13 import sys | 15 import sys |
14 | 16 |
15 # Disable lint check for finding modules: | 17 # Disable lint check for finding modules: |
16 # pylint: disable=F0401 | 18 # pylint: disable=F0401 |
17 | 19 |
18 def _GetDirAbove(dirname): | 20 def _GetDirAbove(dirname): |
19 """Returns the directory "above" this file containing |dirname| (which must | 21 """Returns the directory "above" this file containing |dirname| (which must |
20 also be "above" this file).""" | 22 also be "above" this file).""" |
21 path = os.path.abspath(__file__) | 23 path = os.path.abspath(__file__) |
22 while True: | 24 while True: |
(...skipping 10 matching lines...) Expand all Loading... | |
33 sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), | 35 sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), |
34 "pylib")) | 36 "pylib")) |
35 | 37 |
36 from mojom.error import Error | 38 from mojom.error import Error |
37 import mojom.fileutil as fileutil | 39 import mojom.fileutil as fileutil |
38 from mojom.generate.data import OrderedModuleFromData | 40 from mojom.generate.data import OrderedModuleFromData |
39 from mojom.parse.parser import Parse | 41 from mojom.parse.parser import Parse |
40 from mojom.parse.translate import Translate | 42 from mojom.parse.translate import Translate |
41 | 43 |
42 | 44 |
45 _BUILTIN_GENERATORS = { | |
46 "c++": "mojom_cpp_generator.py", | |
47 "javascript": "mojom_js_generator.py", | |
48 "java": "mojom_java_generator.py", | |
49 } | |
50 | |
43 def LoadGenerators(generators_string): | 51 def LoadGenerators(generators_string): |
44 if not generators_string: | 52 if not generators_string: |
45 return [] # No generators. | 53 return [] # No generators. |
46 | 54 |
47 script_dir = os.path.dirname(os.path.abspath(__file__)) | 55 script_dir = os.path.dirname(os.path.abspath(__file__)) |
48 generators = [] | 56 generators = {} |
49 for generator_name in [s.strip() for s in generators_string.split(",")]: | 57 for generator_name in [s.strip() for s in generators_string.split(",")]: |
50 # "Built-in" generators: | 58 language = generator_name.lower() |
51 if generator_name.lower() == "c++": | 59 if language in _BUILTIN_GENERATORS: |
52 generator_name = os.path.join(script_dir, "generators", | 60 generator_name = os.path.join(script_dir, "generators", |
53 "mojom_cpp_generator.py") | 61 _BUILTIN_GENERATORS[language]) |
54 elif generator_name.lower() == "javascript": | |
55 generator_name = os.path.join(script_dir, "generators", | |
56 "mojom_js_generator.py") | |
57 elif generator_name.lower() == "java": | |
58 generator_name = os.path.join(script_dir, "generators", | |
59 "mojom_java_generator.py") | |
60 # Specified generator python module: | |
61 elif generator_name.endswith(".py"): | 62 elif generator_name.endswith(".py"): |
yzshen1
2015/12/15 00:09:10
This elif is probably not useful.
| |
62 pass | 63 pass |
63 else: | 64 else: |
64 print "Unknown generator name %s" % generator_name | 65 print "Unknown generator name %s" % generator_name |
65 sys.exit(1) | 66 sys.exit(1) |
66 generator_module = imp.load_source(os.path.basename(generator_name)[:-3], | 67 generator_module = imp.load_source(os.path.basename(generator_name)[:-3], |
67 generator_name) | 68 generator_name) |
68 generators.append(generator_module) | 69 generators[language] = generator_module |
69 return generators | 70 return generators |
70 | 71 |
71 | 72 |
72 def MakeImportStackMessage(imported_filename_stack): | 73 def MakeImportStackMessage(imported_filename_stack): |
73 """Make a (human-readable) message listing a chain of imports. (Returned | 74 """Make a (human-readable) message listing a chain of imports. (Returned |
74 string begins with a newline (if nonempty) and does not end with one.)""" | 75 string begins with a newline (if nonempty) and does not end with one.)""" |
75 return ''.join( | 76 return ''.join( |
76 reversed(["\n %s was imported by %s" % (a, b) for (a, b) in \ | 77 reversed(["\n %s was imported by %s" % (a, b) for (a, b) in \ |
77 zip(imported_filename_stack[1:], imported_filename_stack)])) | 78 zip(imported_filename_stack[1:], imported_filename_stack)])) |
78 | 79 |
79 | 80 |
80 def FindImportFile(dir_name, file_name, search_dirs): | 81 def FindImportFile(dir_name, file_name, search_dirs): |
81 for search_dir in [dir_name] + search_dirs: | 82 for search_dir in [dir_name] + search_dirs: |
82 path = os.path.join(search_dir, file_name) | 83 path = os.path.join(search_dir, file_name) |
83 if os.path.isfile(path): | 84 if os.path.isfile(path): |
84 return path | 85 return path |
85 return os.path.join(dir_name, file_name) | 86 return os.path.join(dir_name, file_name) |
86 | 87 |
87 class MojomProcessor(object): | 88 class MojomProcessor(object): |
88 def __init__(self, should_generate): | 89 def __init__(self, should_generate): |
89 self._should_generate = should_generate | 90 self._should_generate = should_generate |
90 self._processed_files = {} | 91 self._processed_files = {} |
91 self._parsed_files = {} | 92 self._parsed_files = {} |
93 self._typemap = {} | |
94 | |
95 def LoadTypemaps(self, typemaps): | |
yzshen1
2015/12/15 00:09:10
Please consider writing tests in:
https://code.goo
| |
96 # Support some very simple single-line comments in typemap JSON. | |
97 comment_expr = r"^\s*//.*$" | |
98 def no_comments(line): | |
99 return not re.match(comment_expr, line) | |
100 for filename in typemaps: | |
101 with open(filename) as f: | |
102 typemaps = json.loads("".join(filter(no_comments, f.readlines()))) | |
103 for language, typemap in typemaps.iteritems(): | |
104 language_map = self._typemap.get(language, {}) | |
105 language_map.update(typemap) | |
106 self._typemap[language] = language_map | |
92 | 107 |
93 def ProcessFile(self, args, remaining_args, generator_modules, filename): | 108 def ProcessFile(self, args, remaining_args, generator_modules, filename): |
94 self._ParseFileAndImports(filename, args.import_directories, []) | 109 self._ParseFileAndImports(filename, args.import_directories, []) |
95 | 110 |
96 return self._GenerateModule(args, remaining_args, generator_modules, | 111 return self._GenerateModule(args, remaining_args, generator_modules, |
97 filename) | 112 filename) |
98 | 113 |
99 def _GenerateModule(self, args, remaining_args, generator_modules, filename): | 114 def _GenerateModule(self, args, remaining_args, generator_modules, filename): |
100 # Return the already-generated module. | 115 # Return the already-generated module. |
101 if filename in self._processed_files: | 116 if filename in self._processed_files: |
(...skipping 17 matching lines...) Expand all Loading... | |
119 module = OrderedModuleFromData(mojom) | 134 module = OrderedModuleFromData(mojom) |
120 | 135 |
121 # Set the path as relative to the source root. | 136 # Set the path as relative to the source root. |
122 module.path = os.path.relpath(os.path.abspath(filename), | 137 module.path = os.path.relpath(os.path.abspath(filename), |
123 os.path.abspath(args.depth)) | 138 os.path.abspath(args.depth)) |
124 | 139 |
125 # Normalize to unix-style path here to keep the generators simpler. | 140 # Normalize to unix-style path here to keep the generators simpler. |
126 module.path = module.path.replace('\\', '/') | 141 module.path = module.path.replace('\\', '/') |
127 | 142 |
128 if self._should_generate(filename): | 143 if self._should_generate(filename): |
129 for generator_module in generator_modules: | 144 for language, generator_module in generator_modules.iteritems(): |
130 generator = generator_module.Generator(module, args.output_dir) | 145 generator = generator_module.Generator( |
146 module, args.output_dir, typemap=self._typemap.get(language, {}), | |
147 variant=args.variant) | |
131 filtered_args = [] | 148 filtered_args = [] |
132 if hasattr(generator_module, 'GENERATOR_PREFIX'): | 149 if hasattr(generator_module, 'GENERATOR_PREFIX'): |
133 prefix = '--' + generator_module.GENERATOR_PREFIX + '_' | 150 prefix = '--' + generator_module.GENERATOR_PREFIX + '_' |
134 filtered_args = [arg for arg in remaining_args | 151 filtered_args = [arg for arg in remaining_args |
135 if arg.startswith(prefix)] | 152 if arg.startswith(prefix)] |
136 generator.GenerateFiles(filtered_args) | 153 generator.GenerateFiles(filtered_args) |
137 | 154 |
138 # Save result. | 155 # Save result. |
139 self._processed_files[filename] = module | 156 self._processed_files[filename] = module |
140 return module | 157 return module |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 metavar="GENERATORS", | 205 metavar="GENERATORS", |
189 default="c++,javascript,java", | 206 default="c++,javascript,java", |
190 help="comma-separated list of generators") | 207 help="comma-separated list of generators") |
191 parser.add_argument("--debug_print_intermediate", action="store_true", | 208 parser.add_argument("--debug_print_intermediate", action="store_true", |
192 help="print the intermediate representation") | 209 help="print the intermediate representation") |
193 parser.add_argument("-I", dest="import_directories", action="append", | 210 parser.add_argument("-I", dest="import_directories", action="append", |
194 metavar="directory", default=[], | 211 metavar="directory", default=[], |
195 help="add a directory to be searched for import files") | 212 help="add a directory to be searched for import files") |
196 parser.add_argument("--use_bundled_pylibs", action="store_true", | 213 parser.add_argument("--use_bundled_pylibs", action="store_true", |
197 help="use Python modules bundled in the SDK") | 214 help="use Python modules bundled in the SDK") |
215 parser.add_argument("--typemap", action="append", metavar="TYPEMAP", | |
216 default=[], dest="typemaps", | |
217 help="apply TYPEMAP to generated output") | |
218 parser.add_argument("--variant", dest="variant", default=None, | |
219 help="output a named variant of the bindings") | |
198 (args, remaining_args) = parser.parse_known_args() | 220 (args, remaining_args) = parser.parse_known_args() |
199 | 221 |
200 generator_modules = LoadGenerators(args.generators_string) | 222 generator_modules = LoadGenerators(args.generators_string) |
201 | 223 |
202 fileutil.EnsureDirectoryExists(args.output_dir) | 224 fileutil.EnsureDirectoryExists(args.output_dir) |
203 | 225 |
204 processor = MojomProcessor(lambda filename: filename in args.filename) | 226 processor = MojomProcessor(lambda filename: filename in args.filename) |
227 processor.LoadTypemaps(set(args.typemaps)) | |
205 for filename in args.filename: | 228 for filename in args.filename: |
206 processor.ProcessFile(args, remaining_args, generator_modules, filename) | 229 processor.ProcessFile(args, remaining_args, generator_modules, filename) |
207 | 230 |
208 return 0 | 231 return 0 |
209 | 232 |
210 | 233 |
211 if __name__ == "__main__": | 234 if __name__ == "__main__": |
212 sys.exit(main()) | 235 sys.exit(main()) |
OLD | NEW |