| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright 2015 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 # This script accepts the output of the mojom parser and uses that | |
| 7 # data to invoke the code generators. | |
| 8 | |
| 9 import argparse | |
| 10 import imp | |
| 11 import os | |
| 12 import sys | |
| 13 | |
| 14 | |
| 15 def _ParseCLIArgs(): | |
| 16 """Parses the command line arguments. | |
| 17 | |
| 18 Returns: | |
| 19 tuple<Namespace, list<str>> The first value of the tuple is a Namespace | |
| 20 holding the value of the optional args. The second value of the tuple is | |
| 21 a list of the remaining arguments. | |
| 22 """ | |
| 23 parser = argparse.ArgumentParser( | |
| 24 description='Generate bindings from mojom parser output.') | |
| 25 parser.add_argument('filenames', nargs='*', | |
| 26 help='Filter on the set of .mojom files for which code ' | |
| 27 'will be generated.') | |
| 28 parser.add_argument('-f', '--file-graph', dest='file_graph', | |
| 29 help='Location of the parser output. "-" for stdin. ' | |
| 30 '(default "-")', default='-') | |
| 31 parser.add_argument("-o", "--output-dir", dest="output_dir", default=".", | |
| 32 help="output directory for generated files") | |
| 33 parser.add_argument("-g", "--generators", dest="generators_string", | |
| 34 metavar="GENERATORS", | |
| 35 default="c++,dart,javascript,java,python", | |
| 36 help="comma-separated list of generators") | |
| 37 parser.add_argument("-s", "--src-root-path", dest="src_root_path", | |
| 38 default=".", | |
| 39 help="relative path to the root of the source tree.") | |
| 40 parser.add_argument("--no-gen-imports", action="store_true", | |
| 41 help="Generate code only for the files that are " | |
| 42 "specified on the command line. By default, code " | |
| 43 "is generated for all specified files and their " | |
| 44 "transitive imports.") | |
| 45 parser.add_argument("--generate-type-info", dest="generate_type_info", | |
| 46 action="store_true", | |
| 47 help="generate mojom type descriptors") | |
| 48 parser.set_defaults(generate_type_info=False) | |
| 49 | |
| 50 return parser.parse_known_args() | |
| 51 | |
| 52 # We assume this script is located in the Mojo SDK in tools/bindings. | |
| 53 # If __file__ is a link, we look for the real location of the script. | |
| 54 BINDINGS_DIR = os.path.dirname(os.path.realpath(os.path.abspath(__file__))) | |
| 55 SDK_ROOT = os.path.abspath(os.path.join(BINDINGS_DIR, os.pardir, os.pardir)) | |
| 56 PYTHON_SDK_DIR = os.path.abspath(os.path.join(SDK_ROOT, "python")) | |
| 57 | |
| 58 sys.path.insert(0, PYTHON_SDK_DIR) | |
| 59 # In order to use mojom_files_mojom we need to make sure the dummy mojo_system | |
| 60 # can be found on the python path. | |
| 61 sys.path.insert(0, os.path.join(PYTHON_SDK_DIR, "dummy_mojo_system")) | |
| 62 | |
| 63 sys.path.insert(0, os.path.join(BINDINGS_DIR, "pylib")) | |
| 64 | |
| 65 | |
| 66 from mojom.generate.generated import mojom_files_mojom | |
| 67 from mojom.generate import mojom_translator | |
| 68 from mojom.parse import parser_runner | |
| 69 from mojo_bindings import serialization | |
| 70 | |
| 71 | |
| 72 def LoadGenerators(generators_string): | |
| 73 if not generators_string: | |
| 74 return [] # No generators. | |
| 75 | |
| 76 generators_dir = os.path.join(BINDINGS_DIR, "generators") | |
| 77 generators = [] | |
| 78 for generator_name in [s.strip() for s in generators_string.split(",")]: | |
| 79 generator_name_lower = generator_name.lower() | |
| 80 # "Built-in" generators: | |
| 81 if generator_name_lower == "c++": | |
| 82 generator_py_name = os.path.join(generators_dir, | |
| 83 "mojom_cpp_generator.py") | |
| 84 elif generator_name_lower == "dart": | |
| 85 generator_py_name = os.path.join(generators_dir, | |
| 86 "mojom_dart_generator.py") | |
| 87 elif generator_name_lower == "go": | |
| 88 generator_py_name = os.path.join(generators_dir, | |
| 89 "mojom_go_generator.py") | |
| 90 elif generator_name_lower == "javascript": | |
| 91 generator_py_name = os.path.join(generators_dir, | |
| 92 "mojom_js_generator.py") | |
| 93 elif generator_name_lower == "java": | |
| 94 generator_py_name = os.path.join(generators_dir, | |
| 95 "mojom_java_generator.py") | |
| 96 elif generator_name_lower == "python": | |
| 97 generator_py_name = os.path.join(generators_dir, | |
| 98 "mojom_python_generator.py") | |
| 99 # Specified generator python module: | |
| 100 elif generator_name.endswith(".py"): | |
| 101 generator_py_name = generator_name | |
| 102 else: | |
| 103 print "Unknown generator name %s" % generator_name | |
| 104 sys.exit(1) | |
| 105 generator_module = imp.load_source(os.path.basename(generator_py_name)[:-3], | |
| 106 generator_py_name) | |
| 107 generators.append(generator_module) | |
| 108 return generators | |
| 109 | |
| 110 | |
| 111 def ReadMojomFileGraphFromFile(fp): | |
| 112 """Reads a mojom_files_mojom.MojomFileGraph from a file. | |
| 113 | |
| 114 Args: | |
| 115 fp: A file pointer from which a serialized mojom_fileS_mojom.MojomFileGraph | |
| 116 can be read. | |
| 117 | |
| 118 Returns: | |
| 119 The mojom_files_mojom.MojomFileGraph that was deserialized from the file. | |
| 120 """ | |
| 121 return parser_runner.DeserializeMojomFileGraph(fp.read()) | |
| 122 | |
| 123 def FixModulePath(module, abs_src_root_path): | |
| 124 """Fix the path attribute of the provided module and its imports. | |
| 125 | |
| 126 The path provided for the various modules is the absolute path to the mojom | |
| 127 file which the module represents. But the generators expect the path to be | |
| 128 relative to the root of the source tree. | |
| 129 | |
| 130 Args: | |
| 131 module: {module.Module} whose path is to be updated. | |
| 132 abs_src_root_path: {str} absolute path to the root of the source tree. | |
| 133 """ | |
| 134 module.path = os.path.relpath(module.path, abs_src_root_path) | |
| 135 if not hasattr(module, 'imports'): | |
| 136 return | |
| 137 for import_dict in module.imports: | |
| 138 FixModulePath(import_dict['module'], abs_src_root_path) | |
| 139 | |
| 140 | |
| 141 def main(): | |
| 142 args, remaining_args = _ParseCLIArgs() | |
| 143 | |
| 144 if args.file_graph == '-': | |
| 145 fp = sys.stdin | |
| 146 else: | |
| 147 fp = open(args.file_graph) | |
| 148 | |
| 149 mojom_file_graph = ReadMojomFileGraphFromFile(fp) | |
| 150 mojom_modules = mojom_translator.TranslateFileGraph(mojom_file_graph) | |
| 151 | |
| 152 # Note that we are using the word "module" in two unrelated ways here. | |
| 153 # A mojom module is the Python data structure defined in module.py that | |
| 154 # represents a Mojom file (sometimes referred to as a Mojom module.) | |
| 155 # A generator module is a Python module in the sense of the entity the Python | |
| 156 # runtime loads corresponding to a .py file. | |
| 157 generator_modules = LoadGenerators(args.generators_string) | |
| 158 | |
| 159 abs_src_root_path = os.path.abspath(args.src_root_path) | |
| 160 for _, mojom_module in mojom_modules.iteritems(): | |
| 161 # If --no-gen-imports is specified then skip the code generation step for | |
| 162 # any modules that do not have the |specified_name| field set. This field | |
| 163 # being set indicates that the module was translated from a .mojom file | |
| 164 # whose name was explicitly requested during parsing. Otherwise the module | |
| 165 # is included only becuase of a mojom import statement. | |
| 166 if args.no_gen_imports and not mojom_module.specified_name: | |
| 167 continue | |
| 168 FixModulePath(mojom_module, abs_src_root_path) | |
| 169 for generator_module in generator_modules: | |
| 170 generator = generator_module.Generator(mojom_module, args.output_dir) | |
| 171 | |
| 172 # Look at unparsed args for generator-specific args. | |
| 173 filtered_args = [] | |
| 174 if hasattr(generator_module, 'GENERATOR_PREFIX'): | |
| 175 prefix = '--' + generator_module.GENERATOR_PREFIX + '_' | |
| 176 filtered_args = [arg for arg in remaining_args | |
| 177 if arg.startswith(prefix)] | |
| 178 if args.generate_type_info: | |
| 179 filtered_args.append("--generate_type_info") | |
| 180 | |
| 181 generator.GenerateFiles(filtered_args) | |
| 182 | |
| 183 | |
| 184 if __name__ == "__main__": | |
| 185 sys.exit(main()) | |
| OLD | NEW |