Browse Source

Reduce compilation time

-Reduce compilation time by adding conditional generation based on .proto modificaiton time
Alexey Edelev 6 years ago
parent
commit
541d837000
2 changed files with 61 additions and 24 deletions
  1. 60 23
      src/generator/generator.cpp
  2. 1 1
      tests/CMakeLists.txt

+ 60 - 23
src/generator/generator.cpp

@@ -34,6 +34,9 @@
 #include "clientsourcegenerator.h"
 #include "utils.h"
 
+#include <sys/stat.h>
+#include <time.h>
+
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/printer.h>
@@ -44,56 +47,90 @@ using namespace ::qtprotobuf::generator;
 using namespace ::google::protobuf;
 using namespace ::google::protobuf::compiler;
 
+namespace {
+#ifdef _WIN32
+    const char separator = '\\';
+#else
+    const char separator = '/';
+#endif
+
+bool checkFileModification(struct stat *protoFileStat, std::string filename) {
+    struct stat genFileStat;
+    return stat(filename.c_str(), &genFileStat) != 0 || difftime(protoFileStat->st_mtim.tv_sec, genFileStat.st_mtim.tv_sec) >= 0;
+}
+}
+
 bool QtGenerator::Generate(const FileDescriptor *file,
-                           const std::string &/*parameter*/,
+                           const std::string &parameter,
                            GeneratorContext *generatorContext,
                            std::string *error) const
 {
+    struct stat protoFileStat;
+    std::vector<std::pair<std::string, std::string> > parammap;
+    ParseGeneratorParameter(parameter, &parammap);
+    std::string outDir;
+
+    for(auto param : parammap) {
+        if (param.first == "out") {
+            outDir = param.second + separator;
+        }
+    }
+
     if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
         *error = "Invalid proto used. This plugin only supports 'proto3' syntax";
         return false;
     }
 
-    std::set<std::string> extractedModels;
-
     for (int i = 0; i < file->message_type_count(); i++) {
         const Descriptor *message = file->message_type(i);
         std::string baseFilename(message->name());
         utils::tolower(baseFilename);
+        stat(message->file()->name().c_str(), &protoFileStat);
 
         std::string filename = baseFilename + ".h";
-        ProtobufClassGenerator classGen(message,
-                                  std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(filename))));
-        classGen.run();
-
-        std::set<std::string> models = classGen.extractModels();
-        extractedModels.insert(std::begin(models), std::end(models));
-
-        std::string sourceFileName = baseFilename + ".cpp";
-        ProtobufSourceGenerator classSourceGen(message,
-                                  std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(sourceFileName))));
-        classSourceGen.run();
+        if (checkFileModification(&protoFileStat, outDir + filename)) {
+            std::cerr << "Regen" << filename << std::endl;
+            ProtobufClassGenerator classGen(message,
+                                      std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(filename))));
+            classGen.run();
+        }
+
+        filename = baseFilename + ".cpp";
+        if (checkFileModification(&protoFileStat, outDir + filename)) {
+            std::cerr << "Regen" << filename << std::endl;
+            ProtobufSourceGenerator classSourceGen(message,
+                                      std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(filename))));
+            classSourceGen.run();
+        }
     }
 
+    stat(file->name().c_str(), &protoFileStat);
+
     for (int i = 0; i < file->service_count(); i++) {
         const ServiceDescriptor* service = file->service(i);
         std::string baseFilename(service->name());
         utils::tolower(baseFilename);
 
         std::string fullFilename = baseFilename + "server.h";
-        ServerGenerator serverGen(service,
-                                  std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(fullFilename))));
-        serverGen.run();
+        if (checkFileModification(&protoFileStat, outDir + fullFilename)) {
+            ServerGenerator serverGen(service,
+                                      std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(fullFilename))));
+            serverGen.run();
+        }
 
         fullFilename = baseFilename + "client.h";
-        ClientGenerator clientGen(service,
-                                  std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(fullFilename))));
-        clientGen.run();
+        if (checkFileModification(&protoFileStat, outDir + fullFilename)) {
+            ClientGenerator clientGen(service,
+                                      std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(fullFilename))));
+            clientGen.run();
+        }
 
         fullFilename = baseFilename + "client.cpp";
-        ClientSourceGenerator clientSrcGen(service,
-                                  std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(fullFilename))));
-        clientSrcGen.run();
+        if (checkFileModification(&protoFileStat, outDir + fullFilename)) {
+            ClientSourceGenerator clientSrcGen(service,
+                                               std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(fullFilename))));
+            clientSrcGen.run();
+        }
     }
     return true;
 }

+ 1 - 1
tests/CMakeLists.txt

@@ -9,7 +9,7 @@ endif()
 
 add_custom_target(${testgeneration})
 add_custom_command(TARGET ${testgeneration}
-        COMMAND ${Protobuf_PROTOC_EXECUTABLE} --plugin=protoc-gen-${PROJECT_NAME}=$<TARGET_FILE:${PROJECT_NAME}> --qtprotobuf_out=${TESTS_OUT_DIR} -I=${CMAKE_CURRENT_SOURCE_DIR}/proto/ ${PROTO_FILES}
+        COMMAND ${Protobuf_PROTOC_EXECUTABLE} --${PROJECT_NAME}_opt=out=${TESTS_OUT_DIR} --plugin=protoc-gen-${PROJECT_NAME}=$<TARGET_FILE:${PROJECT_NAME}> --qtprotobuf_out=${TESTS_OUT_DIR} -I=${CMAKE_CURRENT_SOURCE_DIR}/proto/ ${PROTO_FILES}
         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/proto/
         DEPENDS ${PROTO_FILES}
         COMMENT "Generating test headers"