| OLD | NEW |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import os.path | 5 import os.path |
| 6 import sys | 6 import sys |
| 7 import optparse | 7 import optparse |
| 8 try: | 8 try: |
| 9 import json | 9 import json |
| 10 except ImportError: | 10 except ImportError: |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 deps_dir = os.path.normpath(os.path.join( | 41 deps_dir = os.path.normpath(os.path.join( |
| 42 module_path, os.pardir, os.pardir, os.pardir, os.pardir, "third_party")) | 42 module_path, os.pardir, os.pardir, os.pardir, os.pardir, "third_party")) |
| 43 | 43 |
| 44 if os.path.isdir(deps_dir): | 44 if os.path.isdir(deps_dir): |
| 45 sys.path.insert(1, os.path.join(deps_dir, "jinja2")) | 45 sys.path.insert(1, os.path.join(deps_dir, "jinja2")) |
| 46 sys.path.insert(1, os.path.join(deps_dir, "markupsafe")) | 46 sys.path.insert(1, os.path.join(deps_dir, "markupsafe")) |
| 47 | 47 |
| 48 import jinja2 | 48 import jinja2 |
| 49 | 49 |
| 50 cmdline_parser = optparse.OptionParser() | 50 cmdline_parser = optparse.OptionParser() |
| 51 cmdline_parser.add_option("--protocol") | 51 cmdline_parser.add_option("--output_base") |
| 52 cmdline_parser.add_option("--include") | 52 cmdline_parser.add_option("--config") |
| 53 cmdline_parser.add_option("--include_package") | 53 |
| 54 cmdline_parser.add_option("--string_type") | |
| 55 cmdline_parser.add_option("--export_macro") | |
| 56 cmdline_parser.add_option("--output_dir") | |
| 57 cmdline_parser.add_option("--output_package") | |
| 58 cmdline_parser.add_option("--exported_dir") | |
| 59 cmdline_parser.add_option("--exported_package") | |
| 60 | 54 |
| 61 try: | 55 try: |
| 62 arg_options, arg_values = cmdline_parser.parse_args() | 56 arg_options, arg_values = cmdline_parser.parse_args() |
| 63 protocol_file = arg_options.protocol | 57 output_base = arg_options.output_base |
| 64 if not protocol_file: | 58 if not output_base: |
| 65 raise Exception("Protocol directory must be specified") | 59 raise Exception("Base output directory must be specified") |
| 66 include_file = arg_options.include | 60 config_file = arg_options.config |
| 67 include_package = arg_options.include_package | 61 if not config_file: |
| 68 if include_file and not include_package: | 62 raise Exception("Config file name must be specified") |
| 69 raise Exception("Include package must be specified when using include fi
le") | 63 config_dir = os.path.dirname(config_file) |
| 70 if include_package and not include_file: | |
| 71 raise Exception("Include file must be specified when using include packa
ge") | |
| 72 output_dirname = arg_options.output_dir | |
| 73 if not output_dirname: | |
| 74 raise Exception("Output directory must be specified") | |
| 75 output_package = arg_options.output_package | |
| 76 if not output_package: | |
| 77 raise Exception("Output package must be specified") | |
| 78 exported_dirname = arg_options.exported_dir | |
| 79 if not exported_dirname: | |
| 80 exported_dirname = os.path.join(output_dirname, "exported") | |
| 81 exported_package = arg_options.exported_package | |
| 82 if not exported_package: | |
| 83 exported_package = os.path.join(output_package, "exported") | |
| 84 string_type = arg_options.string_type | |
| 85 if not string_type: | |
| 86 raise Exception("String type must be specified") | |
| 87 export_macro = arg_options.export_macro | |
| 88 if not export_macro: | |
| 89 raise Exception("Export macro must be specified") | |
| 90 except Exception: | 64 except Exception: |
| 91 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html | 65 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html |
| 92 exc = sys.exc_info()[1] | 66 exc = sys.exc_info()[1] |
| 93 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) | 67 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) |
| 94 exit(1) | 68 exit(1) |
| 95 | 69 |
| 96 | 70 |
| 97 input_file = open(protocol_file, "r") | 71 try: |
| 98 json_string = input_file.read() | 72 config_json_string = open(config_file, "r").read() |
| 99 parsed_json = json.loads(json_string) | 73 config = json.loads(config_json_string) |
| 74 |
| 75 protocol_file = config["protocol"]["path"] |
| 76 if not protocol_file: |
| 77 raise Exception("Config is missing protocol.path") |
| 78 protocol_file = os.path.join(config_dir, protocol_file) |
| 79 output_dirname = config["protocol"]["output"] |
| 80 if not output_dirname: |
| 81 raise Exception("Config is missing protocol.output") |
| 82 output_dirname = os.path.join(output_base, output_dirname) |
| 83 output_package = config["protocol"]["package"] |
| 84 if not output_package: |
| 85 raise Exception("Config is missing protocol.package") |
| 86 |
| 87 importing = False |
| 88 if "import" in config: |
| 89 importing = True |
| 90 imported_file = config["import"]["path"] |
| 91 if not imported_file: |
| 92 raise Exception("Config is missing import.path") |
| 93 imported_file = os.path.join(config_dir, imported_file) |
| 94 imported_package = config["import"]["package"] |
| 95 if not imported_package: |
| 96 raise Exception("Config is missing import.package") |
| 97 |
| 98 exporting = False |
| 99 if "export" in config: |
| 100 exporting = True |
| 101 exported_dirname = config["export"]["output"] |
| 102 if not exported_dirname: |
| 103 raise Exception("Config is missing export.output") |
| 104 exported_dirname = os.path.join(output_base, exported_dirname) |
| 105 exported_package = config["export"]["package"] |
| 106 if not exported_package: |
| 107 raise Exception("Config is missing export.package") |
| 108 |
| 109 string_type = config["string"]["class_name"] |
| 110 if not string_type: |
| 111 raise Exception("Config is missing string.class_name") |
| 112 |
| 113 export_macro = config["export_macro"] |
| 114 if not export_macro: |
| 115 raise Exception("Config is missing export_macro") |
| 116 except Exception: |
| 117 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html |
| 118 exc = sys.exc_info()[1] |
| 119 sys.stderr.write("Failed to parse config file: %s\n\n" % exc) |
| 120 exit(1) |
| 100 | 121 |
| 101 | 122 |
| 102 # Make gyp / make generatos happy, otherwise make rebuilds world. | 123 # Make gyp / make generatos happy, otherwise make rebuilds world. |
| 103 def up_to_date(): | 124 def up_to_date(): |
| 104 template_ts = max( | 125 template_ts = max( |
| 105 os.path.getmtime(__file__), | 126 os.path.getmtime(__file__), |
| 106 os.path.getmtime(os.path.join(templates_dir, "TypeBuilder_h.template")), | 127 os.path.getmtime(os.path.join(templates_dir, "TypeBuilder_h.template")), |
| 107 os.path.getmtime(os.path.join(templates_dir, "TypeBuilder_cpp.template")
), | 128 os.path.getmtime(os.path.join(templates_dir, "TypeBuilder_cpp.template")
), |
| 108 os.path.getmtime(os.path.join(templates_dir, "Exported_h.template")), | 129 os.path.getmtime(os.path.join(templates_dir, "Exported_h.template")), |
| 109 os.path.getmtime(os.path.join(templates_dir, "Imported_h.template")), | 130 os.path.getmtime(os.path.join(templates_dir, "Imported_h.template")), |
| 131 os.path.getmtime(config_file), |
| 110 os.path.getmtime(protocol_file)) | 132 os.path.getmtime(protocol_file)) |
| 133 if importing: |
| 134 template_ts = max(template_ts, os.path.getmtime(imported_file)) |
| 111 | 135 |
| 112 for domain in parsed_json["domains"]: | 136 for domain in json_api["domains"]: |
| 113 name = domain["domain"] | 137 name = domain["domain"] |
| 114 paths = [] | 138 paths = [] |
| 115 if name in generate_domains: | 139 if name in generate_domains: |
| 116 paths = [os.path.join(output_dirname, name + ".h"), os.path.join(out
put_dirname, name + ".cpp")] | 140 paths = [os.path.join(output_dirname, name + ".h"), os.path.join(out
put_dirname, name + ".cpp")] |
| 117 if domain["has_exports"]: | 141 if domain["has_exports"]: |
| 118 paths.append(os.path.join(exported_dirname, name + ".h")) | 142 paths.append(os.path.join(exported_dirname, name + ".h")) |
| 119 if name in include_domains and domain["has_exports"]: | 143 if name in imported_domains and domain["has_exports"]: |
| 120 paths = [os.path.join(output_dirname, name + '.h')] | 144 paths = [os.path.join(output_dirname, name + '.h')] |
| 121 for path in paths: | 145 for path in paths: |
| 122 if not os.path.exists(path): | 146 if not os.path.exists(path): |
| 123 return False | 147 return False |
| 124 generated_ts = os.path.getmtime(path) | 148 generated_ts = os.path.getmtime(path) |
| 125 if generated_ts < template_ts: | 149 if generated_ts < template_ts: |
| 126 return False | 150 return False |
| 127 return True | 151 return True |
| 128 | 152 |
| 129 | 153 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 for item in json_value: | 210 for item in json_value: |
| 187 has_exports = calculate_exports_in_json(item) or has_exports | 211 has_exports = calculate_exports_in_json(item) or has_exports |
| 188 if isinstance(json_value, dict): | 212 if isinstance(json_value, dict): |
| 189 has_exports = ("exported" in json_value and json_value["exported"])
or has_exports | 213 has_exports = ("exported" in json_value and json_value["exported"])
or has_exports |
| 190 for key in json_value: | 214 for key in json_value: |
| 191 has_exports = calculate_exports_in_json(json_value[key]) or has_
exports | 215 has_exports = calculate_exports_in_json(json_value[key]) or has_
exports |
| 192 return has_exports | 216 return has_exports |
| 193 | 217 |
| 194 json_api["has_exports"] = False | 218 json_api["has_exports"] = False |
| 195 for domain_json in json_api["domains"]: | 219 for domain_json in json_api["domains"]: |
| 220 domain_name = domain_json["domain"] |
| 196 domain_json["has_exports"] = calculate_exports_in_json(domain_json) | 221 domain_json["has_exports"] = calculate_exports_in_json(domain_json) |
| 197 json_api["has_exports"] = json_api["has_exports"] or domain_json["has_ex
ports"] | 222 if domain_json["has_exports"] and domain_name in generate_domains: |
| 223 if not exporting: |
| 224 sys.stderr.write("Domain %s is exported, but config is missing e
xport entry\n\n" % domain_name) |
| 225 exit(1) |
| 226 json_api["has_exports"] = True |
| 198 | 227 |
| 199 | 228 |
| 200 def create_include_type_definition(domain_name, type): | 229 def create_imported_type_definition(domain_name, type): |
| 201 # pylint: disable=W0622 | 230 # pylint: disable=W0622 |
| 202 return { | 231 return { |
| 203 "return_type": "std::unique_ptr<protocol::%s::API::%s>" % (domain_name,
type["id"]), | 232 "return_type": "std::unique_ptr<protocol::%s::API::%s>" % (domain_name,
type["id"]), |
| 204 "pass_type": "std::unique_ptr<protocol::%s::API::%s>" % (domain_name, ty
pe["id"]), | 233 "pass_type": "std::unique_ptr<protocol::%s::API::%s>" % (domain_name, ty
pe["id"]), |
| 205 "to_raw_type": "%s.get()", | 234 "to_raw_type": "%s.get()", |
| 206 "to_pass_type": "std::move(%s)", | 235 "to_pass_type": "std::move(%s)", |
| 207 "to_rvalue": "std::move(%s)", | 236 "to_rvalue": "std::move(%s)", |
| 208 "type": "std::unique_ptr<protocol::%s::API::%s>" % (domain_name, type["i
d"]), | 237 "type": "std::unique_ptr<protocol::%s::API::%s>" % (domain_name, type["i
d"]), |
| 209 "raw_type": "protocol::%s::API::%s" % (domain_name, type["id"]), | 238 "raw_type": "protocol::%s::API::%s" % (domain_name, type["id"]), |
| 210 "raw_pass_type": "protocol::%s::API::%s*" % (domain_name, type["id"]), | 239 "raw_pass_type": "protocol::%s::API::%s*" % (domain_name, type["id"]), |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 } | 357 } |
| 329 | 358 |
| 330 | 359 |
| 331 def create_type_definitions(): | 360 def create_type_definitions(): |
| 332 for domain in json_api["domains"]: | 361 for domain in json_api["domains"]: |
| 333 type_definitions[domain["domain"] + ".string"] = create_string_type_defi
nition(domain["domain"]) | 362 type_definitions[domain["domain"] + ".string"] = create_string_type_defi
nition(domain["domain"]) |
| 334 if not ("types" in domain): | 363 if not ("types" in domain): |
| 335 continue | 364 continue |
| 336 for type in domain["types"]: | 365 for type in domain["types"]: |
| 337 type_name = domain["domain"] + "." + type["id"] | 366 type_name = domain["domain"] + "." + type["id"] |
| 338 if type["type"] == "object" and domain["domain"] in include_domains: | 367 if type["type"] == "object" and domain["domain"] in imported_domains
: |
| 339 type_definitions[type_name] = create_include_type_definition(dom
ain["domain"], type) | 368 type_definitions[type_name] = create_imported_type_definition(do
main["domain"], type) |
| 340 elif type["type"] == "object": | 369 elif type["type"] == "object": |
| 341 type_definitions[type_name] = create_user_type_definition(domain
["domain"], type) | 370 type_definitions[type_name] = create_user_type_definition(domain
["domain"], type) |
| 342 elif type["type"] == "array": | 371 elif type["type"] == "array": |
| 343 items_type = type["items"]["type"] | 372 items_type = type["items"]["type"] |
| 344 type_definitions[type_name] = wrap_array_definition(type_definit
ions[items_type]) | 373 type_definitions[type_name] = wrap_array_definition(type_definit
ions[items_type]) |
| 345 elif type["type"] == domain["domain"] + ".string": | 374 elif type["type"] == domain["domain"] + ".string": |
| 346 type_definitions[type_name] = create_string_type_definition(doma
in["domain"]) | 375 type_definitions[type_name] = create_string_type_definition(doma
in["domain"]) |
| 347 else: | 376 else: |
| 348 type_definitions[type_name] = create_primitive_type_definition(t
ype["type"]) | 377 type_definitions[type_name] = create_primitive_type_definition(t
ype["type"]) |
| 349 | 378 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 368 return result | 397 return result |
| 369 | 398 |
| 370 | 399 |
| 371 def has_disable(commands): | 400 def has_disable(commands): |
| 372 for command in commands: | 401 for command in commands: |
| 373 if command["name"] == "disable": | 402 if command["name"] == "disable": |
| 374 return True | 403 return True |
| 375 return False | 404 return False |
| 376 | 405 |
| 377 | 406 |
| 407 def generate_with_context(template_context, template, file_name): |
| 408 out_file = output_file(file_name) |
| 409 out_file.write(template.render(template_context)) |
| 410 out_file.close() |
| 411 |
| 412 |
| 378 def generate(domain_object, template, file_name): | 413 def generate(domain_object, template, file_name): |
| 379 template_context = { | 414 template_context = { |
| 380 "domain": domain_object, | 415 "domain": domain_object, |
| 381 "join_arrays": join_arrays, | 416 "join_arrays": join_arrays, |
| 382 "resolve_type": resolve_type, | 417 "resolve_type": resolve_type, |
| 383 "type_definition": type_definition, | 418 "type_definition": type_definition, |
| 384 "has_disable": has_disable, | 419 "has_disable": has_disable, |
| 385 "export_macro": export_macro, | 420 "export_macro": export_macro, |
| 386 "output_package": output_package, | 421 "output_package": output_package |
| 387 "exported_package": exported_package, | |
| 388 "include_package": include_package | |
| 389 } | 422 } |
| 390 out_file = output_file(file_name) | 423 if exporting: |
| 391 out_file.write(template.render(template_context)) | 424 template_context["exported_package"] = exported_package |
| 392 out_file.close() | 425 if importing: |
| 426 template_context["imported_package"] = imported_package |
| 427 generate_with_context(template_context, template, file_name) |
| 393 | 428 |
| 394 | 429 |
| 395 generate_domains = [] | 430 def read_protocol_file(file_name, all_domains): |
| 396 include_domains = [] | 431 input_file = open(file_name, "r") |
| 397 json_api = {} | |
| 398 json_api["domains"] = parsed_json["domains"] | |
| 399 | |
| 400 for domain in parsed_json["domains"]: | |
| 401 generate_domains.append(domain["domain"]) | |
| 402 | |
| 403 if include_file: | |
| 404 input_file = open(include_file, "r") | |
| 405 json_string = input_file.read() | 432 json_string = input_file.read() |
| 406 parsed_json = json.loads(json_string) | 433 parsed_json = json.loads(json_string) |
| 434 domains = [] |
| 407 for domain in parsed_json["domains"]: | 435 for domain in parsed_json["domains"]: |
| 408 include_domains.append(domain["domain"]) | 436 domains.append(domain["domain"]) |
| 409 json_api["domains"] += parsed_json["domains"] | 437 all_domains["domains"] += parsed_json["domains"] |
| 438 return domains |
| 410 | 439 |
| 440 |
| 441 json_api = {"domains": []} |
| 442 generate_domains = read_protocol_file(protocol_file, json_api) |
| 443 imported_domains = read_protocol_file(imported_file, json_api) if importing else
[] |
| 411 patch_full_qualified_refs() | 444 patch_full_qualified_refs() |
| 412 calculate_exports() | 445 calculate_exports() |
| 413 create_type_definitions() | 446 create_type_definitions() |
| 414 | 447 |
| 415 if up_to_date(): | 448 if up_to_date(): |
| 416 sys.exit() | 449 sys.exit() |
| 417 if not os.path.exists(output_dirname): | 450 if not os.path.exists(output_dirname): |
| 418 os.mkdir(output_dirname) | 451 os.mkdir(output_dirname) |
| 419 if json_api["has_exports"] and not os.path.exists(exported_dirname): | 452 if json_api["has_exports"] and not os.path.exists(exported_dirname): |
| 420 os.mkdir(exported_dirname) | 453 os.mkdir(exported_dirname) |
| 421 | 454 |
| 422 jinja_env = initialize_jinja_env(output_dirname) | 455 jinja_env = initialize_jinja_env(output_dirname) |
| 423 h_template = jinja_env.get_template("/TypeBuilder_h.template") | 456 h_template = jinja_env.get_template("/TypeBuilder_h.template") |
| 424 cpp_template = jinja_env.get_template("/TypeBuilder_cpp.template") | 457 cpp_template = jinja_env.get_template("/TypeBuilder_cpp.template") |
| 425 exported_template = jinja_env.get_template("/Exported_h.template") | 458 exported_template = jinja_env.get_template("/Exported_h.template") |
| 426 imported_template = jinja_env.get_template("/Imported_h.template") | 459 imported_template = jinja_env.get_template("/Imported_h.template") |
| 427 | 460 |
| 428 for domain in json_api["domains"]: | 461 for domain in json_api["domains"]: |
| 429 class_name = domain["domain"] | 462 class_name = domain["domain"] |
| 430 if domain["domain"] in generate_domains: | 463 if domain["domain"] in generate_domains: |
| 431 generate(domain, h_template, output_dirname + "/" + class_name + ".h") | 464 generate(domain, h_template, os.path.join(output_dirname, class_name + "
.h")) |
| 432 generate(domain, cpp_template, output_dirname + "/" + class_name + ".cpp
") | 465 generate(domain, cpp_template, os.path.join(output_dirname, class_name +
".cpp")) |
| 433 if domain["has_exports"]: | 466 if domain["has_exports"]: |
| 434 generate(domain, exported_template, exported_dirname + "/" + class_n
ame + ".h") | 467 generate(domain, exported_template, os.path.join(exported_dirname, c
lass_name + ".h")) |
| 435 if domain["domain"] in include_domains and domain["has_exports"]: | 468 if domain["domain"] in imported_domains and domain["has_exports"]: |
| 436 generate(domain, imported_template, output_dirname + "/" + class_name +
".h") | 469 generate(domain, imported_template, os.path.join(output_dirname, class_n
ame + ".h")) |
| OLD | NEW |