From 2fbba9727f57e9c451c1c93b7e3e68e89f4cef33 Mon Sep 17 00:00:00 2001 From: sebaszm Date: Thu, 14 Dec 2023 17:09:33 +0100 Subject: [PATCH 1/2] [JsonGen] Add --cpp-output option and header collection --- JsonGenerator/JsonGenerator.py | 42 +++++++++++++++++++++----- JsonGenerator/source/code_generator.py | 39 ++++++++++++++++++++---- JsonGenerator/source/config.py | 7 +++++ ProxyStubGenerator/StubGenerator.py | 2 +- cmake/FindJsonGenerator.cmake.in | 7 ++++- 5 files changed, 81 insertions(+), 16 deletions(-) diff --git a/JsonGenerator/JsonGenerator.py b/JsonGenerator/JsonGenerator.py index 91cdcd4..bc22e2b 100755 --- a/JsonGenerator/JsonGenerator.py +++ b/JsonGenerator/JsonGenerator.py @@ -59,6 +59,8 @@ else: files.append(p) + joint_headers = {} + for path in files: trackers.object_tracker.Reset() @@ -74,20 +76,41 @@ warnings = config.GENERATED_JSON config.GENERATED_JSON = "@generated" in schema - output_path = path - if args.output_dir: if (args.output_dir[0]) == os.sep: - output_path = os.path.join(args.output_dir, os.path.basename(output_path)) + output_path = os.path.normpath(args.output_dir) + else: + output_path = os.path.join(os.path.dirname(path), os.path.normpath(args.output_dir)) + + if not os.path.exists(output_path): + os.makedirs(output_path) + else: + output_path = os.path.dirname(path) + + if args.cpp_output_dir: + if (args.cpp_output_dir[0]) == os.sep: + cpp_output_path = os.path.normpath(args.cpp_output_dir) else: - dir = os.path.join(os.path.dirname(output_path), args.output_dir) - if not os.path.exists(dir): - os.makedirs(dir) + cpp_output_path = os.path.join(os.path.dirname(path), os.path.normpath(args.cpp_output_dir)) - output_path = os.path.join(dir, os.path.basename(output_path)) + if not os.path.exists(cpp_output_path): + os.makedirs(cpp_output_path) + else: + cpp_output_path = output_path if args.code or args.stubs: - code_generator.Create(log, schema, path, output_path, additional_includes, args.code, args.stubs, args.code) + headers = code_generator.Create(log, schema, path, [output_path, cpp_output_path], additional_includes, args.code, args.stubs, args.code) + + name = os.path.basename(path).replace(".h", "").replace(".json", "") + + if "@generated" in schema and name[0] == "I": + name = name[1:] + + if headers: + if name not in joint_headers: + joint_headers[name] = [] + + joint_headers[name].extend(headers) if args.docs: if "$schema" in schema: @@ -104,6 +127,9 @@ config.GENERATED_JSON = warnings + for n in joint_headers: + code_generator.CreateApiHeader(log, n, output_path, joint_headers[n]) + except json_loader.JsonParseError as err: log.Error(str(err)) except header_loader.CppParseError as err: diff --git a/JsonGenerator/source/code_generator.py b/JsonGenerator/source/code_generator.py index 10f4b46..2f5e296 100644 --- a/JsonGenerator/source/code_generator.py +++ b/JsonGenerator/source/code_generator.py @@ -26,6 +26,24 @@ from emitter import Emitter from json_loader import * +def CreateApiHeader(log, source_name, path, headers): + assert(headers) + + header_file = os.path.join(path, "json_" + source_name + ".h") + with Emitter(header_file, config.INDENT_SIZE) as emitter: + emitter.Line("// %s JSON-RPC API" % os.path.basename(source_name)) + emitter.Line("// Generated automatically. DO NOT EDIT.") + emitter.Line() + emitter.Line("#pragma once") + emitter.Line() + + sorted = [_h for _h in headers if config.DATA_NAMESPACE in _h] + sorted.extend([_h for _h in headers if config.DATA_NAMESPACE not in _h]) + + for h in sorted: + emitter.Line("#include \"%s\"" % os.path.basename(h)) + + log.Success("JSON-RPC API header generated in %s" % (os.path.basename(emitter.FileName()))) def Create(log, schema, source_file, path, additional_includes, generate_classes, generate_stubs, generate_rpc): def _ParseJsonRpcSchema(schema): @@ -43,17 +61,21 @@ def _ParseJsonRpcSchema(schema): else: return None - directory = os.path.dirname(path) + headers = [] + + directory = path[0] + cpp_directory = path[1] + filename = (schema["info"]["namespace"]) if "info" in schema and "namespace" in schema["info"] else "" filename += (schema["info"]["class"]) if "info" in schema and "class" in schema["info"] else "" if len(filename) == 0: - filename = os.path.basename(path.replace("Plugin", "").replace(".json", "").replace(".h", "")) + filename = os.path.basename(source_file.replace("Plugin", "").replace(".json", "").replace(".h", "")) rpcObj = _ParseJsonRpcSchema(schema) if rpcObj: header_file = os.path.join(directory, config.DATA_NAMESPACE + "_" + filename + ".h") - enum_file = os.path.join(directory, "JsonEnum_" + filename + ".cpp") + enum_file = os.path.join(cpp_directory, "JsonEnum_" + filename + ".cpp") data_emitted = 0 @@ -68,6 +90,7 @@ def _ParseJsonRpcSchema(schema): if data_emitted: log.Success("JSON data classes generated in %s" % os.path.basename(emitter.FileName())) + headers.append(header_file) else: log.Info("No JSON data classes generated for %s" % os.path.basename(filename)) @@ -108,10 +131,12 @@ def _ParseJsonRpcSchema(schema): with Emitter(output_filename, config.INDENT_SIZE) as emitter: rpc_emitter.EmitRpcVersionCode(rpcObj, emitter, filename, os.path.basename(source_file), data_emitted) log.Success("JSON-RPC version information generated in %s" % os.path.basename(emitter.FileName())) + headers.append(output_filename) + # Generate manual stub code... if generate_stubs: - with Emitter(os.path.join(directory, filename + "JsonRpc.cpp"), config.INDENT_SIZE) as emitter: + with Emitter(os.path.join(cpp_directory, filename + "JsonRpc.cpp"), config.INDENT_SIZE) as emitter: stub_emitter.EmitHelperCode(log, rpcObj, emitter, os.path.basename(header_file)) log.Success("JSON-RPC stubs generated in %s" % os.path.basename(emitter.FileName())) @@ -124,9 +149,11 @@ def _ParseJsonRpcSchema(schema): else: with Emitter(output_filename, config.INDENT_SIZE) as emitter: rpc_emitter.EmitRpcCode(rpcObj, emitter, filename, os.path.basename(source_file), data_emitted) - - log.Success("JSON-RPC implementation generated in %s" % os.path.basename(emitter.FileName())) + log.Success("JSON-RPC implementation generated in %s" % os.path.basename(emitter.FileName())) + headers.append(output_filename) else: log.Info("No code to generate.") + return headers + diff --git a/JsonGenerator/source/config.py b/JsonGenerator/source/config.py index 8867071..2c5021c 100644 --- a/JsonGenerator/source/config.py +++ b/JsonGenerator/source/config.py @@ -121,6 +121,13 @@ def Parse(cmdline): action="store", default=None, help="output directory, absolute path or directory relative to output file (default: output in the same directory as the source file)") + argparser.add_argument( + "--cpp-output", + dest="cpp_output_dir", + metavar="DIR", + action="store", + default=None, + help="output directory for cpp files, absolute path or directory relative to output file") argparser.add_argument( "--force", dest="force", diff --git a/ProxyStubGenerator/StubGenerator.py b/ProxyStubGenerator/StubGenerator.py index e96af2b..87034ae 100755 --- a/ProxyStubGenerator/StubGenerator.py +++ b/ProxyStubGenerator/StubGenerator.py @@ -1930,7 +1930,7 @@ def GenerateIdentification(name): if not options: options.append("0") - emit.Line("EXTERNAL proxystubs_options_t proxystubs_options()") + emit.Line("EXTERNAL_EXPORT proxystubs_options_t proxystubs_options()") emit.Line("{") emit.IndentInc() emit.Line("return (static_cast(%s));" % " | ".join(options)) diff --git a/cmake/FindJsonGenerator.cmake.in b/cmake/FindJsonGenerator.cmake.in index 258e58c..593f182 100644 --- a/cmake/FindJsonGenerator.cmake.in +++ b/cmake/FindJsonGenerator.cmake.in @@ -31,7 +31,7 @@ function(JsonGenerator) endif() set(optionsArgs CODE STUBS DOCS LEGACY_ALT NO_INCLUDES NO_STYLE_WARNINGS COPY_CTOR NO_REF_NAMES NO_INTERFACES_SECTION VERBOSE FORCE_GENERATE) - set(oneValueArgs OUTPUT IFDIR CPPIFDIR INDENT DEF_STRING DEF_INT_SIZE PATH FORMAT) + set(oneValueArgs OUTPUT CPP_OUTPUT IFDIR CPPIFDIR INDENT DEF_STRING DEF_INT_SIZE PATH FORMAT) set(multiValueArgs INPUT INCLUDE_PATH NAMESPACE) cmake_parse_arguments(Argument "${optionsArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) @@ -105,6 +105,11 @@ function(JsonGenerator) list(APPEND _execute_command "--output" "${Argument_OUTPUT}") endif() + if (Argument_CPP_OUTPUT) + file(MAKE_DIRECTORY "${Argument_CPP_OUTPUT}") + list(APPEND _execute_command "--cpp-output" "${Argument_CPP_OUTPUT}") + endif() + if (Argument_INDENT) list(APPEND _execute_command "--indent" "${Argument_INDENT}") endif() From 91005838ab10202b08871f85e2898bcaec9ae8bf Mon Sep 17 00:00:00 2001 From: sebaszm Date: Thu, 14 Dec 2023 17:31:34 +0100 Subject: [PATCH 2/2] Do not drop I --- JsonGenerator/JsonGenerator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/JsonGenerator/JsonGenerator.py b/JsonGenerator/JsonGenerator.py index bc22e2b..cd50441 100755 --- a/JsonGenerator/JsonGenerator.py +++ b/JsonGenerator/JsonGenerator.py @@ -103,8 +103,8 @@ name = os.path.basename(path).replace(".h", "").replace(".json", "") - if "@generated" in schema and name[0] == "I": - name = name[1:] + # if "@generated" in schema and name[0] == "I": + # name = name[1:] if headers: if name not in joint_headers: