]> git.tdb.fi Git - builder.git/commitdiff
Allow new component types to be registered at runtime
authorMikko Rasa <tdb@tdb.fi>
Wed, 28 Dec 2022 15:35:15 +0000 (17:35 +0200)
committerMikko Rasa <tdb@tdb.fi>
Wed, 28 Dec 2022 15:45:36 +0000 (17:45 +0200)
source/lib/builder.cpp
source/lib/builder.h
source/lib/sourcepackage.cpp
source/lib/sourcepackage.h

index 53b9efbae40af0f318f288e0f9c023ead71fd31e..1535c3e948bf3a1cd7042649347bd3feb8b5d81f 100644 (file)
@@ -20,7 +20,6 @@
 #include "package.h"
 #include "plugin.h"
 #include "sharedlibrary.h"
-#include "sourcepackage.h"
 #include "task.h"
 #include "virtualtarget.h"
 
index 0455637c9ca96808de0ebff64e3c4519dd0b5ac9..6dc29f098d2a22a714594c4dab1262de2a65df72 100644 (file)
@@ -12,6 +12,7 @@
 #include "config.h"
 #include "logger.h"
 #include "packagemanager.h"
+#include "sourcepackage.h"
 #include "target.h"
 #include "toolchain.h"
 #include "virtualfilesystem.h"
@@ -19,7 +20,6 @@
 class FileTarget;
 class Package;
 class Plugin;
-class SourcePackage;
 
 /**
 This class ties everything else together.  It also contains code for loading
@@ -59,6 +59,7 @@ private:
 
        std::vector<LoadedPlugin> plugins;
        PackageManager package_manager;
+       SourcePackage::ComponentRegistry component_registry;
 
        Architecture native_arch;
        Architecture *current_arch = 0;
@@ -82,6 +83,7 @@ public:
 
        void load_plugins();
        PackageManager &get_package_manager() { return package_manager; }
+       SourcePackage::ComponentRegistry &get_component_registry() { return component_registry; }
 
        template<typename F>
        void call_plugins(F) const;
index dfbf16e92553737e9aa9a333db5b5a4a13d048e0..6261d2c844ba42fbdb283bf5e56ed8a4ec88cef1 100644 (file)
@@ -170,6 +170,8 @@ SourcePackage::Loader::Loader(SourcePackage &p, const Config::InputOptions *o):
        add("source_tarball", &Loader::source_archive);
        add("tarball",     &Loader::tarball);
        add("version",     &Loader::version);
+
+       p.builder.get_component_registry().invoke_all(*this);
 }
 
 void SourcePackage::Loader::finish()
@@ -200,16 +202,6 @@ void SourcePackage::Loader::feature(const string &n, const string &d)
        }
 }
 
-template<typename C, typename... Args>
-void SourcePackage::Loader::component(Args... args, const string &n)
-{
-       if(any_of(obj.components.begin(), obj.components.end(), [&n](const Component *c){ return c->get_name()==n; }))
-               throw key_error(n);
-       C *comp = new C(obj, n, args...);
-       load_sub(*comp);
-       obj.components.push_back(comp);
-}
-
 void SourcePackage::Loader::build_info()
 {
        load_sub(obj.build_info);
index d37ecf4a8a7e356d3d1b45f4566df605c8b77093..2c2e57c70a4503e8f21ad980cda88ac1e84f935e 100644 (file)
@@ -1,8 +1,10 @@
 #ifndef SOURCEPACKAGE_H_
 #define SOURCEPACKAGE_H_
 
+#include <algorithm>
 #include <stdexcept>
 #include <string>
+#include <msp/core/typeregistry.h>
 #include "buildinfo.h"
 #include "cache.h"
 #include "component.h"
@@ -25,7 +27,15 @@ class SourcePackage: public Package
 public:
        class Loader: public Msp::DataFile::DerivedObjectLoader<SourcePackage, Package::Loader>, public FeatureConditional
        {
+               friend class SourcePackage;
+
        private:
+               template<typename T>
+               struct AddComponent
+               {
+                       void operator()(const std::string &n, Loader &l) const { l.add(n, &Loader::component<T>); }
+               };
+
                const Config::InputOptions *options;
 
        public:
@@ -44,6 +54,8 @@ public:
                void version(const std::string &);
        };
 
+       using ComponentRegistry = Msp::TypeRegistry<Loader::AddComponent, Loader &>;
+
 private:
        std::string version;
        std::string interface_version;
@@ -88,4 +100,15 @@ private:
        void save_caches() override;
 };
 
+
+template<typename C, typename... Args>
+void SourcePackage::Loader::component(Args... args, const std::string &n)
+{
+       if(std::any_of(obj.components.begin(), obj.components.end(), [&n](const Component *c){ return c->get_name()==n; }))
+               throw Msp::key_error(n);
+       C *comp = new C(obj, n, args...);
+       load_sub(*comp);
+       obj.components.push_back(comp);
+}
+
 #endif