From: Markus Blatt <markus@dr-blatt.de>
Date: Fri, 20 Jan 2023 19:49:37 +0100
Subject: Refactored ParserInit.cpp to reduce ram needed for compilation

---
 CMakeLists.txt                                     |  1 +
 CopyHeaders.cmake                                  |  3 +
 GenerateKeywords.cmake                             |  8 +-
 opm/input/eclipse/Generator/KeywordGenerator.hpp   |  2 +-
 .../input/eclipse/Generator/KeywordGenerator.cpp   | 93 ++++++++++++++++++----
 .../eclipse/Parser/createDefaultKeywordList.cpp    |  2 +-
 6 files changed, 90 insertions(+), 19 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d057ece..e5ae79e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -136,6 +136,7 @@ macro (sources_hook)
     list(INSERT opm-common_SOURCES 0 ${PROJECT_BINARY_DIR}/ParserInit.cpp)
     foreach (name A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
         list(INSERT opm-common_SOURCES 0 ${PROJECT_BINARY_DIR}/ParserKeywords/${name}.cpp)
+        list(INSERT opm-common_SOURCES 0 ${PROJECT_BINARY_DIR}/ParserKeywords/ParserInit${name}.cpp)
         list(INSERT opm-common_HEADERS 0 ${PROJECT_BINARY_DIR}/include/opm/input/eclipse/Parser/ParserKeywords/${name}.hpp)
     endforeach()
     if (OPM_ENABLE_EMBEDDED_PYTHON)
diff --git a/CopyHeaders.cmake b/CopyHeaders.cmake
index 044fbb3..4c243e3 100644
--- a/CopyHeaders.cmake
+++ b/CopyHeaders.cmake
@@ -31,4 +31,7 @@ foreach (name A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
     execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
                             ${BASE_DIR}/tmp_gen/ParserKeywords/${name}.cpp
                             ${BASE_DIR}/ParserKeywords/${name}.cpp)
+    execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
+                            ${BASE_DIR}/tmp_gen/ParserKeywords/ParserInit${name}.cpp
+                            ${BASE_DIR}/ParserKeywords/ParserInit${name}.cpp)
 endforeach()
diff --git a/GenerateKeywords.cmake b/GenerateKeywords.cmake
index 16a94c4..9320f92 100644
--- a/GenerateKeywords.cmake
+++ b/GenerateKeywords.cmake
@@ -54,9 +54,13 @@ set( genkw_argv keyword_list.argv
 
 foreach (name A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
   list(APPEND _tmp_output ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/${name}.cpp
-                          ${PROJECT_BINARY_DIR}/tmp_gen/include/opm/input/eclipse/Parser/ParserKeywords/${name}.hpp)
+                          ${PROJECT_BINARY_DIR}/tmp_gen/include/opm/input/eclipse/Parser/ParserKeywords/${name}.hpp
+                          ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/ParserInit${name}.cpp
+                          ${PROJECT_BINARY_DIR}/tmp_gen/include/opm/input/eclipse/Parser/ParserKeywords/ParserInit${name}.hpp)
   list(APPEND _target_output ${PROJECT_BINARY_DIR}/ParserKeywords/${name}.cpp
-                             ${PROJECT_BINARY_DIR}/include/opm/input/eclipse/Parser/ParserKeywords/${name}.hpp)
+                             ${PROJECT_BINARY_DIR}/include/opm/input/eclipse/Parser/ParserKeywords/${name}.hpp
+                             ${PROJECT_BINARY_DIR}/ParserKeywords/ParserInit${name}.cpp
+                             ${PROJECT_BINARY_DIR}/include/opm/input/eclipse/Parser/ParserKeywords/ParserInit${name}.hpp)
 endforeach()
 
 foreach(name TestKeywords.cpp ParserInit.cpp)
