1
0
mirror of synced 2024-11-12 10:10:53 +01:00

build/plugin: Make plugins no longer depend on their file name

This commit is contained in:
WerWolv 2022-01-23 23:28:56 +01:00
parent b3a8d02d19
commit 541c0d7547
6 changed files with 85 additions and 53 deletions

View File

@ -16,15 +16,25 @@ macro(addVersionDefines)
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
) )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGIT_COMMIT_HASH=\"\\\"${GIT_COMMIT_HASH}\"\\\"") add_compile_definitions(GIT_COMMIT_HASH="${GIT_COMMIT_HASH}" GIT_BRANCH="${GIT_BRANCH}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGIT_BRANCH=\"\\\"${GIT_BRANCH}\"\\\"") endif ()
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_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\"\\\"") add_compile_definitions(
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DRELEASE -DIMHEX_VERSION=\"\\\"${PROJECT_VERSION}-ReleaseWithDebugInfo\"\\\"") $<$<CONFIG:Release>:IMHEX_VERSION="${PROJECT_VERSION}">
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -DRELEASE -DIMHEX_VERSION=\"\\\"${PROJECT_VERSION}-ReleaseMinimumSize\"\\\"") $<$<CONFIG:Debug>:IMHEX_VERSION="${PROJECT_VERSION}-Debug">
$<$<CONFIG:RelWithDebInfo>:IMHEX_VERSION="${PROJECT_VERSION}-ReleaseWithDebugInfo">
$<$<CONFIG:MinSizeRel>:IMHEX_VERSION="${PROJECT_VERSION}-ReleaseMinimumSize">
)
add_compile_definitions(
$<$<CONFIG:Release>:RELEASE>
$<$<CONFIG:Debug>:DEBUG>
$<$<CONFIG:RelWithDebInfo>:RELEASE>
$<$<CONFIG:MinSizeRel>:RELEASE>
)
endmacro() endmacro()
macro(configurePython) macro(configurePython)
@ -49,30 +59,30 @@ macro(configurePython)
endif () endif ()
list(JOIN PYTHON_VERSION_MAJOR_MINOR "." PYTHON_VERSION_MAJOR_MINOR) 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() endmacro()
# Detect current OS / System # Detect current OS / System
macro(detectOS) macro(detectOS)
if (WIN32) if (WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOS_WINDOWS") add_compile_definitions(OS_WINDOWS)
set(CMAKE_INSTALL_BINDIR ".") set(CMAKE_INSTALL_BINDIR ".")
set(CMAKE_INSTALL_LIBDIR ".") set(CMAKE_INSTALL_LIBDIR ".")
set(PLUGINS_INSTALL_LOCATION "plugins") set(PLUGINS_INSTALL_LOCATION "plugins")
set(MAGIC_INSTALL_LOCATION "magic") set(MAGIC_INSTALL_LOCATION "magic")
elseif(APPLE) elseif (APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOS_MACOS") add_compile_definitions(OS_MACOS)
set(CMAKE_INSTALL_BINDIR ".") set(CMAKE_INSTALL_BINDIR ".")
set(CMAKE_INSTALL_LIBDIR ".") set(CMAKE_INSTALL_LIBDIR ".")
set(PLUGINS_INSTALL_LOCATION "plugins") set(PLUGINS_INSTALL_LOCATION "plugins")
set(MAGIC_INSTALL_LOCATION "magic") set(MAGIC_INSTALL_LOCATION "magic")
elseif(UNIX AND NOT APPLE) elseif (UNIX AND NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOS_LINUX") add_compile_definitions(OS_LINUX)
set(CMAKE_INSTALL_BINDIR "bin") set(CMAKE_INSTALL_BINDIR "bin")
set(CMAKE_INSTALL_LIBDIR "lib") set(CMAKE_INSTALL_LIBDIR "lib")
set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins") set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins")
set(MAGIC_INSTALL_LOCATION "share/imhex/magic") set(MAGIC_INSTALL_LOCATION "share/imhex/magic")
else() else ()
message(FATAL_ERROR "Unknown / unsupported system!") message(FATAL_ERROR "Unknown / unsupported system!")
endif() endif()
endmacro() endmacro()
@ -80,9 +90,9 @@ endmacro()
# Detect 32 vs. 64 bit system # Detect 32 vs. 64 bit system
macro(detectArch) macro(detectArch)
if(CMAKE_SIZEOF_VOID_P EQUAL 8) 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) elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DARCH_32_BIT") add_compile_definitions(ARCH_32_BIT)
endif() endif()
endmacro() endmacro()

View File

@ -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(name, author, description) IMHEX_PLUGIN_SETUP_IMPL(IMHEX_PLUGIN_NAME, name, author, description)
#define IMHEX_PLUGIN_SETUP_IMPL(namespaceName, name, author, description) \ #define IMHEX_PLUGIN_SETUP_IMPL(namespaceName, name, author, description) \
namespace hex::plugin::namespaceName::internal { \ extern "C" [[gnu::visibility("default")]] const char* getPluginName() { return name; } \
[[gnu::visibility("default")]] void initializePlugin(); \ extern "C" [[gnu::visibility("default")]] const char* getPluginAuthor() { return author; } \
\ extern "C" [[gnu::visibility("default")]] const char* getPluginDescription() { return description; } \
[[gnu::visibility("default")]] const char* getPluginName() { return name; } \ extern "C" [[gnu::visibility("default")]] const char* getCompatibleVersion() { return IMHEX_VERSION; } \
[[gnu::visibility("default")]] const char* getPluginAuthor() { return author; } \ extern "C" [[gnu::visibility("default")]] void setImGuiContext(ImGuiContext *ctx) { ImGui::SetCurrentContext(ctx); GImGui = ctx; } \
[[gnu::visibility("default")]] const char* getPluginDescription() { return description; } \ extern "C" [[gnu::visibility("default")]] void initializePlugin()
[[gnu::visibility("default")]] void setImGuiContext(ImGuiContext *ctx) { ImGui::SetCurrentContext(ctx); GImGui = ctx; } \
} \
void hex::plugin::namespaceName::internal::initializePlugin()

View File

@ -22,33 +22,39 @@ namespace hex {
[[nodiscard]] std::string getPluginName() const; [[nodiscard]] std::string getPluginName() const;
[[nodiscard]] std::string getPluginAuthor() const; [[nodiscard]] std::string getPluginAuthor() const;
[[nodiscard]] std::string getPluginDescription() const; [[nodiscard]] std::string getPluginDescription() const;
[[nodiscard]] std::string getCompatibleVersion() const;
void setImGuiContext(ImGuiContext *ctx) const; void setImGuiContext(ImGuiContext *ctx) const;
[[nodiscard]] const fs::path& getPath() const; [[nodiscard]] const fs::path& getPath() const;
[[nodiscard]] bool isLoaded() const;
private: private:
using InitializePluginFunc = void(*)(); using InitializePluginFunc = void(*)();
using GetPluginNameFunc = const char*(*)(); using GetPluginNameFunc = const char*(*)();
using GetPluginAuthorFunc = const char*(*)(); using GetPluginAuthorFunc = const char*(*)();
using GetPluginDescriptionFunc = const char*(*)(); using GetPluginDescriptionFunc = const char*(*)();
using GetCompatibleVersionFunc = const char*(*)();
using SetImGuiContextFunc = void(*)(ImGuiContext*); using SetImGuiContextFunc = void(*)(ImGuiContext*);
void *m_handle = nullptr; void *m_handle = nullptr;
fs::path m_path; fs::path m_path;
mutable bool m_initialized = false;
InitializePluginFunc m_initializePluginFunction = nullptr; InitializePluginFunc m_initializePluginFunction = nullptr;
GetPluginNameFunc m_getPluginNameFunction = nullptr; GetPluginNameFunc m_getPluginNameFunction = nullptr;
GetPluginAuthorFunc m_getPluginAuthorFunction = nullptr; GetPluginAuthorFunc m_getPluginAuthorFunction = nullptr;
GetPluginDescriptionFunc m_getPluginDescriptionFunction = nullptr; GetPluginDescriptionFunc m_getPluginDescriptionFunction = nullptr;
GetCompatibleVersionFunc m_getCompatibleVersionFunction = nullptr;
SetImGuiContextFunc m_setImGuiContextFunction = nullptr; SetImGuiContextFunc m_setImGuiContextFunction = nullptr;
template<typename T> template<typename T>
[[nodiscard]] auto getPluginFunction(const std::string &pluginName, const std::string &symbol) { [[nodiscard]] auto getPluginFunction(const std::string &symbol) {
return reinterpret_cast<T>(this->getPluginFunction(pluginName, symbol)); return reinterpret_cast<T>(this->getPluginFunction(symbol));
} }
private: private:
[[nodiscard]] void* getPluginFunction(const std::string &pluginName, const std::string &symbol); [[nodiscard]] void* getPluginFunction(const std::string &symbol);
}; };
class PluginManager { class PluginManager {

View File

@ -7,13 +7,6 @@
namespace hex { namespace hex {
// hex::plugin::<pluginName>::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) { Plugin::Plugin(const fs::path &path) : m_path(path) {
this->m_handle = dlopen(path.string().c_str(), RTLD_LAZY); this->m_handle = dlopen(path.string().c_str(), RTLD_LAZY);
@ -24,11 +17,12 @@ namespace hex {
auto pluginName = fs::path(path).stem().string(); auto pluginName = fs::path(path).stem().string();
this->m_initializePluginFunction = getPluginFunction<InitializePluginFunc>(pluginName, InitializePluginSymbol); this->m_initializePluginFunction = getPluginFunction<InitializePluginFunc>("initializePlugin");
this->m_getPluginNameFunction = getPluginFunction<GetPluginNameFunc>(pluginName, GetPluginNameSymbol); this->m_getPluginNameFunction = getPluginFunction<GetPluginNameFunc>("getPluginName");
this->m_getPluginAuthorFunction = getPluginFunction<GetPluginAuthorFunc>(pluginName, GetPluginAuthorSymbol); this->m_getPluginAuthorFunction = getPluginFunction<GetPluginAuthorFunc>("getPluginAuthor");
this->m_getPluginDescriptionFunction = getPluginFunction<GetPluginDescriptionFunc>(pluginName, GetPluginDescriptionSymbol); this->m_getPluginDescriptionFunction = getPluginFunction<GetPluginDescriptionFunc>("getPluginDescription");
this->m_setImGuiContextFunction = getPluginFunction<SetImGuiContextFunc>(pluginName, SetImGuiContextSymbol); this->m_getCompatibleVersionFunction = getPluginFunction<GetCompatibleVersionFunc>("getCompatibleVersion");
this->m_setImGuiContextFunction = getPluginFunction<SetImGuiContextFunc>("setImGuiContext");
} }
Plugin::Plugin(Plugin &&other) noexcept { Plugin::Plugin(Plugin &&other) noexcept {
@ -39,6 +33,7 @@ namespace hex {
this->m_getPluginNameFunction = other.m_getPluginNameFunction; this->m_getPluginNameFunction = other.m_getPluginNameFunction;
this->m_getPluginAuthorFunction = other.m_getPluginAuthorFunction; this->m_getPluginAuthorFunction = other.m_getPluginAuthorFunction;
this->m_getPluginDescriptionFunction = other.m_getPluginDescriptionFunction; this->m_getPluginDescriptionFunction = other.m_getPluginDescriptionFunction;
this->m_getCompatibleVersionFunction = other.m_getCompatibleVersionFunction;
this->m_setImGuiContextFunction = other.m_setImGuiContextFunction; this->m_setImGuiContextFunction = other.m_setImGuiContextFunction;
other.m_handle = nullptr; other.m_handle = nullptr;
@ -46,6 +41,7 @@ namespace hex {
other.m_getPluginNameFunction = nullptr; other.m_getPluginNameFunction = nullptr;
other.m_getPluginAuthorFunction = nullptr; other.m_getPluginAuthorFunction = nullptr;
other.m_getPluginDescriptionFunction = nullptr; other.m_getPluginDescriptionFunction = nullptr;
other.m_getCompatibleVersionFunction = nullptr;
other.m_setImGuiContextFunction = nullptr; other.m_setImGuiContextFunction = nullptr;
} }
@ -55,12 +51,20 @@ namespace hex {
} }
bool Plugin::initializePlugin() const { 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) { if (this->m_initializePluginFunction != nullptr) {
this->m_initializePluginFunction(); this->m_initializePluginFunction();
return true;
} else { } else {
return false; return false;
} }
this->m_initialized = true;
return true;
} }
std::string Plugin::getPluginName() const { std::string Plugin::getPluginName() const {
@ -84,6 +88,13 @@ namespace hex {
return ""; return "";
} }
std::string Plugin::getCompatibleVersion() const {
if (this->m_getCompatibleVersionFunction != nullptr)
return this->m_getCompatibleVersionFunction();
else
return "";
}
void Plugin::setImGuiContext(ImGuiContext *ctx) const { void Plugin::setImGuiContext(ImGuiContext *ctx) const {
if (this->m_setImGuiContextFunction != nullptr) if (this->m_setImGuiContextFunction != nullptr)
this->m_setImGuiContextFunction(ctx); this->m_setImGuiContextFunction(ctx);
@ -93,12 +104,15 @@ namespace hex {
return this->m_path; return this->m_path;
} }
void* Plugin::getPluginFunction(const std::string &pluginName, const std::string &symbol) { bool Plugin::isLoaded() const {
auto symbolName = hex::format(symbol.data(), pluginName.length(), pluginName.data()); return this->m_initialized;
return dlsym(this->m_handle, symbolName.c_str());
} }
void* Plugin::getPluginFunction(const std::string &symbol) {
return dlsym(this->m_handle, symbol.c_str());
}
bool PluginManager::load(const fs::path &pluginFolder) { bool PluginManager::load(const fs::path &pluginFolder) {
if (!fs::exists(pluginFolder)) if (!fs::exists(pluginFolder))

View File

@ -715,11 +715,12 @@ namespace hex {
const auto &plugins = PluginManager::getPlugins(); const auto &plugins = PluginManager::getPlugins();
if (!plugins.empty()) { 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::TableSetupScrollFreeze(0, 1);
ImGui::TableSetupColumn("hex.welcome.plugins.plugin"_lang); ImGui::TableSetupColumn("hex.welcome.plugins.plugin"_lang, ImGuiTableColumnFlags_WidthStretch, 0.2);
ImGui::TableSetupColumn("hex.welcome.plugins.author"_lang); ImGui::TableSetupColumn("hex.welcome.plugins.author"_lang, ImGuiTableColumnFlags_WidthStretch, 0.2);
ImGui::TableSetupColumn("hex.welcome.plugins.desc"_lang); ImGui::TableSetupColumn("hex.welcome.plugins.desc"_lang, ImGuiTableColumnFlags_WidthStretch, 0.6);
ImGui::TableSetupColumn("##loaded", ImGuiTableColumnFlags_WidthFixed, ImGui::GetTextLineHeight());
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
@ -728,13 +729,17 @@ namespace hex {
while (clipper.Step()) { while (clipper.Step()) {
for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
const auto &plugin = plugins[i];
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted((plugins[i].getPluginName() + " ").c_str()); ImGui::TextUnformatted(plugin.getPluginName().c_str());
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted((plugins[i].getPluginAuthor() + " ").c_str()); ImGui::TextUnformatted(plugin.getPluginAuthor().c_str());
ImGui::TableNextColumn(); 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);
} }
} }

View File

@ -15,7 +15,7 @@ namespace hex::plugin::windows {
IMHEX_PLUGIN_SETUP("Windows", "WerWolv", "Windows-only features") { IMHEX_PLUGIN_SETUP("Windows", "WerWolv", "Windows-only features") {
using namespace hex::plugin::windows; using namespace hex::plugin::windows;
ContentRegistry::Views::add<ViewTTYConsole>(); hex::ContentRegistry::Views::add<ViewTTYConsole>();
registerLanguageEnUS(); registerLanguageEnUS();
registerLanguageZhCN(); registerLanguageZhCN();