From c3a038c2b6eaa450327833f93725b2654cbdf393 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Sun, 29 Dec 2019 07:51:57 +0100 Subject: [PATCH 1/4] Refactor code generation to facilitate multiple source files --- CMakeLists.txt | 2 +- CopyHeaders.cmake | 8 +- ExtraTests.cmake | 7 - GenerateKeywords.cmake | 3 +- .../eclipse/Generator/KeywordGenerator.hpp | 5 +- .../eclipse/Generator/KeywordLoader.hpp | 19 +-- .../eclipse/Generator/KeywordGenerator.cpp | 145 +++++++++--------- .../eclipse/Generator/KeywordLoader.cpp | 102 +++++------- .../Parser/createDefaultKeywordList.cpp | 37 +++-- tests/parser/KeywordLoaderTests.cpp | 66 -------- tests/parser/TableManagerTests.cpp | 2 - 11 files changed, 143 insertions(+), 253 deletions(-) delete mode 100644 tests/parser/KeywordLoaderTests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d9702813..7309b93d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,7 +115,7 @@ macro (sources_hook) include(GenerateKeywords.cmake) # Append generated sources - list(INSERT opm-common_SOURCES 0 ${PROJECT_BINARY_DIR}/ParserKeywords.cpp) + list(INSERT opm-common_SOURCES 0 ${PROJECT_BINARY_DIR}/ParserKeywords.cpp ${PROJECT_BINARY_DIR}/ParserInit.cpp) endif() set_source_files_properties(src/opm/parser/eclipse/Python/Python.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow) diff --git a/CopyHeaders.cmake b/CopyHeaders.cmake index 150b3922a..91b19a704 100644 --- a/CopyHeaders.cmake +++ b/CopyHeaders.cmake @@ -3,12 +3,12 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${BASE_DIR}/ParserKeywords.cpp) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${BASE_DIR}/tmp_gen/inlinekw.cpp - ${BASE_DIR}/inlinekw.cpp) + ${BASE_DIR}/tmp_gen/ParserInit.cpp + ${BASE_DIR}/ParserInit.cpp) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${BASE_DIR}/tmp_gen/include/opm/parser/eclipse/Parser/ParserKeywords.hpp - ${BASE_DIR}/include/opm/parser/eclipse/Parser/ParserKeywords.hpp) + ${BASE_DIR}/tmp_gen/inlinekw.cpp + ${BASE_DIR}/inlinekw.cpp) file(GLOB HDRS ${BASE_DIR}/tmp_gen/include/opm/parser/eclipse/Parser/ParserKeywords/*.hpp) diff --git a/ExtraTests.cmake b/ExtraTests.cmake index 921670c88..118a8ff5d 100644 --- a/ExtraTests.cmake +++ b/ExtraTests.cmake @@ -13,13 +13,6 @@ list(APPEND EXTRA_TESTS inlinekw) include(cmake/Modules/CheckCaseSensitiveFileSystem.cmake) set(_testdir ${PROJECT_SOURCE_DIR}/tests/parser/data) -opm_add_test(LoaderTest - SOURCES tests/parser/KeywordLoaderTests.cpp - src/opm/parser/eclipse/Generator/KeywordLoader.cpp - LIBRARIES ${TEST_LIBS} - TEST_ARGS ${_testdir}/parser/keyword-generator/) -list(APPEND EXTRA_TESTS LoaderTest) - opm_add_test(ParserTests SOURCES tests/parser/ParserTests.cpp LIBRARIES ${TEST_LIBS} diff --git a/GenerateKeywords.cmake b/GenerateKeywords.cmake index e52f615fe..9795043e3 100644 --- a/GenerateKeywords.cmake +++ b/GenerateKeywords.cmake @@ -44,6 +44,7 @@ add_custom_command( OUTPUT ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords.cpp ${PROJECT_BINARY_DIR}/tmp_gen/inlinekw.cpp COMMAND genkw keyword_list.argv ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserInit.cpp ${PROJECT_BINARY_DIR}/tmp_gen/include/ opm/parser/eclipse/Parser/ParserKeywords ${PROJECT_BINARY_DIR}/tmp_gen/inlinekw.cpp @@ -51,7 +52,7 @@ add_custom_command( ) # To avoid some rebuilds -add_custom_command(OUTPUT ParserKeywords.cpp inlinekw.cpp +add_custom_command(OUTPUT ParserKeywords.cpp inlinekw.cpp ParserInit.cpp DEPENDS ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords.cpp COMMAND ${CMAKE_COMMAND} -DBASE_DIR=${PROJECT_BINARY_DIR} -P ${PROJECT_SOURCE_DIR}/CopyHeaders.cmake) diff --git a/opm/parser/eclipse/Generator/KeywordGenerator.hpp b/opm/parser/eclipse/Generator/KeywordGenerator.hpp index cce5a88b2..38aefb2e3 100644 --- a/opm/parser/eclipse/Generator/KeywordGenerator.hpp +++ b/opm/parser/eclipse/Generator/KeywordGenerator.hpp @@ -38,8 +38,9 @@ namespace Opm { static std::string headerHeader( const std::string& ); static bool updateFile(const std::stringstream& newContent, const std::string& filename); - bool updateSource(const KeywordLoader& loader, const std::string& sourceFile ) const; - bool updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerFile) const; + bool updateInitSource(const KeywordLoader& loader, const std::string& sourceFile ) const; + bool updateKeywordSource(const KeywordLoader& loader, const std::string& sourceFile ) const; + bool updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const; bool updateTest(const KeywordLoader& loader , const std::string& testFile) const; private: diff --git a/opm/parser/eclipse/Generator/KeywordLoader.hpp b/opm/parser/eclipse/Generator/KeywordLoader.hpp index 0ae48f29c..5028e4e06 100644 --- a/opm/parser/eclipse/Generator/KeywordLoader.hpp +++ b/opm/parser/eclipse/Generator/KeywordLoader.hpp @@ -22,34 +22,25 @@ #define KEYWORD_LOADER_HPP #include -#include #include #include #include +#include namespace Opm { - class ParserKeyword; class KeywordLoader { public: - KeywordLoader(bool verbose); - size_t size() const; - bool hasKeyword(const std::string& keyword) const; - std::shared_ptr getKeyword(const std::string& keyword) const; + KeywordLoader(const std::vector& keyword_files, bool verbose); std::string getJsonFile(const std::string& keyword) const; - void loadKeyword(const std::string& filename); - void loadKeyword(boost::filesystem::path& path); - std::map >::const_iterator keyword_begin( ) const; - std::map >::const_iterator keyword_end( ) const; + std::map >::const_iterator begin( ) const; + std::map >::const_iterator end( ) const; private: - void addKeyword(std::shared_ptr keyword , const std::string& jsonFile); - - bool m_verbose; - std::map > m_keywords; + std::map> keywords; std::map m_jsonFile; }; } diff --git a/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp b/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp index 79d389712..9a8d1408e 100644 --- a/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp +++ b/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp @@ -40,23 +40,17 @@ const std::string testHeader = "#include \n" "#include \n" "#include \n" - "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" - "using namespace Opm;\n" - "auto unitSystem = UnitSystem::newMETRIC();\n"; + "auto unitSystem = Opm::UnitSystem::newMETRIC();\n"; const std::string sourceHeader = "#include \n" - "#include \n" "#include \n" "#include \n" - "#include \n" - "#include \n\n\n" - "namespace Opm {\n" - "namespace ParserKeywords {\n\n"; + "#include \n\n\n"; } namespace Opm { @@ -102,71 +96,71 @@ namespace Opm { return update; } + bool KeywordGenerator::updateInitSource(const KeywordLoader& loader , const std::string& sourceFile ) const { + std::stringstream newSource; + newSource << "#include " << std::endl; + for(const auto& kw_pair : loader) { + const auto& first_char = kw_pair.first; + newSource << "#include " << std::endl; + } + newSource << "namespace Opm {" << std::endl; + newSource << "namespace ParserKeywords {" << std::endl; + newSource << "void addDefaultKeywords(Parser& p);" << std::endl + << "void addDefaultKeywords(Parser& p) {" << std::endl; - bool KeywordGenerator::updateSource(const KeywordLoader& loader , const std::string& sourceFile ) const { + for(const auto& kw_pair : loader) { + const auto& keywords = kw_pair.second; + for (const auto& kw: keywords) + newSource << " p.addKeyword< ParserKeywords::" + << kw.className() + << " >();" << std::endl; + } + newSource << "}" << std::endl; + newSource << "}" << std::endl; + + newSource << "void Parser::addDefaultKeywords() {\n ParserKeywords::addDefaultKeywords(*this);\n}" << std::endl; + newSource << "}" << std::endl; + return write_file( newSource, sourceFile, m_verbose, "init" ); + } + + bool KeywordGenerator::updateKeywordSource(const KeywordLoader& loader , const std::string& sourceFile ) const { std::stringstream newSource; newSource << sourceHeader << std::endl; - newSource << "void addDefaultKeywords(Parser& p);" << std::endl - << "void addDefaultKeywords(Parser& p) {" << std::endl; - for( auto iter = loader.keyword_begin(); iter != loader.keyword_end(); ++iter ) { - newSource << "p.addKeyword< ParserKeywords::" - << iter->second->className() - << " >();" << std::endl; + for(const auto& kw_pair : loader) { + const auto& first_char = kw_pair.first; + const auto& keywords = kw_pair.second; + newSource << std::endl << std::endl << "#include " << std::endl; + newSource << "namespace Opm {" << std::endl; + newSource << "namespace ParserKeywords {" << std::endl; + for (const auto& kw: keywords) + newSource << kw.createCode() << std::endl; + newSource << "}\n}" << std::endl; } - newSource << "}" << std::endl; - - for (auto iter = loader.keyword_begin(); iter != loader.keyword_end(); ++iter) { - std::shared_ptr keyword = (*iter).second; - newSource << keyword->createCode() << std::endl; - } - - newSource << "}" << std::endl; - - newSource << "void Parser::addDefaultKeywords() {" << std::endl - << " Opm::ParserKeywords::addDefaultKeywords(*this);" << std::endl - << "}}" << std::endl; - return write_file( newSource, sourceFile, m_verbose, "source" ); } - bool KeywordGenerator::updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerFile) const { + bool KeywordGenerator::updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const { bool update = false; - std::map< char, std::vector< const ParserKeyword* > > keywords; - for( auto iter = loader.keyword_begin(); iter != loader.keyword_end(); ++iter ) - keywords[ std::toupper( iter->second->className().at(0) ) ].push_back( iter->second.get() ); - - for( const auto& iter : keywords ) { + for( const auto& kw_pair : loader) { std::stringstream stream; + const auto& first_char = kw_pair.first; + const auto& keywords = kw_pair.second; - stream << headerHeader( std::string( 1, std::toupper( iter.first ) ) ); - for( auto& kw : iter.second ) - stream << kw->createDeclaration(" ") << std::endl; + stream << headerHeader( std::string( 1, std::toupper( first_char ) ) ); + for( auto& kw : keywords ) + stream << kw.createDeclaration(" ") << std::endl; stream << "}" << std::endl << "}" << std::endl; stream << "#endif" << std::endl; - const auto final_path = headerBuildPath + headerFile + "/" + std::string( 1, iter.first ) + ".hpp"; + const auto final_path = headerBuildPath + headerPath+ "/" + std::string( 1, first_char ) + ".hpp"; if( write_file( stream, final_path, m_verbose, "header" ) ) update = true; } - - std::stringstream stream; - stream << headerHeader(""); - stream << "}}" << std::endl; - - for( const auto& iter : keywords ) - stream << "#include <" - << headerFile + "/" - << std::string( 1, std::toupper( iter.first ) ) + ".hpp>" - << std::endl; - - stream << "#endif" << std::endl; - - const auto final_path = headerBuildPath + headerFile + ".hpp"; - return write_file( stream, final_path, m_verbose, "header" ) || update; + return update; } @@ -185,27 +179,32 @@ namespace Opm { std::stringstream stream; stream << testHeader; - for (auto iter = loader.keyword_begin(); iter != loader.keyword_end(); ++iter) { - const std::string& keywordName = (*iter).first; - std::shared_ptr keyword = (*iter).second; - stream << startTest(keywordName); - stream << " std::string jsonFile = \"" << loader.getJsonFile( keywordName) << "\";" << std::endl; - stream << " boost::filesystem::path jsonPath( jsonFile );" << std::endl; - stream << " Json::JsonObject jsonConfig( jsonPath );" << std::endl; - stream << " ParserKeyword jsonKeyword(jsonConfig);" << std::endl; - stream << " ParserKeywords::" << keywordName << " inlineKeyword;" << std::endl; - stream << " BOOST_CHECK_EQUAL( jsonKeyword, inlineKeyword );" << std::endl; - stream << " if (jsonKeyword.hasDimension()) {" <" << std::endl; + stream << "namespace Opm {" << std::endl; + const auto& keywords = kw_pair.second; + for (const auto& kw: keywords) { + const std::string& keywordName = kw.getName(); + stream << startTest(keywordName); + stream << " std::string jsonFile = \"" << loader.getJsonFile( keywordName) << "\";" << std::endl; + stream << " boost::filesystem::path jsonPath( jsonFile );" << std::endl; + stream << " Json::JsonObject jsonConfig( jsonPath );" << std::endl; + stream << " ParserKeyword jsonKeyword(jsonConfig);" << std::endl; + stream << " ParserKeywords::" << keywordName << " inlineKeyword;" << std::endl; + stream << " BOOST_CHECK_EQUAL( jsonKeyword, inlineKeyword );" << std::endl; + stream << " if (jsonKeyword.hasDimension()) {" <& keyword_files, bool verbose) { - } + std::map keyword_map; + for (const auto& keyword_file : keyword_files) { + if (verbose) + std::cout << "Loading keyword from file: " << keyword_file << std::endl; + + boost::filesystem::path path( keyword_file ); + std::unique_ptr parserKeyword; + + try { + Json::JsonObject jsonConfig = Json::JsonObject( path ); + parserKeyword.reset( new ParserKeyword(jsonConfig) ); + boost::filesystem::path abs_path = boost::filesystem::absolute( path ); + } catch (const std::exception& exc) { + std::cerr << std::endl; + std::cerr << "Failed to create parserkeyword from: " << path.string() << std::endl; + std::cerr << exc.what() << std::endl; + std::cerr << std::endl; + throw; + } + + const std::string name = parserKeyword->getName(); + if (keyword_map.find(name) != keyword_map.end()) { + this->m_jsonFile.erase(name); + keyword_map.erase(name); + } - size_t KeywordLoader::size() const { - return m_keywords.size(); - } + this->m_jsonFile.insert( std::pair ( name , keyword_file)); + keyword_map.insert( std::pair ( name , std::move(*parserKeyword))); + } - - bool KeywordLoader::hasKeyword(const std::string& keyword) const { - if (m_keywords.find( keyword ) == m_keywords.end()) - return false; - else - return true; - } - - - std::shared_ptr KeywordLoader::getKeyword(const std::string& keyword) const { - auto iter = m_keywords.find( keyword ); - if (iter == m_keywords.end()) - throw std::invalid_argument("Keyword " + keyword + " not loaded"); - else - return (*iter).second; + for (const auto& kw_pair : keyword_map) { + const auto& name = kw_pair.first; + const auto& parserKeyword = kw_pair.second; + this->keywords[name[0]].push_back( std::move(parserKeyword) ); + } } @@ -67,53 +80,14 @@ namespace Opm { } - void KeywordLoader::loadKeyword(boost::filesystem::path& path) { - std::shared_ptr jsonConfig = std::make_shared( path ); - try { - std::shared_ptr parserKeyword = std::make_shared(*jsonConfig); - boost::filesystem::path abs_path = boost::filesystem::absolute( path ); - addKeyword( parserKeyword , abs_path.generic_string() ); - } catch (const std::exception& exc) { - std::cerr << std::endl; - std::cerr << "Failed to create parserkeyword from: " << path.string() << std::endl; - std::cerr << exc.what() << std::endl; - std::cerr << std::endl; - throw; - } + std::map>::const_iterator KeywordLoader::begin( ) const { + return this->keywords.begin( ); } - void KeywordLoader::loadKeyword(const std::string& filename) { - boost::filesystem::path path( filename ); - if (m_verbose) - std::cout << "Loading keyword from file: " << filename << std::endl; - return loadKeyword( path ); + std::map>::const_iterator KeywordLoader::end( ) const { + return this->keywords.end( ); } - - - void KeywordLoader::addKeyword(std::shared_ptr keyword , const std::string& jsonFile) { - const std::string& name = keyword->getName(); - - if (hasKeyword(name)) { - m_keywords[name] = keyword; - m_jsonFile[name] = jsonFile; - } else { - m_keywords.insert( std::pair > (name , keyword) ); - m_jsonFile.insert( std::pair ( name , jsonFile)); - } - } - - - - std::map >::const_iterator KeywordLoader::keyword_begin( ) const { - return m_keywords.begin( ); - } - - std::map >::const_iterator KeywordLoader::keyword_end( ) const { - return m_keywords.end( ); - } - - } diff --git a/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp b/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp index 8d975ea87..93c612189 100644 --- a/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp +++ b/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp @@ -61,37 +61,36 @@ int main(int , char ** argv) { } const char * keyword_list_file = argv[1]; const char * source_file_name = argv[2]; - const char * header_file_base_path = argv[3]; - const char * header_file_name = argv[4]; - const char * test_file_name = argv[5]; + const char * init_file_name = argv[3]; + const char * header_file_base_path = argv[4]; + const char * header_file_path = argv[5]; + const char * test_file_name = argv[6]; - Opm::KeywordGenerator generator( true ); - Opm::KeywordLoader loader( false ); - + std::vector keyword_list; { + std::string buffer; + std::ifstream is(keyword_list_file); + std::getline( is , buffer ); + is.close(); + size_t start = 0; - std::string keyword_list; - - { - std::ifstream is(keyword_list_file); - std::getline( is , keyword_list ); - is.close(); - } - while (true) { - size_t end = keyword_list.find( ";" , start); + size_t end = buffer.find( ";" , start); if (end == std::string::npos) { - loader.loadKeyword( keyword_list.substr( start )); + keyword_list.push_back( buffer.substr(start) ); break; } - loader.loadKeyword( keyword_list.substr( start , end - start )); + keyword_list.push_back( buffer.substr(start, end - start )); start = end + 1; } } + Opm::KeywordLoader loader( keyword_list, false ); + Opm::KeywordGenerator generator( true ); - generator.updateSource(loader , source_file_name ); - generator.updateHeader(loader, header_file_base_path, header_file_name ); + generator.updateInitSource(loader , init_file_name ); + generator.updateKeywordSource(loader , source_file_name ); + generator.updateHeader(loader, header_file_base_path, header_file_path ); generator.updateTest( loader , test_file_name ); } diff --git a/tests/parser/KeywordLoaderTests.cpp b/tests/parser/KeywordLoaderTests.cpp deleted file mode 100644 index 2a3927c8c..000000000 --- a/tests/parser/KeywordLoaderTests.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright 2015 Statoil ASA. - - This file is part of the Open Porous Media project (OPM). - - OPM is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OPM is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OPM. If not, see . - */ - -#include -#include -#include - -#define BOOST_TEST_MODULE InputKeywordTests - -#include -#include -#include - - -#include -#include -#include - -inline std::string prefix() { - return boost::unit_test::framework::master_test_suite().argv[1]; -} - -BOOST_AUTO_TEST_CASE(EmptyKeywordLoader) { - Opm::KeywordLoader loader(false); - - BOOST_CHECK_EQUAL( false , loader.hasKeyword("NO")); - BOOST_CHECK_EQUAL( 0U , loader.size() ); - BOOST_CHECK_THROW( loader.getKeyword("NO") , std::invalid_argument); -} - - - -BOOST_AUTO_TEST_CASE(LoadKeyword) { - Opm::KeywordLoader loader(false); - - BOOST_CHECK_THROW( loader.loadKeyword("does/not/exists") , std::invalid_argument ); - BOOST_CHECK_THROW( loader.loadKeyword(prefix() + "invalid.json") , std::invalid_argument); - BOOST_CHECK_THROW( loader.loadKeyword(prefix() + "PORO-invalid") , std::invalid_argument); - - loader.loadKeyword(prefix() + "PORO.json"); - loader.loadKeyword(prefix() + "PORO.json"); - - BOOST_CHECK_EQUAL( true , loader.hasKeyword("PORO")); - BOOST_CHECK_EQUAL( 1U , loader.size() ); - - loader.getKeyword("PORO"); -} - - - diff --git a/tests/parser/TableManagerTests.cpp b/tests/parser/TableManagerTests.cpp index 7b20bb71f..1cf89a073 100644 --- a/tests/parser/TableManagerTests.cpp +++ b/tests/parser/TableManagerTests.cpp @@ -46,8 +46,6 @@ #include #include -#include - #include #include From aaee287dac1c646bb7a406a20a5a1a772cf89ab8 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Mon, 30 Dec 2019 09:00:35 +0100 Subject: [PATCH 2/4] Code generation file update routines are void --- .../eclipse/Generator/KeywordGenerator.hpp | 11 +++--- .../eclipse/Generator/KeywordGenerator.cpp | 36 +++++++------------ .../Parser/createDefaultKeywordList.cpp | 2 +- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/opm/parser/eclipse/Generator/KeywordGenerator.hpp b/opm/parser/eclipse/Generator/KeywordGenerator.hpp index 38aefb2e3..3b07a1c77 100644 --- a/opm/parser/eclipse/Generator/KeywordGenerator.hpp +++ b/opm/parser/eclipse/Generator/KeywordGenerator.hpp @@ -36,13 +36,12 @@ namespace Opm { static std::string endTest(); static std::string startTest(const std::string& test_name); static std::string headerHeader( const std::string& ); - static bool updateFile(const std::stringstream& newContent, const std::string& filename); - - bool updateInitSource(const KeywordLoader& loader, const std::string& sourceFile ) const; - bool updateKeywordSource(const KeywordLoader& loader, const std::string& sourceFile ) const; - bool updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const; - bool updateTest(const KeywordLoader& loader , const std::string& testFile) const; + static void updateFile(const std::stringstream& newContent, const std::string& filename); + void updateInitSource(const KeywordLoader& loader, const std::string& sourceFile ) const; + void updateKeywordSource(const KeywordLoader& loader, const std::string& sourceFile ) const; + void updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const; + void updateTest(const KeywordLoader& loader , const std::string& testFile) const; private: bool m_verbose; }; diff --git a/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp b/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp index 9a8d1408e..a06b8a024 100644 --- a/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp +++ b/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp @@ -76,27 +76,19 @@ namespace Opm { boost::filesystem::create_directories( file.parent_path()); } - bool KeywordGenerator::updateFile(const std::stringstream& newContent , const std::string& filename) { + void KeywordGenerator::updateFile(const std::stringstream& newContent , const std::string& filename) { ensurePath(filename); std::ofstream outputStream(filename); outputStream << newContent.str(); - - return true; } - static bool write_file( const std::stringstream& stream, const std::string& file, bool verbose, std::string desc = "source" ) { - auto update = KeywordGenerator::updateFile( stream, file ); - if( !verbose ) return update; - - if( update ) + static void write_file( const std::stringstream& stream, const std::string& file, bool verbose, std::string desc = "source" ) { + KeywordGenerator::updateFile( stream, file ); + if( verbose ) std::cout << "Updated " << desc << " file written to: " << file << std::endl; - else - std::cout << "No changes to " << desc << " file: " << file << std::endl; - - return update; } - bool KeywordGenerator::updateInitSource(const KeywordLoader& loader , const std::string& sourceFile ) const { + void KeywordGenerator::updateInitSource(const KeywordLoader& loader , const std::string& sourceFile ) const { std::stringstream newSource; newSource << "#include " << std::endl; for(const auto& kw_pair : loader) { @@ -120,10 +112,10 @@ namespace Opm { newSource << "void Parser::addDefaultKeywords() {\n ParserKeywords::addDefaultKeywords(*this);\n}" << std::endl; newSource << "}" << std::endl; - return write_file( newSource, sourceFile, m_verbose, "init" ); + write_file( newSource, sourceFile, m_verbose, "init" ); } - bool KeywordGenerator::updateKeywordSource(const KeywordLoader& loader , const std::string& sourceFile ) const { + void KeywordGenerator::updateKeywordSource(const KeywordLoader& loader , const std::string& sourceFile ) const { std::stringstream newSource; newSource << sourceHeader << std::endl; @@ -138,12 +130,10 @@ namespace Opm { newSource << "}\n}" << std::endl; } - return write_file( newSource, sourceFile, m_verbose, "source" ); + write_file( newSource, sourceFile, m_verbose, "source" ); } - bool KeywordGenerator::updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const { - bool update = false; - + void KeywordGenerator::updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const { for( const auto& kw_pair : loader) { std::stringstream stream; const auto& first_char = kw_pair.first; @@ -157,10 +147,8 @@ namespace Opm { stream << "#endif" << std::endl; const auto final_path = headerBuildPath + headerPath+ "/" + std::string( 1, first_char ) + ".hpp"; - if( write_file( stream, final_path, m_verbose, "header" ) ) - update = true; + write_file( stream, final_path, m_verbose, "header" ); } - return update; } @@ -175,7 +163,7 @@ namespace Opm { - bool KeywordGenerator::updateTest(const KeywordLoader& loader , const std::string& testFile) const { + void KeywordGenerator::updateTest(const KeywordLoader& loader , const std::string& testFile) const { std::stringstream stream; stream << testHeader; @@ -205,7 +193,7 @@ namespace Opm { } stream << "}" << std::endl; } - return updateFile( stream , testFile ); + updateFile( stream , testFile ); } } diff --git a/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp b/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp index 93c612189..aa5d93a37 100644 --- a/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp +++ b/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp @@ -89,8 +89,8 @@ int main(int , char ** argv) { Opm::KeywordLoader loader( keyword_list, false ); Opm::KeywordGenerator generator( true ); - generator.updateInitSource(loader , init_file_name ); generator.updateKeywordSource(loader , source_file_name ); + generator.updateInitSource(loader , init_file_name ); generator.updateHeader(loader, header_file_base_path, header_file_path ); generator.updateTest( loader , test_file_name ); } From 3c6a60c4a9dd09dc3e4c390e7be3a7f171bf2543 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Mon, 30 Dec 2019 15:26:17 +0100 Subject: [PATCH 3/4] Code genereator will create many source files --- CMakeLists.txt | 5 +- CopyHeaders.cmake | 11 +-- GenerateKeywords.cmake | 67 +++++++++++++++++-- .../eclipse/Generator/KeywordGenerator.cpp | 8 +-- .../eclipse/Generator/KeywordLoader.cpp | 2 + .../Parser/createDefaultKeywordList.cpp | 4 +- 6 files changed, 80 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7309b93d4..aca783851 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,7 +115,10 @@ macro (sources_hook) include(GenerateKeywords.cmake) # Append generated sources - list(INSERT opm-common_SOURCES 0 ${PROJECT_BINARY_DIR}/ParserKeywords.cpp ${PROJECT_BINARY_DIR}/ParserInit.cpp) + 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) + endforeach() endif() set_source_files_properties(src/opm/parser/eclipse/Python/Python.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow) diff --git a/CopyHeaders.cmake b/CopyHeaders.cmake index 91b19a704..08a7fa726 100644 --- a/CopyHeaders.cmake +++ b/CopyHeaders.cmake @@ -1,7 +1,3 @@ -execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${BASE_DIR}/tmp_gen/ParserKeywords.cpp - ${BASE_DIR}/ParserKeywords.cpp) - execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${BASE_DIR}/tmp_gen/ParserInit.cpp ${BASE_DIR}/ParserInit.cpp) @@ -18,4 +14,11 @@ foreach(HDR ${HDRS}) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${HDR} ${BASE_DIR}/include/opm/parser/eclipse/Parser/ParserKeywords/${hdr}) + +endforeach() + +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) endforeach() diff --git a/GenerateKeywords.cmake b/GenerateKeywords.cmake index 9795043e3..b770f2719 100644 --- a/GenerateKeywords.cmake +++ b/GenerateKeywords.cmake @@ -40,10 +40,37 @@ string(REGEX REPLACE "([^;]+)" "${PROJECT_SOURCE_DIR}/src/opm/parser/eclipse/sha configure_file(src/opm/parser/eclipse/keyword_list.argv.in keyword_list.argv) # Generate keyword source -add_custom_command( - OUTPUT ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords.cpp ${PROJECT_BINARY_DIR}/tmp_gen/inlinekw.cpp - COMMAND genkw keyword_list.argv - ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords.cpp + +add_custom_command( OUTPUT + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/A.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/B.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/C.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/D.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/E.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/F.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/G.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/H.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/I.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/J.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/K.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/L.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/M.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/N.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/O.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/P.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/Q.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/R.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/S.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/T.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/U.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/V.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/W.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/X.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/Y.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/Z.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/inlinekw.cpp + COMMAND genkw keyword_list.argv + ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords ${PROJECT_BINARY_DIR}/tmp_gen/ParserInit.cpp ${PROJECT_BINARY_DIR}/tmp_gen/include/ opm/parser/eclipse/Parser/ParserKeywords @@ -52,7 +79,35 @@ add_custom_command( ) # To avoid some rebuilds -add_custom_command(OUTPUT ParserKeywords.cpp inlinekw.cpp ParserInit.cpp - DEPENDS ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords.cpp +add_custom_command(OUTPUT + ${PROJECT_BINARY_DIR}/ParserKeywords/A.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/B.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/C.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/D.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/E.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/F.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/G.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/H.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/I.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/J.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/K.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/L.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/M.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/N.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/O.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/P.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/Q.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/R.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/S.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/T.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/U.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/V.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/W.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/X.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/Y.cpp + ${PROJECT_BINARY_DIR}/ParserKeywords/Z.cpp + ${PROJECT_BINARY_DIR}/inlinekw.cpp + ${PROJECT_BINARY_DIR}/ParserInit.cpp + DEPENDS ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/A.cpp COMMAND ${CMAKE_COMMAND} -DBASE_DIR=${PROJECT_BINARY_DIR} -P ${PROJECT_SOURCE_DIR}/CopyHeaders.cmake) diff --git a/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp b/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp index a06b8a024..72b06322c 100644 --- a/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp +++ b/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp @@ -115,22 +115,22 @@ namespace Opm { write_file( newSource, sourceFile, m_verbose, "init" ); } - void KeywordGenerator::updateKeywordSource(const KeywordLoader& loader , const std::string& sourceFile ) const { - std::stringstream newSource; - newSource << sourceHeader << std::endl; + void KeywordGenerator::updateKeywordSource(const KeywordLoader& loader , const std::string& sourcePath ) const { for(const auto& kw_pair : loader) { const auto& first_char = kw_pair.first; const auto& keywords = kw_pair.second; + std::stringstream newSource; + newSource << sourceHeader << std::endl; newSource << std::endl << std::endl << "#include " << std::endl; newSource << "namespace Opm {" << std::endl; newSource << "namespace ParserKeywords {" << std::endl; for (const auto& kw: keywords) newSource << kw.createCode() << std::endl; newSource << "}\n}" << std::endl; + write_file( newSource, sourcePath + "/" + first_char + ".cpp", m_verbose, "source" ); } - write_file( newSource, sourceFile, m_verbose, "source" ); } void KeywordGenerator::updateHeader(const KeywordLoader& loader, const std::string& headerBuildPath, const std::string& headerPath) const { diff --git a/src/opm/parser/eclipse/Generator/KeywordLoader.cpp b/src/opm/parser/eclipse/Generator/KeywordLoader.cpp index 711772b72..19ee07c2c 100644 --- a/src/opm/parser/eclipse/Generator/KeywordLoader.cpp +++ b/src/opm/parser/eclipse/Generator/KeywordLoader.cpp @@ -63,6 +63,8 @@ namespace Opm { keyword_map.insert( std::pair ( name , std::move(*parserKeyword))); } + this->keywords['Y'] = {}; + this->keywords['X'] = {}; for (const auto& kw_pair : keyword_map) { const auto& name = kw_pair.first; const auto& parserKeyword = kw_pair.second; diff --git a/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp b/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp index aa5d93a37..52873acad 100644 --- a/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp +++ b/src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp @@ -60,7 +60,7 @@ int main(int , char ** argv) { << std::endl; } const char * keyword_list_file = argv[1]; - const char * source_file_name = argv[2]; + const char * source_file_path = argv[2]; const char * init_file_name = argv[3]; const char * header_file_base_path = argv[4]; const char * header_file_path = argv[5]; @@ -89,7 +89,7 @@ int main(int , char ** argv) { Opm::KeywordLoader loader( keyword_list, false ); Opm::KeywordGenerator generator( true ); - generator.updateKeywordSource(loader , source_file_name ); + generator.updateKeywordSource(loader , source_file_path ); generator.updateInitSource(loader , init_file_name ); generator.updateHeader(loader, header_file_base_path, header_file_path ); generator.updateTest( loader , test_file_name ); From 087aec6e01107a0e4f0243fce84537681687c3de Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Tue, 31 Dec 2019 14:50:18 +0100 Subject: [PATCH 4/4] Refactored generated keyword test to reduce compilation time --- CopyHeaders.cmake | 4 +- ExtraTests.cmake | 6 +- GenerateKeywords.cmake | 4 +- .../eclipse/Generator/KeywordGenerator.cpp | 71 ++++++++++--------- 4 files changed, 46 insertions(+), 39 deletions(-) diff --git a/CopyHeaders.cmake b/CopyHeaders.cmake index 08a7fa726..25a4ed73f 100644 --- a/CopyHeaders.cmake +++ b/CopyHeaders.cmake @@ -3,8 +3,8 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${BASE_DIR}/ParserInit.cpp) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${BASE_DIR}/tmp_gen/inlinekw.cpp - ${BASE_DIR}/inlinekw.cpp) + ${BASE_DIR}/tmp_gen/TestKeywords.cpp + ${BASE_DIR}/TestKeywords.cpp) file(GLOB HDRS ${BASE_DIR}/tmp_gen/include/opm/parser/eclipse/Parser/ParserKeywords/*.hpp) diff --git a/ExtraTests.cmake b/ExtraTests.cmake index 118a8ff5d..79c33e647 100644 --- a/ExtraTests.cmake +++ b/ExtraTests.cmake @@ -4,10 +4,10 @@ set(EXTRA_TESTS) # Generated source, needs to be here opm_add_test(InlineKeywordTest - EXE_NAME inlinekw - SOURCES ${PROJECT_BINARY_DIR}/inlinekw.cpp + EXE_NAME TestKeywords + SOURCES ${PROJECT_BINARY_DIR}/TestKeywords.cpp LIBRARIES ${TEST_LIBS}) -list(APPEND EXTRA_TESTS inlinekw) +list(APPEND EXTRA_TESTS TestKeywords) # Extra compile definitions and extra parameters include(cmake/Modules/CheckCaseSensitiveFileSystem.cmake) diff --git a/GenerateKeywords.cmake b/GenerateKeywords.cmake index b770f2719..2d00d0283 100644 --- a/GenerateKeywords.cmake +++ b/GenerateKeywords.cmake @@ -74,7 +74,7 @@ add_custom_command( OUTPUT ${PROJECT_BINARY_DIR}/tmp_gen/ParserInit.cpp ${PROJECT_BINARY_DIR}/tmp_gen/include/ opm/parser/eclipse/Parser/ParserKeywords - ${PROJECT_BINARY_DIR}/tmp_gen/inlinekw.cpp + ${PROJECT_BINARY_DIR}/tmp_gen/TestKeywords.cpp DEPENDS genkw ${keyword_files} src/opm/parser/eclipse/share/keywords/keyword_list.cmake ) @@ -106,7 +106,7 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/ParserKeywords/X.cpp ${PROJECT_BINARY_DIR}/ParserKeywords/Y.cpp ${PROJECT_BINARY_DIR}/ParserKeywords/Z.cpp - ${PROJECT_BINARY_DIR}/inlinekw.cpp + ${PROJECT_BINARY_DIR}/TestKeywords.cpp ${PROJECT_BINARY_DIR}/ParserInit.cpp DEPENDS ${PROJECT_BINARY_DIR}/tmp_gen/ParserKeywords/A.cpp COMMAND ${CMAKE_COMMAND} -DBASE_DIR=${PROJECT_BINARY_DIR} diff --git a/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp b/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp index 72b06322c..9b9812239 100644 --- a/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp +++ b/src/opm/parser/eclipse/Generator/KeywordGenerator.cpp @@ -34,17 +34,6 @@ namespace { -const std::string testHeader = - "#define BOOST_TEST_MODULE ParserRecordTests\n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "auto unitSystem = Opm::UnitSystem::newMETRIC();\n"; const std::string sourceHeader = "#include \n" @@ -166,33 +155,51 @@ namespace Opm { void KeywordGenerator::updateTest(const KeywordLoader& loader , const std::string& testFile) const { std::stringstream stream; - stream << testHeader; for(const auto& kw_pair : loader) { const auto& first_char = kw_pair.first; stream << "#include " << std::endl; - stream << "namespace Opm {" << std::endl; + } + + stream << R"( + +#define BOOST_TEST_MODULE GeneratedKeywordTest +#include +#include +#include +#include +#include +#include +#include +#include +auto unitSystem = Opm::UnitSystem::newMETRIC(); + +namespace Opm { +void test_keyword(const ParserKeyword& inline_keyword, const std::string& json_file) { + boost::filesystem::path jsonPath( json_file ); + Json::JsonObject jsonConfig( jsonPath ); + ParserKeyword json_keyword(jsonConfig); + BOOST_CHECK_EQUAL( json_keyword, inline_keyword); + if (json_keyword.hasDimension()) { + const auto& parserRecord = json_keyword.getRecord(0); + for (size_t i=0; i < parserRecord.size(); i++){ + const auto& item = parserRecord.get( i ); + for (const auto& dim : item.dimensions()) + BOOST_CHECK_NO_THROW( unitSystem.getNewDimension( dim )); + } + } +} + + +)"; + + for(const auto& kw_pair : loader) { + stream << std::endl << "BOOST_AUTO_TEST_CASE(TestKeywords" << kw_pair.first << ") {" << std::endl; const auto& keywords = kw_pair.second; - for (const auto& kw: keywords) { - const std::string& keywordName = kw.getName(); - stream << startTest(keywordName); - stream << " std::string jsonFile = \"" << loader.getJsonFile( keywordName) << "\";" << std::endl; - stream << " boost::filesystem::path jsonPath( jsonFile );" << std::endl; - stream << " Json::JsonObject jsonConfig( jsonPath );" << std::endl; - stream << " ParserKeyword jsonKeyword(jsonConfig);" << std::endl; - stream << " ParserKeywords::" << keywordName << " inlineKeyword;" << std::endl; - stream << " BOOST_CHECK_EQUAL( jsonKeyword, inlineKeyword );" << std::endl; - stream << " if (jsonKeyword.hasDimension()) {" <