diff --git a/opm/input/eclipse/Generator/KeywordGenerator.hpp b/opm/input/eclipse/Generator/KeywordGenerator.hpp
index e571193..7c24f18 100644
--- a/opm/input/eclipse/Generator/KeywordGenerator.hpp
+++ b/opm/input/eclipse/Generator/KeywordGenerator.hpp
@@ -39,7 +39,7 @@ namespace Opm {
         static void updateFile(const std::stringstream& newContent, const std::string& filename);
 
         void updateBuiltInHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const;
-        void updateInitSource(const KeywordLoader& loader, const std::string& sourceFile ) const;
+        void updateInitSource(const KeywordLoader& loader, const std::string& sourceFile, const std::string& sourcePath) const;
         void updateKeywordSource(const KeywordLoader& loader, const std::string& sourceFile ) const;
         void updatePybindSource(const KeywordLoader& loader , const std::string& sourceFile ) const;
         void updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const;
diff --git a/src/opm/input/eclipse/Generator/KeywordGenerator.cpp b/src/opm/input/eclipse/Generator/KeywordGenerator.cpp
index f2179cf..418f311 100644
--- a/src/opm/input/eclipse/Generator/KeywordGenerator.cpp
+++ b/src/opm/input/eclipse/Generator/KeywordGenerator.cpp
@@ -65,18 +65,34 @@ namespace Opm {
             std::filesystem::create_directories( file.parent_path());
     }
 
-    void KeywordGenerator::updateFile(const std::stringstream& newContent , const std::string& filename) {
-        ensurePath(filename);
+    void
+    updateFile(const std::string& newContent, const std::string& filename)
+    {
+        KeywordGenerator::ensurePath(filename);
         std::ofstream outputStream(filename);
-        outputStream << newContent.str();
+        outputStream << newContent;
+    }
+    void
+    KeywordGenerator::updateFile(const std::stringstream& newContent, const std::string& filename)
+    {
+        Opm::updateFile(newContent.str(), filename);
     }
 
-    static void write_file( const std::stringstream& stream, const std::string& file, bool verbose, std::string desc = "source" ) {
-        KeywordGenerator::updateFile( stream, file );
-        if( verbose )
+    void
+    write_file(const std::string& content, const std::string& file, bool verbose, std::string desc = "source")
+    {
+        Opm::updateFile(content, file);
+        if (verbose)
             fmt::print("Updated {} file written to {}\n", desc, file);
     }
 
+
+    static void
+    write_file(const std::stringstream& stream, const std::string& file, bool verbose, std::string desc = "source")
+    {
+        write_file(stream.str(), file, verbose, desc);
+    }
+
     void KeywordGenerator::updateBuiltInHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const {
         std::stringstream newSource;
         newSource << R"(#ifndef PARSER_KEYWORDS_BUILTIN_HPP
@@ -141,7 +157,11 @@ private:
         write_file( newSource, final_path, m_verbose, "header" );
     }
 
-    void KeywordGenerator::updateInitSource(const KeywordLoader& loader , const std::string& sourceFile ) const {
+    void KeywordGenerator::updateInitSource(const KeywordLoader& loader , const std::string& sourceFile,
+                                            const std::string& sourcePath ) const {
+        std::filesystem::path parserInitSource(sourceFile);
+        std::string stem = parserInitSource.stem();
+        std::filesystem::path parentPath = parserInitSource.parent_path();
         std::stringstream newSource;
         newSource << R"(
 #include <opm/input/eclipse/Parser/Parser.hpp>
@@ -150,7 +170,52 @@ private:
 
         for(const auto& kw_pair : loader) {
             const auto& first_char = kw_pair.first;
-            newSource << fmt::format("#include <opm/input/eclipse/Parser/ParserKeywords/{}.hpp>\n", first_char);
+            const std::string header = fmt::format(R"(
+#ifndef OPM_PARSER_INIT_{0}_HH
+#define OPM_PARSER_INIT_{0}_HH
+
+namespace Opm {{
+class Parser;
+namespace ParserKeywords {{
+void addDefaultKeywords{0}(Parser& p);
+}}
+}}
+#endif
+)",
+                                                   first_char);
+            auto charHeaderFile = parserInitSource;
+            charHeaderFile.replace_filename(
+                fmt::format("include/opm/input/eclipse/Parser/ParserKeywords/ParserInit{}.hpp", first_char));
+            write_file(header, charHeaderFile, m_verbose, fmt::format("init header for {}", first_char));
+            std::stringstream sourceStr;
+            sourceStr << fmt::format(R"(
+#include <opm/input/eclipse/Parser/Parser.hpp>
+#include <opm/input/eclipse/Parser/ParserKeywords/Builtin.hpp>
+#include<opm/input/eclipse/Parser/ParserKeywords/ParserInit{0}.hpp>
+#include <opm/input/eclipse/Parser/ParserKeywords/{0}.hpp>
+
+namespace Opm {{
+namespace ParserKeywords {{
+void addDefaultKeywords{0}(Parser& p){{
+    Builtin keywords;
+)",
+                                     first_char);
+            for (const auto& kw_pair : loader) {
+                const auto& keywords = kw_pair.second;
+                for (const auto& kw : keywords)
+                    sourceStr << fmt::format("    p.addParserKeyword( keywords.{} );", kw.className()) << std::endl;
+            }
+            sourceStr << R"(
+
+}
+}
+}
+)";
+            auto charSourceFile = std::filesystem::path(sourcePath) / fmt::format("ParserInit{}.cpp", first_char);
+            write_file(sourceStr, charSourceFile, m_verbose, fmt::format("init source for {}", first_char));
+
+            newSource << fmt::format("#include <opm/input/eclipse/Parser/ParserKeywords/ParserInit{}.hpp>\n",
+                                     first_char);
         }
 
         newSource << R"(
@@ -158,24 +223,22 @@ namespace Opm {
 namespace ParserKeywords {
 void addDefaultKeywords(Parser& p);
 void addDefaultKeywords(Parser& p) {
-     Builtin keywords;
 )";
 
-        for(const auto& kw_pair : loader) {
-            const auto& keywords = kw_pair.second;
-            for (const auto& kw: keywords)
-                newSource << "     p.addParserKeyword( keywords." << kw.className() << " );" << std::endl;
+        for(const auto& [first_char, keywords] : loader) {
+                newSource << fmt::format("    addDefaultKeywords{}(p);", first_char) << std::endl;
         }
 
         newSource << R"(
 }
 }
 void Parser::addDefaultKeywords() {
-     ParserKeywords::addDefaultKeywords(*this);
+    ParserKeywords::addDefaultKeywords(*this);
 }
 }
 )";
-        write_file( newSource, sourceFile, m_verbose, "init" );
+
+        write_file(newSource, sourceFile, m_verbose, "init");
     }
 
 
diff --git a/src/opm/input/eclipse/Parser/createDefaultKeywordList.cpp b/src/opm/input/eclipse/Parser/createDefaultKeywordList.cpp
index 9c65405..88c8cf1 100644
--- a/src/opm/input/eclipse/Parser/createDefaultKeywordList.cpp
+++ b/src/opm/input/eclipse/Parser/createDefaultKeywordList.cpp
@@ -58,7 +58,7 @@ int main(int argc, char ** argv) {
     Opm::KeywordGenerator generator( true );
 
     generator.updateKeywordSource(loader , source_file_path );
-    generator.updateInitSource(loader , init_file_name );
+    generator.updateInitSource(loader , init_file_name , source_file_path );
     generator.updateHeader(loader, header_file_base_path, header_file_path );
     generator.updateBuiltInHeader(loader, header_file_base_path, header_file_path );
     generator.updateTest( loader , test_file_name );
