| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 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 | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 """The frontend for the Mojo bindings system.""" | |
| 7 | |
| 8 | |
| 9 import argparse | |
| 10 import imp | |
| 11 import os | |
| 12 import pprint | |
| 13 import sys | |
| 14 | |
| 15 script_dir = os.path.dirname(os.path.realpath(__file__)) | |
| 16 sys.path.insert(0, os.path.join(script_dir, "pylib")) | |
| 17 | |
| 18 from generate import mojom_data | |
| 19 from parse import mojo_lexer | |
| 20 from parse import mojo_parser | |
| 21 from parse import mojo_translate | |
| 22 | |
| 23 | |
| 24 def LoadGenerators(generators_string): | |
| 25 if not generators_string: | |
| 26 return [] # No generators. | |
| 27 | |
| 28 generators = [] | |
| 29 for generator_name in [s.strip() for s in generators_string.split(",")]: | |
| 30 # "Built-in" generators: | |
| 31 if generator_name.lower() == "c++": | |
| 32 generator_name = os.path.join(script_dir, "generators", | |
| 33 "mojom_cpp_generator.py") | |
| 34 elif generator_name.lower() == "javascript": | |
| 35 generator_name = os.path.join(script_dir, "generators", | |
| 36 "mojom_js_generator.py") | |
| 37 # Specified generator python module: | |
| 38 elif generator_name.endswith(".py"): | |
| 39 pass | |
| 40 else: | |
| 41 print "Unknown generator name %s" % generator_name | |
| 42 sys.exit(1) | |
| 43 generator_module = imp.load_source(os.path.basename(generator_name)[:-3], | |
| 44 generator_name) | |
| 45 generators.append(generator_module) | |
| 46 return generators | |
| 47 | |
| 48 | |
| 49 def _PrintImportStack(imported_filename_stack): | |
| 50 """Prints a chain of imports, given by imported_filename_stack.""" | |
| 51 for i in reversed(xrange(0, len(imported_filename_stack)-1)): | |
| 52 print " %s was imported by %s" % (imported_filename_stack[i+1], | |
| 53 imported_filename_stack[i]) | |
| 54 | |
| 55 def ProcessFile(args, generator_modules, filename, processed_files={}, | |
| 56 imported_filename_stack=[]): | |
| 57 # Memoized results. | |
| 58 if filename in processed_files: | |
| 59 return processed_files[filename] | |
| 60 | |
| 61 # Ensure we only visit each file once. | |
| 62 if filename in imported_filename_stack: | |
| 63 print "%s: Error: Circular dependency" % filename | |
| 64 _PrintImportStack(imported_filename_stack + [filename]) | |
| 65 sys.exit(1) | |
| 66 | |
| 67 try: | |
| 68 with open(filename) as f: | |
| 69 source = f.read() | |
| 70 except IOError as e: | |
| 71 print "%s: Error: %s" % (e.filename, e.strerror) | |
| 72 _PrintImportStack(imported_filename_stack + [filename]) | |
| 73 sys.exit(1) | |
| 74 | |
| 75 try: | |
| 76 tree = mojo_parser.Parse(source, filename) | |
| 77 except (mojo_lexer.LexError, mojo_parser.ParseError) as e: | |
| 78 print e | |
| 79 _PrintImportStack(imported_filename_stack + [filename]) | |
| 80 sys.exit(1) | |
| 81 | |
| 82 dirname, name = os.path.split(filename) | |
| 83 mojom = mojo_translate.Translate(tree, name) | |
| 84 if args.debug_print_intermediate: | |
| 85 pprint.PrettyPrinter().pprint(mojom) | |
| 86 | |
| 87 # Process all our imports first and collect the module object for each. | |
| 88 # We use these to generate proper type info. | |
| 89 for import_data in mojom['imports']: | |
| 90 import_filename = os.path.join(dirname, import_data['filename']) | |
| 91 import_data['module'] = ProcessFile( | |
| 92 args, generator_modules, import_filename, | |
| 93 processed_files=processed_files, | |
| 94 imported_filename_stack=imported_filename_stack + [filename]) | |
| 95 | |
| 96 module = mojom_data.OrderedModuleFromData(mojom) | |
| 97 | |
| 98 # Set the path as relative to the source root. | |
| 99 module.path = os.path.relpath(os.path.abspath(filename), | |
| 100 os.path.abspath(args.depth)) | |
| 101 | |
| 102 # Normalize to unix-style path here to keep the generators simpler. | |
| 103 module.path = module.path.replace('\\', '/') | |
| 104 | |
| 105 for generator_module in generator_modules: | |
| 106 generator = generator_module.Generator(module, args.output_dir) | |
| 107 generator.GenerateFiles() | |
| 108 | |
| 109 # Save result. | |
| 110 processed_files[filename] = module | |
| 111 return module | |
| 112 | |
| 113 | |
| 114 def Main(): | |
| 115 parser = argparse.ArgumentParser( | |
| 116 description="Generate bindings from mojom files.") | |
| 117 parser.add_argument("filename", nargs="+", | |
| 118 help="mojom input file") | |
| 119 parser.add_argument("-d", "--depth", dest="depth", default=".", | |
| 120 help="depth from source root") | |
| 121 parser.add_argument("-o", "--output_dir", dest="output_dir", default=".", | |
| 122 help="output directory for generated files") | |
| 123 parser.add_argument("-g", "--generators", dest="generators_string", | |
| 124 metavar="GENERATORS", default="c++,javascript", | |
| 125 help="comma-separated list of generators") | |
| 126 parser.add_argument("--debug_print_intermediate", action="store_true", | |
| 127 help="print the intermediate representation") | |
| 128 args = parser.parse_args() | |
| 129 | |
| 130 generator_modules = LoadGenerators(args.generators_string) | |
| 131 | |
| 132 if not os.path.exists(args.output_dir): | |
| 133 os.makedirs(args.output_dir) | |
| 134 | |
| 135 for filename in args.filename: | |
| 136 ProcessFile(args, generator_modules, filename) | |
| 137 | |
| 138 return 0 | |
| 139 | |
| 140 | |
| 141 if __name__ == "__main__": | |
| 142 sys.exit(Main()) | |
| OLD | NEW |