diff --git a/CMakeLists.txt b/CMakeLists.txt index 66f56188535e5a3b7f26bb74d67b4d5cd283eaea..08782444aaad92cb5142f5940b19272dfea18249 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,12 +22,19 @@ if("${PUGS_SHORT_VERSION}" STREQUAL "") message(FATAL_ERROR "Unable to compute short version from PUGS_VERSION=${PUGS_VERSION}") endif() +# set project version as PUGS_SHORT_VERSION +project (Pugs VERSION ${PUGS_SHORT_VERSION}) + +# ----------------------------------------------------- +# dynamic libraries + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +link_libraries("-rdynamic") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -set(CMAKE_CONFIGURATION_TYPES "Release;Debug;Coverage" CACHE STRING INTERNAL FORCE ) +#------------------------------------------------------ -# set project version as PUGS_SHORT_VERSION -project (Pugs VERSION ${PUGS_SHORT_VERSION}) +set(CMAKE_CONFIGURATION_TYPES "Release;Debug;Coverage" CACHE STRING INTERNAL FORCE ) #------------------------------------------------------ @@ -380,6 +387,7 @@ include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/rang/include") include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/CLI11/include") # PEGTL +add_subdirectory(${PUGS_SOURCE_DIR}/packages/PEGTL/) include_directories(SYSTEM "${PUGS_SOURCE_DIR}/packages/PEGTL/include/tao") # Pugs src @@ -597,10 +605,6 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage") endif() endif() -# ----------------------------------------------------- - -link_libraries("-rdynamic") - # ------------------- Source files -------------------- # Pugs binary add_executable( diff --git a/src/language/modules/ModuleRepository.cpp b/src/language/modules/ModuleRepository.cpp index 42d62fa0abac86a74a36379271482bc15b685997..c9c487b67b5fdbf63d2b307baf1497519666a5d8 100644 --- a/src/language/modules/ModuleRepository.cpp +++ b/src/language/modules/ModuleRepository.cpp @@ -13,6 +13,27 @@ #include <set> +ModuleRepository* ModuleRepository::m_instance = nullptr; + +ModuleRepository& +ModuleRepository::getInstance() +{ + if (m_instance == nullptr) { + m_instance = new ModuleRepository; + } + + return *m_instance; +} + +void +ModuleRepository::destroy() +{ + if (m_instance != nullptr) { + delete m_instance; + m_instance = nullptr; + } +} + void ModuleRepository::_subscribe(std::unique_ptr<IModule> m) { diff --git a/src/language/modules/ModuleRepository.hpp b/src/language/modules/ModuleRepository.hpp index b2e217b9374bb918e75d5a6dbe028ae4f8e12923..35bf6f7aa6a7704f2804125c488ac0bf115ddf39 100644 --- a/src/language/modules/ModuleRepository.hpp +++ b/src/language/modules/ModuleRepository.hpp @@ -31,13 +31,12 @@ class ModuleRepository const IModule::NameValueMap& name_value_map, SymbolTable& symbol_table); + static ModuleRepository* m_instance; + public: - static ModuleRepository& - getInstance() - { - static ModuleRepository m_instance; - return m_instance; - } + static ModuleRepository& getInstance(); + + static void destroy(); template <typename ModuleT> struct Subscribe diff --git a/src/main.cpp b/src/main.cpp index a373bd2cd867b21b1d931449f12b64239ef03c22..cd576a9f63a8273b366a76a298b508e2fbb1ff54 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include <analysis/QuadratureManager.hpp> #include <dev/ParallelChecker.hpp> #include <language/PugsParser.hpp> +#include <language/modules/ModuleRepository.hpp> #include <mesh/DualConnectivityManager.hpp> #include <mesh/DualMeshManager.hpp> #include <mesh/MeshDataManager.hpp> @@ -11,6 +12,8 @@ #include <utils/RandomEngine.hpp> #include <utils/checkpointing/ResumingManager.hpp> +#include <utils/PluginsLoader.hpp> + int main(int argc, char* argv[]) { @@ -20,6 +23,8 @@ main(int argc, char* argv[]) std::string filename = initialize(argc, argv); + PluginsLoader plugins_loader; + SynchronizerManager::create(); RandomEngine::create(); QuadratureManager::create(); @@ -32,6 +37,8 @@ main(int argc, char* argv[]) parser(filename); ExecutionStatManager::printInfo(); + ModuleRepository::destroy(); + GlobalVariableManager::destroy(); DualMeshManager::destroy(); diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 13b0db80862c2b28e80dc18ff22951b08157db28..39e8cb35925fb1417222080e2ac0e060814ad353 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -16,6 +16,7 @@ add_library( Messenger.cpp Partitioner.cpp PETScWrapper.cpp + PluginsLoader.cpp PugsUtils.cpp RandomEngine.cpp ReproducibleSumManager.cpp diff --git a/src/utils/PluginsLoader.cpp b/src/utils/PluginsLoader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8616c7a68ecb6703a91f4885693fbd020fd2406f --- /dev/null +++ b/src/utils/PluginsLoader.cpp @@ -0,0 +1,96 @@ +#include <utils/PluginsLoader.hpp> + +#include <dlfcn.h> + +#include <rang.hpp> + +#include <filesystem> +#include <iostream> +#include <sstream> +#include <unistd.h> +#include <vector> + +std::vector<std::string> +split(const std::string& full_string) +{ + std::vector<std::string> split_string; + + std::stringstream is(full_string); + + std::string segment; + while (std::getline(is, segment, ';')) { + if (segment.size() > 0) { + split_string.push_back(segment); + } + } + return split_string; +} + +void +PluginsLoader::_open(const std::string& plugin) +{ + auto handle = dlopen(plugin.c_str(), RTLD_NOW); + if (handle != nullptr) { + m_dl_handler_stack.push(handle); + std::cout << " * \"" << rang::fgB::green << plugin << rang::fg::reset << "\"\n"; + } else { + std::cout << " " << rang::fgB::red << "cannot load " << rang::fg::reset << '\"' << rang::fgB::yellow << plugin + << rang::fg::reset << "\"\n"; + } +} + +PluginsLoader::PluginsLoader() +{ + std::vector<std::string> plugin_vector; + + { + char* env = getenv("PUGS_PLUGIN"); + if (env != nullptr) { + std::string plugins = env; + plugin_vector = split(plugins); + } + } + + { + char* env = getenv("PUGS_PLUGIN_DIR"); + if (env != nullptr) { + std::string paths = env; + std::vector<std::string> path_vector = split(paths); + for (auto&& path : path_vector) { + if (access(path.c_str(), R_OK) == -1) { + std::cout << ' ' << rang::fgB::red << 'X' << rang::fg::reset << " cannot access plugin dir \"" + << rang::fgB::yellow << path << rang::fg::reset << "\"\n"; + } else { + for (auto&& entry : + std::filesystem::directory_iterator(path, + (std::filesystem::directory_options::follow_directory_symlink | + std::filesystem::directory_options::skip_permission_denied))) { + if (entry.path().extension() == ".so") { + plugin_vector.push_back(entry.path().string()); + } + } + } + } + } + } + + // keep unique entries + std::sort(plugin_vector.begin(), plugin_vector.end()); + plugin_vector.resize(std::distance(plugin_vector.begin(), std::unique(plugin_vector.begin(), plugin_vector.end()))); + + if (plugin_vector.size() > 0) { + std::cout << rang::style::bold << "Loading plugins" << rang::style::reset << '\n'; + for (auto&& plugin : plugin_vector) { + this->_open(plugin); + } + std::cout << "-------------------------------------------------------\n"; + } +} + +PluginsLoader::~PluginsLoader() +{ + while (not m_dl_handler_stack.empty()) { + dlclose(m_dl_handler_stack.top()); + m_dl_handler_stack.pop(); + } +} diff --git a/src/utils/PluginsLoader.hpp b/src/utils/PluginsLoader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..76be25c6934c5f336360e938d9a40d75f075e6d3 --- /dev/null +++ b/src/utils/PluginsLoader.hpp @@ -0,0 +1,23 @@ +#ifndef PLUGINS_LOADER_HPP +#define PLUGINS_LOADER_HPP + +#include <stack> +#include <string> + +class PluginsLoader +{ + private: + std::stack<void*> m_dl_handler_stack; + + void _open(const std::string& filename); + + public: + PluginsLoader(); + + PluginsLoader(const PluginsLoader&) = delete; + PluginsLoader(PluginsLoader&&) = delete; + + ~PluginsLoader(); +}; + +#endif // PLUGINS_LOADER_HPP