From f9f8b6926a842f241edf7db6590af4b47a87bfd3 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 3 Jan 2023 14:16:42 +0200 Subject: [PATCH] Make it possible for plugins to require other plugins This is used to ensure correct ordering if one plugin customizes tools from another. --- source/lib/builder.cpp | 50 +++++++++++++++++++++++++++++++++++++++++- source/lib/builder.h | 1 + source/lib/plugin.h | 5 +++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/source/lib/builder.cpp b/source/lib/builder.cpp index 738361b..c8c7bf8 100644 --- a/source/lib/builder.cpp +++ b/source/lib/builder.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include "binarypackage.h" @@ -47,6 +48,7 @@ void Builder::load_plugins() FS::Path plugins_dir = FS::get_sys_lib_dir(); logger->log("files", "Traversing %s", plugins_dir); + vector unordered_plugins; for(const string &f: list_filtered(plugins_dir, "\\.dlm$")) { LoadedPlugin plugin; @@ -69,7 +71,7 @@ void Builder::load_plugins() if(plugin.plugin) { logger->log("plugins", "Loaded plugin %s", f); - plugins.emplace_back(move(plugin)); + unordered_plugins.emplace_back(move(plugin)); continue; } else @@ -80,6 +82,40 @@ void Builder::load_plugins() logger->log("plugins", "Failed to initialize plugin %s: %s", f, exc.what()); } } + + auto have_plugin = [this](const string &r){ + return any_of(plugins.begin(), plugins.end(), [&r](const LoadedPlugin &p){ return FS::basepart(FS::basename(p.path))==r; }); + }; + + while(!unordered_plugins.empty()) + { + bool any_added = false; + for(auto i=unordered_plugins.begin(); i!=unordered_plugins.end(); ) + { + const vector &required = i->plugin->get_required_plugins(); + if(all_of(required.begin(), required.end(), have_plugin)) + { + plugins.push_back(move(*i)); + i = unordered_plugins.erase(i); + any_added = true; + } + else + ++i; + } + + if(!any_added) + break; + } + + for(const LoadedPlugin &p: unordered_plugins) + { + vector missing; + for(const string &r: p.plugin->get_required_plugins()) + if(!have_plugin(r)) + missing.push_back(r); + logger->log("plugins", "Missing required plugins for plugin %s: %s", + FS::basename(p.path), join(missing.begin(), missing.end())); + } } void Builder::set_architecture(const string &name) @@ -374,6 +410,18 @@ Builder::LoadedPlugin::LoadedPlugin(LoadedPlugin &&other): other.plugin = 0; } +Builder::LoadedPlugin &Builder::LoadedPlugin::operator=(LoadedPlugin &&other) +{ + delete plugin; + delete module; + path = move(other.path); + module = other.module; + plugin = other.plugin; + other.module = 0; + other.plugin = 0; + return *this; +} + Builder::LoadedPlugin::~LoadedPlugin() { delete plugin; diff --git a/source/lib/builder.h b/source/lib/builder.h index 9845226..d9a942b 100644 --- a/source/lib/builder.h +++ b/source/lib/builder.h @@ -54,6 +54,7 @@ private: LoadedPlugin() = default; LoadedPlugin(LoadedPlugin &&); + LoadedPlugin &operator=(LoadedPlugin &&); ~LoadedPlugin(); }; diff --git a/source/lib/plugin.h b/source/lib/plugin.h index 1e79fca..19198a8 100644 --- a/source/lib/plugin.h +++ b/source/lib/plugin.h @@ -1,6 +1,8 @@ #ifndef PLUGIN_H_ #define PLUGIN_H_ +#include +#include #include "libbuilder_api.h" class Architecture; @@ -12,11 +14,14 @@ class LIBBUILDER_API Plugin { protected: Builder &builder; + std::vector required_plugins; Plugin(Builder &b): builder(b) { } public: virtual ~Plugin() = default; + const std::vector &get_required_plugins() const { return required_plugins; } + virtual void add_tools(Toolchain &, const Architecture &) const { } virtual void create_targets(SourcePackage &) const { } }; -- 2.45.2