From: Mikko Rasa Date: Wed, 28 Dec 2022 13:16:21 +0000 (+0200) Subject: Add an interface for dynamically loaded plugins X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=1dd53b56788697971f7aff08232aa91e610c3592;p=builder.git Add an interface for dynamically loaded plugins --- diff --git a/source/cli/buildercli.cpp b/source/cli/buildercli.cpp index cb0897c..9f8c895 100644 --- a/source/cli/buildercli.cpp +++ b/source/cli/buildercli.cpp @@ -87,6 +87,7 @@ BuilderCLI::BuilderCLI(int argc, char **argv): for(const string &p: split(c, ',')) logger.enable_channel(p); builder.set_logger(&logger); + builder.load_plugins(); if(!analyze_mode.empty()) { diff --git a/source/lib/builder.cpp b/source/lib/builder.cpp index 92924eb..72ee524 100644 --- a/source/lib/builder.cpp +++ b/source/lib/builder.cpp @@ -22,6 +22,7 @@ #include "installedfile.h" #include "msvc/microsofttools.h" #include "package.h" +#include "plugin.h" #include "sharedlibrary.h" #include "sourcepackage.h" #include "task.h" @@ -46,6 +47,49 @@ Builder::~Builder() delete current_arch; } +void Builder::load_plugins() +{ + using CreateFunc = Plugin *(Builder &); + + FS::Path plugins_dir = FS::get_sys_lib_dir(); + logger->log("files", "Traversing %s", plugins_dir); + for(const string &f: list_filtered(plugins_dir, "\\.dlm$")) + { + LoadedPlugin plugin; + plugin.path = plugins_dir/f; + + try + { + plugin.module = new Module(plugin.path.str()); + } + catch(const exception &exc) + { + logger->log("plugins", "Failed to load plugin %s: %s", f, exc.what()); + continue; + } + + try + { + CreateFunc *create_func = reinterpret_cast(plugin.module->get_symbol("create_plugin")); + plugin.plugin = create_func(*this); + if(plugin.plugin) + { + logger->log("plugins", "Loaded plugin %s", f); + plugins.emplace_back(move(plugin)); + continue; + } + else + logger->log("plugins", "Plugin %s refused to initialize", f); + } + catch(const exception &exc) + { + logger->log("plugins", "Failed to initialize plugin %s: %s", f, exc.what()); + } + + delete plugin.module; + } +} + void Builder::set_architecture(const string &name) { if(current_arch!=&native_arch) @@ -110,6 +154,8 @@ void Builder::add_default_tools() toolchain.add_toolchain(new MicrosoftTools(*this, *current_arch)); toolchain.add_toolchain(new BuiltinTools(*this)); toolchain.add_tool(new DataTool(*this)); + for(const LoadedPlugin &p: plugins) + p.plugin->add_tools(toolchain, *current_arch); auto i = find_if(toolchain.get_toolchains(), [](const Toolchain *tc){ return (tc->has_tool("CC") || tc->has_tool("CXX")); }); if(i!=toolchain.get_toolchains().end()) @@ -310,6 +356,22 @@ int Builder::clean(bool all, bool dry_run) } +Builder::LoadedPlugin::LoadedPlugin(LoadedPlugin &&other): + path(move(other.path)), + module(other.module), + plugin(other.plugin) +{ + other.module = 0; + other.plugin = 0; +} + +Builder::LoadedPlugin::~LoadedPlugin() +{ + delete plugin; + delete module; +} + + Builder::Loader::Loader(Builder &b, const Config::InputOptions *o, bool a): DataFile::ObjectLoader(b), options(o), diff --git a/source/lib/builder.h b/source/lib/builder.h index e06cec3..32d06a0 100644 --- a/source/lib/builder.h +++ b/source/lib/builder.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include "architecture.h" @@ -17,6 +18,7 @@ class FileTarget; class Package; +class Plugin; class SourcePackage; /** @@ -44,6 +46,18 @@ private: }; private: + struct LoadedPlugin + { + Msp::FS::Path path; + Msp::Module *module = nullptr; + Plugin *plugin = nullptr; + + LoadedPlugin() = default; + LoadedPlugin(LoadedPlugin &&); + ~LoadedPlugin(); + }; + + std::vector plugins; PackageManager package_manager; Architecture native_arch; @@ -66,6 +80,7 @@ public: Builder(); ~Builder(); + void load_plugins(); PackageManager &get_package_manager() { return package_manager; } void set_architecture(const std::string &); diff --git a/source/lib/plugin.h b/source/lib/plugin.h new file mode 100644 index 0000000..910e259 --- /dev/null +++ b/source/lib/plugin.h @@ -0,0 +1,20 @@ +#ifndef PLUGIN_H_ +#define PLUGIN_H_ + +class Architecture; +class Builder; +class Toolchain; + +class Plugin +{ +protected: + Builder &builder; + + Plugin(Builder &b): builder(b) { } +public: + virtual ~Plugin() = default; + + virtual void add_tools(Toolchain &, const Architecture &) const { } +}; + +#endif