]> git.tdb.fi Git - builder.git/commitdiff
Add helper functions to process sources in a uniform way
authorMikko Rasa <tdb@tdb.fi>
Fri, 15 Sep 2023 18:54:54 +0000 (21:54 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 15 Sep 2023 19:13:02 +0000 (22:13 +0300)
13 files changed:
plugins/android/androidassetpackagingtool.cpp
plugins/android/apkbuilder.cpp
plugins/base/copy.cpp
plugins/datafile/datatool.cpp
plugins/gnu/gnuarchiver.cpp
plugins/gnu/gnucompiler.cpp
plugins/gnu/gnulinker.cpp
plugins/gnu/mingwdlltool.cpp
plugins/msvc/msvcarchiver.cpp
plugins/msvc/msvccompiler.cpp
plugins/msvc/msvclinker.cpp
source/lib/tool.cpp
source/lib/tool.h

index ba321cb6fceb28e0a43918b6471accb411c6c251..da6a0a247311c8aa75db2f509e56f8e497088db1 100644 (file)
@@ -31,17 +31,7 @@ Target *AndroidAssetPackagingTool::create_target(const vector<Target *> &sources
 {
        AndroidManifestFile *manifest = 0;
        vector<FileTarget *> resources;
-       resources.reserve(sources.size());
-       for(Target *s: sources)
-       {
-               if(AndroidManifestFile *m = dynamic_cast<AndroidManifestFile *>(s))
-                       manifest = m;
-               else if(FileTarget *f = dynamic_cast<FileTarget *>(s))
-                       resources.push_back(f);
-       }
-
-       if(!manifest)
-               throw invalid_argument("AndroidAssetPackagingTool::create_target");
+       extract_sources(sources, required(manifest), resources);
 
        AndroidResourceBundle *res = new AndroidResourceBundle(builder, *manifest->get_component(), *manifest, resources);
        res->set_tool(*this);
index ec208543ef848d4cc6781292d513e226d486f32b..b262d1833215ec8778f7bdd8a58853b55bc793ef 100644 (file)
@@ -25,14 +25,8 @@ Target *ApkBuilder::create_target(const vector<Target *> &sources, const string
 {
        AndroidResourceBundle *resource_bundle = 0;
        vector<FileTarget *> other_files;
-       other_files.reserve(sources.size());
-       for(Target *s: sources)
-       {
-               if(AndroidResourceBundle *r = dynamic_cast<AndroidResourceBundle *>(s))
-                       resource_bundle = r;
-               else if(FileTarget *f = dynamic_cast<FileTarget *>(s))
-                       other_files.push_back(f);
-       }
+       extract_sources(sources, required(resource_bundle), other_files);
+
        AndroidPackageFile *apk = new AndroidPackageFile(builder, *resource_bundle->get_component(), *resource_bundle, other_files);
        apk->set_tool(*this);
        return apk;
index 0633ff9705edefea62071cf5b995f4df09c5c5e8..0a82d3873b4342097a288d7c8e19ae049eb15178 100644 (file)
@@ -22,8 +22,10 @@ Copy::Copy(Builder &b):
 
 Target *Copy::create_target(const vector<Target *> &sources, const string &arg)
 {
-       FileTarget &file_tgt = dynamic_cast<FileTarget &>(*sources.front());
-       InstalledFile *inst = new InstalledFile(builder, *file_tgt.get_package(), file_tgt, arg);
+       FileTarget *file_tgt = 0;
+       extract_sources(sources, required(file_tgt));
+
+       InstalledFile *inst = new InstalledFile(builder, *file_tgt->get_package(), *file_tgt, arg);
        inst->set_tool(*this);
        return inst;
 }
index 04592e35106aec8149f16ee17bd5d4b0aed13a14..71a7768a6c0856c445dce0e2346494eca45c4339 100644 (file)
@@ -29,21 +29,18 @@ Target *DataTool::create_target(const vector<Target *> &sources, const string &a
 {
        if(arg=="collection")
        {
-               if(sources.size()!=1)
-                       throw invalid_argument("DataTool::create_target");
-               DataTransform &source = dynamic_cast<DataTransform &>(*sources.front());
-               DataCollection *coll = new DataCollection(builder, *source.get_component(), source);
+               DataTransform *source = 0;
+               extract_sources(sources, required(source));
+
+               DataCollection *coll = new DataCollection(builder, *source->get_component(), *source);
                coll->set_tool(*this);
                return coll;
        }
        else if(arg=="pack")
        {
-               if(sources.empty())
-                       throw invalid_argument("DataTool::create_target");
                vector<FileTarget *> files;
-               files.reserve(sources.size());
-               for(Target *t: sources)
-                       files.push_back(&dynamic_cast<FileTarget &>(*t));
+               extract_sources(sources, required(files));
+
                DataPack *pack = new DataPack(builder, *files.front()->get_component(), files);
                pack->set_tool(*this);
                return pack;
index c977eaa7ee057c41ae10f422e349d07b50270572..4f216749e2c85f121ce369a861da5ba380654327 100644 (file)
@@ -22,13 +22,8 @@ GnuArchiver::GnuArchiver(Builder &b, const Architecture &a):
 
 Target *GnuArchiver::create_target(const vector<Target *> &sources, const string &)
 {
-       if(sources.empty())
-               throw invalid_argument("GnuArchiver::create_target");
-
        vector<ObjectFile *> objs;
-       objs.reserve(sources.size());
-       for(Target *s: sources)
-               objs.push_back(&dynamic_cast<ObjectFile &>(*s));
+       extract_sources(sources, required(objs));
 
        const Component &comp = *objs.front()->get_component();
        StaticLibrary *lib = new StaticLibrary(builder, comp, objs);
index 252f394b42753b1f937b6a49de8f14044395b55e..5e89a4eb24d7a99ff5ba9913eb62eb6d50400bf0 100644 (file)
@@ -70,10 +70,10 @@ Target *GnuCompiler::create_source(const FS::Path &path) const
 
 Target *GnuCompiler::create_target(const vector<Target *> &sources, const string &)
 {
-       if(sources.size()!=1)
-               throw invalid_argument("GnuCompiler::create_target");
-       SourceFile &source = dynamic_cast<SourceFile &>(*sources.front());
-       ObjectFile *obj = new ObjectFile(builder, *source.get_component(), source);
+       SourceFile *source = 0;
+       extract_sources(sources, required(source));
+
+       ObjectFile *obj = new ObjectFile(builder, *source->get_component(), *source);
        obj->set_tool(*this);
        return obj;
 }
index 3d81fcca6156236a58d9f943dc05136eb1d8ff9b..95e74fdc0aa314087c953f8be5aaac0db429a84a 100644 (file)
@@ -35,25 +35,20 @@ GnuLinker::GnuLinker(Builder &b, const Architecture &a):
 
 Target *GnuLinker::create_target(const vector<Target *> &sources, const string &arg)
 {
-       if(sources.empty())
-               throw invalid_argument("GnuLinker::create_target");
-
        if(arg=="import")
        {
-               if(sources.size()!=1)
-                       throw invalid_argument("GnuLinker::create_target");
-               SharedLibrary &shlib = dynamic_cast<SharedLibrary &>(*sources.front());
+               SharedLibrary *shlib = 0;
+               extract_sources(sources, required(shlib));
+
                if(architecture->get_system()!="windows")
                        return 0;
 
                Tool &dlltool = builder.get_toolchain().get_tool("DLL");
-               return dlltool.create_target(shlib);
+               return dlltool.create_target(*shlib);
        }
 
        vector<ObjectFile *> objs;
-       objs.reserve(sources.size());
-       for(Target *s: sources)
-               objs.push_back(&dynamic_cast<ObjectFile &>(*s));
+       extract_sources(sources, required(objs));
 
        const Component &comp = *objs.front()->get_component();
        Binary *bin = 0;
index a3fdadbe3d8bb64e40b870d8b0efc22d7407d78b..bf869cc99823f5356c7024e4974223840ea750e9 100644 (file)
@@ -24,20 +24,20 @@ MingwDllTool::MingwDllTool(Builder &b, const Architecture &a):
 
 Target *MingwDllTool::create_target(const vector<Target *> &sources, const string &)
 {
-       if(sources.size()!=1)
-               throw invalid_argument("MingwDllTool::create_target");
-       SharedLibrary &shlib = dynamic_cast<SharedLibrary &>(*sources.front());
+       SharedLibrary *shlib = 0;
+       extract_sources(sources, required(shlib));
 
        vector<ObjectFile *> objs;
-       objs.reserve(shlib.get_dependencies().size());
-       for(Target *d: shlib.get_dependencies())
-               if(ObjectFile *obj = dynamic_cast<ObjectFile *>(d))
-                       objs.push_back(obj);
+       ExportDefinitions *exp = 0;
+       extract_sources(shlib->get_dependencies(), objs, exp);
 
-       ExportDefinitions *exp = new ExportDefinitions(builder, *shlib.get_component(), objs);
-       exp->set_tool(*this);
+       if(!exp)
+       {
+               exp = new ExportDefinitions(builder, *shlib->get_component(), objs);
+               exp->set_tool(*this);
+       }
 
-       ImportLibrary *imp = new ImportLibrary(builder, *shlib.get_component(), shlib);
+       ImportLibrary *imp = new ImportLibrary(builder, *shlib->get_component(), *shlib);
        imp->add_dependency(*exp);
        imp->set_tool(*this);
 
index 2434eebf6d2343d611a819a6ed1ccd56d291f384..b8d3d1916d5382f83337be4f9ad61300c71a5b7c 100644 (file)
@@ -21,13 +21,8 @@ MsvcArchiver::MsvcArchiver(Builder &b, const Architecture &a, const MicrosoftToo
 
 Target *MsvcArchiver::create_target(const vector<Target *> &sources, const string &)
 {
-       if(sources.empty())
-               throw invalid_argument("MsvcArchiver::create_target");
-
        vector<ObjectFile *> objs;
-       objs.reserve(sources.size());
-       for(Target *s: sources)
-               objs.push_back(&dynamic_cast<ObjectFile &>(*s));
+       extract_sources(sources, required(objs));
 
        const Component &comp = *objs.front()->get_component();
        StaticLibrary *lib = new StaticLibrary(builder, comp, objs);
index 9eac8724fadbc21b5b170f9f0618d3a76993c641..bb94634a46389c256578885871a05347f8ed62fd 100644 (file)
@@ -48,10 +48,10 @@ Target *MsvcCompiler::create_source(const FS::Path &path) const
 
 Target *MsvcCompiler::create_target(const vector<Target *> &sources, const string &)
 {
-       if(sources.size()!=1)
-               throw invalid_argument("MsvcCompiler::create_target");
-       SourceFile &source = dynamic_cast<SourceFile &>(*sources.front());
-       ObjectFile *obj = new ObjectFile(builder, *source.get_component(), source);
+       SourceFile *source = 0;
+       extract_sources(sources, source);
+
+       ObjectFile *obj = new ObjectFile(builder, *source->get_component(), *source);
        obj->set_tool(*this);
        return obj;
 }
index 8f0ac94e11dbe0e8464b8cef171b07d9111bd5fe..a9ada9958802d36c13ba76fde7797272a2afa3bd 100644 (file)
@@ -31,27 +31,21 @@ MsvcLinker::MsvcLinker(Builder &b, const Architecture &a, const MicrosoftTools &
 
 Target *MsvcLinker::create_target(const vector<Target *> &sources, const string &arg)
 {
-       if(sources.empty())
-               throw invalid_argument("MsvcLinker::create_target");
-
        if(arg=="import")
        {
-               if(sources.size()!=1)
-                       throw invalid_argument("MsvcLinker::create_target");
-               SharedLibrary &shlib = dynamic_cast<SharedLibrary &>(*sources.front());
+               SharedLibrary *shlib = 0;
+               extract_sources(sources, required(shlib));
 
-               ImportLibrary *imp = new ImportLibrary(builder, *shlib.get_component(), shlib);
-               for(ObjectFile *o: shlib.get_objects())
+               ImportLibrary *imp = new ImportLibrary(builder, *shlib->get_component(), *shlib);
+               for(ObjectFile *o: shlib->get_objects())
                        imp->add_dependency(*o);
-               shlib.add_side_effect(*imp);
+               shlib->add_side_effect(*imp);
 
                return imp;
        }
 
        vector<ObjectFile *> objs;
-       objs.reserve(sources.size());
-       for(Target *s: sources)
-               objs.push_back(&dynamic_cast<ObjectFile &>(*s));
+       extract_sources(sources, required(objs));
 
        const Component &comp = *objs.front()->get_component();
        Binary *bin = 0;
index eaf4977d8c16030f2aa1bb0994ad3abc1d67c900..2aa47e25239c9663b36e6179dabc6cbed3f6f545 100644 (file)
@@ -37,6 +37,11 @@ Target *Tool::create_target(Target &source, const string &arg)
        return create_target(sources, arg);
 }
 
+void Tool::extract_source(Target *source) const
+{
+       throw logic_error(format("%s can't process %s", tag, source->get_type()));
+}
+
 void Tool::prepare()
 {
        if(prepared)
index 5921c2ddb2eb44e545711878d5c0401ded919343..ce631da2f0cef95bb44871d1bf9a4014ea718535 100644 (file)
@@ -5,6 +5,7 @@
 #include <string>
 #include <vector>
 #include <msp/fs/path.h>
+#include <msp/strings/format.h>
 #include "buildinfo.h"
 #include "externaltask.h"
 #include "internaltask.h"
@@ -43,6 +44,12 @@ public:
        };
 
 protected:
+       template<typename T>
+       struct RequiredSource
+       {
+               T &ref;
+       };
+
        Builder &builder;
        const Architecture *architecture = 0;
        std::string tag;
@@ -130,6 +137,37 @@ public:
        alternative target type for tools that can create multiple kinds of targets. */ 
        virtual Target *create_target(const std::vector<Target *> &, const std::string & = std::string()) = 0;
 
+protected:
+       template<typename... Ts>
+       void extract_sources(const std::vector<Target *> &, Ts &...) const;
+
+       template<typename T>
+       const RequiredSource<T> required(T &s) const { return { s }; }
+
+private:
+       void extract_source(Target *) const;
+
+       template<typename T, typename... Rest>
+       void extract_source(Target *, T *&, Rest &...) const;
+
+       template<typename T, typename... Rest>
+       void extract_source(Target *, std::vector<T *> &, Rest &...) const;
+
+       template<typename T, typename... Rest>
+       void extract_source(Target *s, const RequiredSource<T> &t, Rest &... r) const { extract_source(s, t.ref, r...); }
+
+       bool check_required_sources() const { return true; }
+
+       template<typename T, typename... Rest>
+       bool check_required_sources(const RequiredSource<T *> &, Rest &...) const;
+
+       template<typename T, typename... Rest>
+       bool check_required_sources(const RequiredSource<std::vector<T *>> &, Rest &...) const;
+
+       template<typename T, typename... Rest>
+       bool check_required_sources(T &, Rest &... rest) const { return check_required_sources(rest...); }
+
+public:
        /** Creates an install target for a target created by this tool.  Can return
        null if the tool does not want to handle installing in a special way. */
        virtual Target *create_install(Target &) const { return 0; }
@@ -171,6 +209,49 @@ void Tool::set_run_internal(bool (*f)(const T &))
        });
 }
 
+template<typename... Ts>
+void Tool::extract_sources(const std::vector<Target *> &sources, Ts &... store) const
+{
+       for(Target *t: sources)
+               extract_source(t, store...);
+       if(!check_required_sources(store...))
+               throw std::logic_error(Msp::format("required sources missing for %s", tag));
+}
+
+template<typename T, typename... Rest>
+void Tool::extract_source(Target *source, T *&store, Rest &... rest) const
+{
+       if(T *cast_src = dynamic_cast<T *>(source))
+       {
+               if(store)
+                       throw std::logic_error(Msp::format("extraneous %s given to %s", source->get_type(), tag));
+               store = cast_src;
+       }
+       else
+               extract_source(source, rest...);
+}
+
+template<typename T, typename... Rest>
+void Tool::extract_source(Target *source, std::vector<T *> &store, Rest &... rest) const
+{
+       if(T *cast_src = dynamic_cast<T *>(source))
+               store.push_back(cast_src);
+       else
+               extract_source(source, rest...);
+}
+
+template<typename T, typename... Rest>
+bool Tool::check_required_sources(const RequiredSource<T *> &store, Rest &... rest) const
+{
+       return store.ref && check_required_sources(rest...);
+}
+
+template<typename T, typename... Rest>
+bool Tool::check_required_sources(const RequiredSource<std::vector<T *>> &store, Rest &... rest) const
+{
+       return !store.ref.empty() && check_required_sources(rest...);
+}
+
 
 void operator>>(const Msp::LexicalConverter &, Tool::ProcessingUnit &);