From 541c0d75474d30eb4d0ca9bf903dd70f1b1ba924 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sun, 23 Jan 2022 23:28:56 +0100 Subject: [PATCH] build/plugin: Make plugins no longer depend on their file name --- cmake/build_helpers.cmake | 42 +++++++++++++-------- lib/libimhex/include/hex/plugin.hpp | 17 ++++----- main/include/helpers/plugin_manager.hpp | 12 ++++-- main/source/helpers/plugin_manager.cpp | 46 +++++++++++++++-------- main/source/window/window.cpp | 19 ++++++---- plugins/windows/source/plugin_windows.cpp | 2 +- 6 files changed, 85 insertions(+), 53 deletions(-) diff --git a/cmake/build_helpers.cmake b/cmake/build_helpers.cmake index 3ae87b6f6..8cbbdd94b 100644 --- a/cmake/build_helpers.cmake +++ b/cmake/build_helpers.cmake @@ -16,15 +16,25 @@ macro(addVersionDefines) OUTPUT_STRIP_TRAILING_WHITESPACE ) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGIT_COMMIT_HASH=\"\\\"${GIT_COMMIT_HASH}\"\\\"") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGIT_BRANCH=\"\\\"${GIT_BRANCH}\"\\\"") - endif() + add_compile_definitions(GIT_COMMIT_HASH="${GIT_COMMIT_HASH}" GIT_BRANCH="${GIT_BRANCH}") + endif () set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DPROJECT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} -DPROJECT_VERSION_MINOR=${PROJECT_VERSION_MINOR} -DPROJECT_VERSION_PATCH=${PROJECT_VERSION_PATCH} ") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DRELEASE -DIMHEX_VERSION=\"\\\"${PROJECT_VERSION}\"\\\"") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -DIMHEX_VERSION=\"\\\"${PROJECT_VERSION}-Debug\"\\\"") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DRELEASE -DIMHEX_VERSION=\"\\\"${PROJECT_VERSION}-ReleaseWithDebugInfo\"\\\"") - set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -DRELEASE -DIMHEX_VERSION=\"\\\"${PROJECT_VERSION}-ReleaseMinimumSize\"\\\"") + + add_compile_definitions( + $<$:IMHEX_VERSION="${PROJECT_VERSION}"> + $<$:IMHEX_VERSION="${PROJECT_VERSION}-Debug"> + $<$:IMHEX_VERSION="${PROJECT_VERSION}-ReleaseWithDebugInfo"> + $<$:IMHEX_VERSION="${PROJECT_VERSION}-ReleaseMinimumSize"> + ) + + add_compile_definitions( + $<$:RELEASE> + $<$:DEBUG> + $<$:RELEASE> + $<$:RELEASE> + ) + endmacro() macro(configurePython) @@ -49,30 +59,30 @@ macro(configurePython) endif () list(JOIN PYTHON_VERSION_MAJOR_MINOR "." PYTHON_VERSION_MAJOR_MINOR) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} -DPYTHON_VERSION_MAJOR_MINOR=\"\\\"${PYTHON_VERSION_MAJOR_MINOR}\"\\\"") + add_compile_definitions(PYTHON_VERSION_MAJOR_MINOR="${PYTHON_VERSION_MAJOR_MINOR}") endmacro() # Detect current OS / System macro(detectOS) if (WIN32) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOS_WINDOWS") + add_compile_definitions(OS_WINDOWS) set(CMAKE_INSTALL_BINDIR ".") set(CMAKE_INSTALL_LIBDIR ".") set(PLUGINS_INSTALL_LOCATION "plugins") set(MAGIC_INSTALL_LOCATION "magic") - elseif(APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOS_MACOS") + elseif (APPLE) + add_compile_definitions(OS_MACOS) set(CMAKE_INSTALL_BINDIR ".") set(CMAKE_INSTALL_LIBDIR ".") set(PLUGINS_INSTALL_LOCATION "plugins") set(MAGIC_INSTALL_LOCATION "magic") - elseif(UNIX AND NOT APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOS_LINUX") + elseif (UNIX AND NOT APPLE) + add_compile_definitions(OS_LINUX) set(CMAKE_INSTALL_BINDIR "bin") set(CMAKE_INSTALL_LIBDIR "lib") set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins") set(MAGIC_INSTALL_LOCATION "share/imhex/magic") - else() + else () message(FATAL_ERROR "Unknown / unsupported system!") endif() endmacro() @@ -80,9 +90,9 @@ endmacro() # Detect 32 vs. 64 bit system macro(detectArch) if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DARCH_64_BIT") + add_compile_definitions(ARCH_64_BIT) elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DARCH_32_BIT") + add_compile_definitions(ARCH_32_BIT) endif() endmacro() diff --git a/lib/libimhex/include/hex/plugin.hpp b/lib/libimhex/include/hex/plugin.hpp index b35057bed..aa63536eb 100644 --- a/lib/libimhex/include/hex/plugin.hpp +++ b/lib/libimhex/include/hex/plugin.hpp @@ -8,13 +8,10 @@ #define IMHEX_PLUGIN_SETUP(name, author, description) IMHEX_PLUGIN_SETUP_IMPL(IMHEX_PLUGIN_NAME, name, author, description) -#define IMHEX_PLUGIN_SETUP_IMPL(namespaceName, name, author, description) \ - namespace hex::plugin::namespaceName::internal { \ - [[gnu::visibility("default")]] void initializePlugin(); \ - \ - [[gnu::visibility("default")]] const char* getPluginName() { return name; } \ - [[gnu::visibility("default")]] const char* getPluginAuthor() { return author; } \ - [[gnu::visibility("default")]] const char* getPluginDescription() { return description; } \ - [[gnu::visibility("default")]] void setImGuiContext(ImGuiContext *ctx) { ImGui::SetCurrentContext(ctx); GImGui = ctx; } \ - } \ - void hex::plugin::namespaceName::internal::initializePlugin() +#define IMHEX_PLUGIN_SETUP_IMPL(namespaceName, name, author, description) \ + extern "C" [[gnu::visibility("default")]] const char* getPluginName() { return name; } \ + extern "C" [[gnu::visibility("default")]] const char* getPluginAuthor() { return author; } \ + extern "C" [[gnu::visibility("default")]] const char* getPluginDescription() { return description; } \ + extern "C" [[gnu::visibility("default")]] const char* getCompatibleVersion() { return IMHEX_VERSION; } \ + extern "C" [[gnu::visibility("default")]] void setImGuiContext(ImGuiContext *ctx) { ImGui::SetCurrentContext(ctx); GImGui = ctx; } \ + extern "C" [[gnu::visibility("default")]] void initializePlugin() diff --git a/main/include/helpers/plugin_manager.hpp b/main/include/helpers/plugin_manager.hpp index dc26f03d5..17c34ed54 100644 --- a/main/include/helpers/plugin_manager.hpp +++ b/main/include/helpers/plugin_manager.hpp @@ -22,33 +22,39 @@ namespace hex { [[nodiscard]] std::string getPluginName() const; [[nodiscard]] std::string getPluginAuthor() const; [[nodiscard]] std::string getPluginDescription() const; + [[nodiscard]] std::string getCompatibleVersion() const; void setImGuiContext(ImGuiContext *ctx) const; [[nodiscard]] const fs::path& getPath() const; + [[nodiscard]] bool isLoaded() const; private: using InitializePluginFunc = void(*)(); using GetPluginNameFunc = const char*(*)(); using GetPluginAuthorFunc = const char*(*)(); using GetPluginDescriptionFunc = const char*(*)(); + using GetCompatibleVersionFunc = const char*(*)(); using SetImGuiContextFunc = void(*)(ImGuiContext*); void *m_handle = nullptr; fs::path m_path; + mutable bool m_initialized = false; + InitializePluginFunc m_initializePluginFunction = nullptr; GetPluginNameFunc m_getPluginNameFunction = nullptr; GetPluginAuthorFunc m_getPluginAuthorFunction = nullptr; GetPluginDescriptionFunc m_getPluginDescriptionFunction = nullptr; + GetCompatibleVersionFunc m_getCompatibleVersionFunction = nullptr; SetImGuiContextFunc m_setImGuiContextFunction = nullptr; template - [[nodiscard]] auto getPluginFunction(const std::string &pluginName, const std::string &symbol) { - return reinterpret_cast(this->getPluginFunction(pluginName, symbol)); + [[nodiscard]] auto getPluginFunction(const std::string &symbol) { + return reinterpret_cast(this->getPluginFunction(symbol)); } private: - [[nodiscard]] void* getPluginFunction(const std::string &pluginName, const std::string &symbol); + [[nodiscard]] void* getPluginFunction(const std::string &symbol); }; class PluginManager { diff --git a/main/source/helpers/plugin_manager.cpp b/main/source/helpers/plugin_manager.cpp index dd500dee5..e42223ee6 100644 --- a/main/source/helpers/plugin_manager.cpp +++ b/main/source/helpers/plugin_manager.cpp @@ -7,13 +7,6 @@ namespace hex { - // hex::plugin::::internal::initializePlugin() - constexpr auto InitializePluginSymbol = "_ZN3hex6plugin{0}{1}8internal16initializePluginEv"; - constexpr auto GetPluginNameSymbol = "_ZN3hex6plugin{0}{1}8internal13getPluginNameEv"; - constexpr auto GetPluginAuthorSymbol = "_ZN3hex6plugin{0}{1}8internal15getPluginAuthorEv"; - constexpr auto GetPluginDescriptionSymbol = "_ZN3hex6plugin{0}{1}8internal20getPluginDescriptionEv"; - constexpr auto SetImGuiContextSymbol = "_ZN3hex6plugin{0}{1}8internal15setImGuiContextEP12ImGuiContext"; - Plugin::Plugin(const fs::path &path) : m_path(path) { this->m_handle = dlopen(path.string().c_str(), RTLD_LAZY); @@ -24,11 +17,12 @@ namespace hex { auto pluginName = fs::path(path).stem().string(); - this->m_initializePluginFunction = getPluginFunction(pluginName, InitializePluginSymbol); - this->m_getPluginNameFunction = getPluginFunction(pluginName, GetPluginNameSymbol); - this->m_getPluginAuthorFunction = getPluginFunction(pluginName, GetPluginAuthorSymbol); - this->m_getPluginDescriptionFunction = getPluginFunction(pluginName, GetPluginDescriptionSymbol); - this->m_setImGuiContextFunction = getPluginFunction(pluginName, SetImGuiContextSymbol); + this->m_initializePluginFunction = getPluginFunction("initializePlugin"); + this->m_getPluginNameFunction = getPluginFunction("getPluginName"); + this->m_getPluginAuthorFunction = getPluginFunction("getPluginAuthor"); + this->m_getPluginDescriptionFunction = getPluginFunction("getPluginDescription"); + this->m_getCompatibleVersionFunction = getPluginFunction("getCompatibleVersion"); + this->m_setImGuiContextFunction = getPluginFunction("setImGuiContext"); } Plugin::Plugin(Plugin &&other) noexcept { @@ -39,6 +33,7 @@ namespace hex { this->m_getPluginNameFunction = other.m_getPluginNameFunction; this->m_getPluginAuthorFunction = other.m_getPluginAuthorFunction; this->m_getPluginDescriptionFunction = other.m_getPluginDescriptionFunction; + this->m_getCompatibleVersionFunction = other.m_getCompatibleVersionFunction; this->m_setImGuiContextFunction = other.m_setImGuiContextFunction; other.m_handle = nullptr; @@ -46,6 +41,7 @@ namespace hex { other.m_getPluginNameFunction = nullptr; other.m_getPluginAuthorFunction = nullptr; other.m_getPluginDescriptionFunction = nullptr; + other.m_getCompatibleVersionFunction = nullptr; other.m_setImGuiContextFunction = nullptr; } @@ -55,12 +51,20 @@ namespace hex { } bool Plugin::initializePlugin() const { + const auto requestedVersion = getCompatibleVersion(); + if (requestedVersion != IMHEX_VERSION) { + log::error("Refused to load plugin '{}' which was built for a different version of ImHex: '{}'", this->m_path.filename().string(), requestedVersion); + return false; + } + if (this->m_initializePluginFunction != nullptr) { this->m_initializePluginFunction(); - return true; } else { return false; } + + this->m_initialized = true; + return true; } std::string Plugin::getPluginName() const { @@ -84,6 +88,13 @@ namespace hex { return ""; } + std::string Plugin::getCompatibleVersion() const { + if (this->m_getCompatibleVersionFunction != nullptr) + return this->m_getCompatibleVersionFunction(); + else + return ""; + } + void Plugin::setImGuiContext(ImGuiContext *ctx) const { if (this->m_setImGuiContextFunction != nullptr) this->m_setImGuiContextFunction(ctx); @@ -93,12 +104,15 @@ namespace hex { return this->m_path; } - void* Plugin::getPluginFunction(const std::string &pluginName, const std::string &symbol) { - auto symbolName = hex::format(symbol.data(), pluginName.length(), pluginName.data()); - return dlsym(this->m_handle, symbolName.c_str()); + bool Plugin::isLoaded() const { + return this->m_initialized; } + void* Plugin::getPluginFunction(const std::string &symbol) { + return dlsym(this->m_handle, symbol.c_str()); + } + bool PluginManager::load(const fs::path &pluginFolder) { if (!fs::exists(pluginFolder)) diff --git a/main/source/window/window.cpp b/main/source/window/window.cpp index 83b88c173..3cdb49647 100644 --- a/main/source/window/window.cpp +++ b/main/source/window/window.cpp @@ -715,11 +715,12 @@ namespace hex { const auto &plugins = PluginManager::getPlugins(); if (!plugins.empty()) { - if (ImGui::BeginTable("plugins", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_SizingFixedFit, ImVec2((ImGui::GetContentRegionAvail().x * 5) / 6, ImGui::GetTextLineHeightWithSpacing() * 5))) { + if (ImGui::BeginTable("plugins", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_SizingFixedFit, ImVec2((ImGui::GetContentRegionAvail().x * 5) / 6, ImGui::GetTextLineHeightWithSpacing() * 5))) { ImGui::TableSetupScrollFreeze(0, 1); - ImGui::TableSetupColumn("hex.welcome.plugins.plugin"_lang); - ImGui::TableSetupColumn("hex.welcome.plugins.author"_lang); - ImGui::TableSetupColumn("hex.welcome.plugins.desc"_lang); + ImGui::TableSetupColumn("hex.welcome.plugins.plugin"_lang, ImGuiTableColumnFlags_WidthStretch, 0.2); + ImGui::TableSetupColumn("hex.welcome.plugins.author"_lang, ImGuiTableColumnFlags_WidthStretch, 0.2); + ImGui::TableSetupColumn("hex.welcome.plugins.desc"_lang, ImGuiTableColumnFlags_WidthStretch, 0.6); + ImGui::TableSetupColumn("##loaded", ImGuiTableColumnFlags_WidthFixed, ImGui::GetTextLineHeight()); ImGui::TableHeadersRow(); @@ -728,13 +729,17 @@ namespace hex { while (clipper.Step()) { for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { + const auto &plugin = plugins[i]; + ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::TextUnformatted((plugins[i].getPluginName() + " ").c_str()); + ImGui::TextUnformatted(plugin.getPluginName().c_str()); ImGui::TableNextColumn(); - ImGui::TextUnformatted((plugins[i].getPluginAuthor() + " ").c_str()); + ImGui::TextUnformatted(plugin.getPluginAuthor().c_str()); ImGui::TableNextColumn(); - ImGui::TextUnformatted(plugins[i].getPluginDescription().c_str()); + ImGui::TextUnformatted(plugin.getPluginDescription().c_str()); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(plugin.isLoaded() ? ICON_VS_CHECK : ICON_VS_CLOSE); } } diff --git a/plugins/windows/source/plugin_windows.cpp b/plugins/windows/source/plugin_windows.cpp index b7a791b45..846e56acc 100644 --- a/plugins/windows/source/plugin_windows.cpp +++ b/plugins/windows/source/plugin_windows.cpp @@ -15,7 +15,7 @@ namespace hex::plugin::windows { IMHEX_PLUGIN_SETUP("Windows", "WerWolv", "Windows-only features") { using namespace hex::plugin::windows; - ContentRegistry::Views::add(); + hex::ContentRegistry::Views::add(); registerLanguageEnUS(); registerLanguageZhCN();