diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index db9953d64..bc8f5fbdc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -371,6 +371,11 @@ jobs: ninja + - name: 🧪 Test if plugin can be loaded + run: | + export WORKSPACE=$(echo "${{ github.workspace }}" | tr '\\' '/') + ${WORKSPACE}/out/imhex.exe --validate-plugin ${WORKSPACE}/template/build/example_plugin.hexplug + # MacOS build macos-x86: runs-on: macos-13 diff --git a/lib/libimhex/include/hex/api/plugin_manager.hpp b/lib/libimhex/include/hex/api/plugin_manager.hpp index 8b3906df2..c74accf20 100644 --- a/lib/libimhex/include/hex/api/plugin_manager.hpp +++ b/lib/libimhex/include/hex/api/plugin_manager.hpp @@ -81,8 +81,9 @@ EXPORT_MODULE namespace hex { [[nodiscard]] const std::fs::path &getPath() const; - [[nodiscard]] bool isValid() const; [[nodiscard]] bool isLoaded() const; + [[nodiscard]] bool isValid() const; + [[nodiscard]] bool isInitialized() const; [[nodiscard]] std::span getSubCommands() const; [[nodiscard]] std::span getFeatures() const; diff --git a/lib/libimhex/source/api/plugin_manager.cpp b/lib/libimhex/source/api/plugin_manager.cpp index b7116a832..3ae50c886 100644 --- a/lib/libimhex/source/api/plugin_manager.cpp +++ b/lib/libimhex/source/api/plugin_manager.cpp @@ -202,11 +202,16 @@ namespace hex { return m_path; } - bool Plugin::isValid() const { - return m_handle != 0 || m_functions.initializeLibraryFunction != nullptr || m_functions.initializePluginFunction != nullptr; + bool Plugin::isLoaded() const { + return m_handle != 0; } - bool Plugin::isLoaded() const { + + bool Plugin::isValid() const { + return isLoaded() || m_functions.initializeLibraryFunction != nullptr || m_functions.initializePluginFunction != nullptr; + } + + bool Plugin::isInitialized() const { return m_initialized; } @@ -330,7 +335,7 @@ namespace hex { void PluginManager::initializeNewPlugins() { for (const auto &plugin : getPlugins()) { - if (!plugin.isLoaded()) + if (!plugin.isInitialized()) std::ignore = plugin.initializePlugin(); } } diff --git a/plugins/builtin/include/content/command_line_interface.hpp b/plugins/builtin/include/content/command_line_interface.hpp index 8c7b72bca..88d581a3e 100644 --- a/plugins/builtin/include/content/command_line_interface.hpp +++ b/plugins/builtin/include/content/command_line_interface.hpp @@ -27,7 +27,7 @@ namespace hex::plugin::builtin { void handleDemangleCommand(const std::vector &args); void handleSettingsResetCommand(const std::vector &args); void handleDebugModeCommand(const std::vector &args); - + void handleValidatePluginCommand(const std::vector &args); void registerCommandForwarders(); diff --git a/plugins/builtin/source/content/command_line_interface.cpp b/plugins/builtin/source/content/command_line_interface.cpp index 880a75c66..4d0df05f8 100644 --- a/plugins/builtin/source/content/command_line_interface.cpp +++ b/plugins/builtin/source/content/command_line_interface.cpp @@ -415,7 +415,37 @@ namespace hex::plugin::builtin { } void handleDebugModeCommand(const std::vector &) { - hex::dbg::setDebugModeEnabled(true); + dbg::setDebugModeEnabled(true); + } + + void handleValidatePluginCommand(const std::vector &args) { + if (args.size() != 1) { + log::println("usage: imhex --validate-plugin "); + std::exit(EXIT_FAILURE); + } + + log::resumeLogging(); + + const auto plugin = Plugin(args[0]); + + if (!plugin.isLoaded()) { + log::println("Plugin couldn't be loaded. Make sure the plugin was built using the SDK of this ImHex version!"); + std::exit(EXIT_FAILURE); + } + + if (!plugin.isValid()) { + log::println("Plugin is missing required init function! Make sure your plugin has a IMHEX_PLUGIN_SETUP or IMHEX_LIBRARY_SETUP block!"); + std::exit(EXIT_FAILURE); + } + + if (!plugin.initializePlugin()) { + log::println("An error occurred while trying to initialize the plugin. Check the logs for more information."); + std::exit(EXIT_FAILURE); + } + + log::println("Plugin is valid!"); + + std::exit(EXIT_SUCCESS); } diff --git a/plugins/builtin/source/content/views/view_about.cpp b/plugins/builtin/source/content/views/view_about.cpp index 8430c7db7..c7e8b87d1 100644 --- a/plugins/builtin/source/content/views/view_about.cpp +++ b/plugins/builtin/source/content/views/view_about.cpp @@ -444,7 +444,7 @@ namespace hex::plugin::builtin { ImGui::TableNextColumn(); ImGui::TextUnformatted(plugin.getPluginDescription().c_str()); ImGui::TableNextColumn(); - ImGui::TextUnformatted(plugin.isLoaded() ? ICON_VS_CHECK : ICON_VS_CLOSE); + ImGui::TextUnformatted(plugin.isInitialized() ? ICON_VS_CHECK : ICON_VS_CLOSE); if (open) { for (const auto &feature : plugin.getFeatures()) { diff --git a/plugins/builtin/source/plugin_builtin.cpp b/plugins/builtin/source/plugin_builtin.cpp index 222ababb5..029639b26 100644 --- a/plugins/builtin/source/plugin_builtin.cpp +++ b/plugins/builtin/source/plugin_builtin.cpp @@ -62,28 +62,29 @@ namespace hex::plugin::builtin { } IMHEX_PLUGIN_SUBCOMMANDS() { - { "help", "h", "Print help about this command", hex::plugin::builtin::handleHelpCommand }, - { "version", "", "Print ImHex version", hex::plugin::builtin::handleVersionCommand }, - { "version-short", "", "Print only the version info in plain text", hex::plugin::builtin::handleVersionShortCommand }, - { "plugins", "", "Lists all plugins that have been installed", hex::plugin::builtin::handlePluginsCommand }, - { "language", "", "Changes the language ImHex uses", hex::plugin::builtin::handleLanguageCommand }, - { "verbose", "v", "Enables verbose debug logging", hex::plugin::builtin::handleVerboseCommand }, + { "help", "h", "Print help about this command", hex::plugin::builtin::handleHelpCommand }, + { "version", "", "Print ImHex version", hex::plugin::builtin::handleVersionCommand }, + { "version-short", "", "Print only the version info in plain text", hex::plugin::builtin::handleVersionShortCommand }, + { "plugins", "", "Lists all plugins that have been installed", hex::plugin::builtin::handlePluginsCommand }, + { "language", "", "Changes the language ImHex uses", hex::plugin::builtin::handleLanguageCommand }, + { "verbose", "v", "Enables verbose debug logging", hex::plugin::builtin::handleVerboseCommand }, - { "open", "o", "Open files passed as argument. [default]", hex::plugin::builtin::handleOpenCommand }, - { "new", "n", "Create a new empty file", hex::plugin::builtin::handleNewCommand }, + { "open", "o", "Open files passed as argument. [default]", hex::plugin::builtin::handleOpenCommand }, + { "new", "n", "Create a new empty file", hex::plugin::builtin::handleNewCommand }, - { "select", "", "Select a range of bytes in the Hex Editor", hex::plugin::builtin::handleSelectCommand }, - { "pattern", "", "Sets the loaded pattern", hex::plugin::builtin::handlePatternCommand }, - { "calc", "", "Evaluate a mathematical expression", hex::plugin::builtin::handleCalcCommand }, - { "hash", "", "Calculate the hash of a file", hex::plugin::builtin::handleHashCommand }, - { "encode", "", "Encode a string", hex::plugin::builtin::handleEncodeCommand }, - { "decode", "", "Decode a string", hex::plugin::builtin::handleDecodeCommand }, - { "magic", "", "Identify file types", hex::plugin::builtin::handleMagicCommand }, - { "pl", "", "Interact with the pattern language", hex::plugin::builtin::handlePatternLanguageCommand, SubCommand::Type::SubCommand }, - { "hexdump", "", "Generate a hex dump of the provided file", hex::plugin::builtin::handleHexdumpCommand }, - { "demangle", "", "Demangle a mangled symbol", hex::plugin::builtin::handleDemangleCommand }, - { "reset-settings", "", "Resets all settings back to default", hex::plugin::builtin::handleSettingsResetCommand }, - { "debug-mode", "", "Enables debugging features", hex::plugin::builtin::handleDebugModeCommand, } + { "select", "", "Select a range of bytes in the Hex Editor", hex::plugin::builtin::handleSelectCommand }, + { "pattern", "", "Sets the loaded pattern", hex::plugin::builtin::handlePatternCommand }, + { "calc", "", "Evaluate a mathematical expression", hex::plugin::builtin::handleCalcCommand }, + { "hash", "", "Calculate the hash of a file", hex::plugin::builtin::handleHashCommand }, + { "encode", "", "Encode a string", hex::plugin::builtin::handleEncodeCommand }, + { "decode", "", "Decode a string", hex::plugin::builtin::handleDecodeCommand }, + { "magic", "", "Identify file types", hex::plugin::builtin::handleMagicCommand }, + { "pl", "", "Interact with the pattern language", hex::plugin::builtin::handlePatternLanguageCommand, SubCommand::Type::SubCommand }, + { "hexdump", "", "Generate a hex dump of the provided file", hex::plugin::builtin::handleHexdumpCommand }, + { "demangle", "", "Demangle a mangled symbol", hex::plugin::builtin::handleDemangleCommand }, + { "reset-settings", "", "Resets all settings back to default", hex::plugin::builtin::handleSettingsResetCommand }, + { "debug-mode", "", "Enables debugging features", hex::plugin::builtin::handleDebugModeCommand, }, + { "validate-plugin", "", "Validates that a plugin can be loaded", hex::plugin::builtin::handleValidatePluginCommand } }; IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") {