]> git.tdb.fi Git - builder.git/commitdiff
Redesign how tools are run
authorMikko Rasa <tdb@tdb.fi>
Thu, 22 Dec 2022 16:05:25 +0000 (18:05 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 22 Dec 2022 16:05:25 +0000 (18:05 +0200)
It also uses functors now.  The run functions access properties of the
tool through the target.  This will allow tool customization without
having to derive from the class, which will be useful for modularization.

40 files changed:
source/androidassetpackagingtool.cpp
source/androidassetpackagingtool.h
source/androidmanifestgenerator.cpp
source/androidmanifestgenerator.h
source/apkbuilder.cpp
source/apkbuilder.h
source/compilecommandsgenerator.cpp
source/compilecommandsgenerator.h
source/copy.cpp
source/copy.h
source/datatool.cpp
source/datatool.h
source/gnuarchiver.cpp
source/gnuarchiver.h
source/gnucompiler.cpp
source/gnucompiler.h
source/gnulinker.cpp
source/gnulinker.h
source/jarsigner.cpp
source/jarsigner.h
source/mingwdlltool.cpp
source/mingwdlltool.h
source/msvcarchiver.cpp
source/msvcarchiver.h
source/msvccompiler.cpp
source/msvccompiler.h
source/msvclinker.cpp
source/msvclinker.h
source/pkgconfiggenerator.cpp
source/pkgconfiggenerator.h
source/sourcegenerator.cpp
source/sourcegenerator.h
source/tar.cpp
source/tar.h
source/tool.cpp
source/tool.h
source/vcxprojectgenerator.cpp
source/vcxprojectgenerator.h
source/vssolutiongenerator.cpp
source/vssolutiongenerator.h

index af8bc95ea422187112d5dce75927d8567803d309..a511da04986ba65eae493f31965e1becfbb4a5c5 100644 (file)
@@ -24,6 +24,8 @@ AndroidAssetPackagingTool::AndroidAssetPackagingTool(Builder &b, const AndroidSd
 
        if(sdk.get_platform_jar().empty())
                problems.push_back("Android platform not found");
+
+       set_run(_run);
 }
 
 Target *AndroidAssetPackagingTool::create_target(const vector<Target *> &sources, const string &)
@@ -47,18 +49,18 @@ Target *AndroidAssetPackagingTool::create_target(const vector<Target *> &sources
        return res;
 }
 
-Task *AndroidAssetPackagingTool::run(const Target &tgt) const
+Task *AndroidAssetPackagingTool::_run(const AndroidResourceBundle &res)
 {
-       const AndroidResourceBundle &res = dynamic_cast<const AndroidResourceBundle &>(tgt);
+       const AndroidAssetPackagingTool &tool = dynamic_cast<const AndroidAssetPackagingTool &>(*res.get_tool());
 
        ExternalTask::Arguments argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
        argv.push_back("package");
 
        FS::Path work_dir = res.get_component()->get_package().get_source_directory();
 
        argv.push_back("-I");
-       argv.push_back(sdk.get_platform_jar().str());
+       argv.push_back(tool.sdk.get_platform_jar().str());
 
        argv.push_back("-F");
        argv.push_back(FS::relative(res.get_path(), work_dir).str());
index 8f01e6daadf8e3fc372244c0d060d7fb8a673634..e4f0f770ad879ab606ae3d87a9f6d4732ee98981 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "tool.h"
 
+class AndroidResourceBundle;
 class AndroidSdk;
 
 class AndroidAssetPackagingTool: public Tool
@@ -14,7 +15,9 @@ public:
        AndroidAssetPackagingTool(Builder &, const AndroidSdk &);
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
-       Task *run(const Target &) const override;
+
+private:
+       static Task *_run(const AndroidResourceBundle &);
 };
 
 #endif
index 70b1e20754d06d2b72db97a070894b8a3c571c41..0c489825824784a6af316572406a1d338a256691 100644 (file)
 using namespace std;
 using namespace Msp;
 
-Target *AndroidManifestGenerator::create_target(const vector<Target *> &, const string &)
+AndroidManifestGenerator::AndroidManifestGenerator(Builder &b):
+       Tool(b, "AMG")
 {
-       throw logic_error("not implemented");
+       set_run_internal(_run);
 }
 
-Task *AndroidManifestGenerator::run(const Target &target) const
+Target *AndroidManifestGenerator::create_target(const vector<Target *> &, const string &)
 {
-       const AndroidManifestFile &manifest = dynamic_cast<const AndroidManifestFile &>(target);
-       return new InternalTask([&manifest]{ return _run(manifest); });
+       throw logic_error("not implemented");
 }
 
 bool AndroidManifestGenerator::_run(const AndroidManifestFile &manifest)
index 6013c5f51b8a1f2cebc2b8eaab6d046cc9cfbd58..58fc0b236df4119da47aab4ea491eebad4898022 100644 (file)
@@ -8,10 +8,9 @@ class AndroidManifestFile;
 class AndroidManifestGenerator: public Tool
 {
 public:
-       AndroidManifestGenerator(Builder &b): Tool(b, "AMG") { }
+       AndroidManifestGenerator(Builder &);
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
-       Task *run(const Target &) const override;
 
 private:
        static bool _run(const AndroidManifestFile &);
index d232a6f927ee23827db9eaafacf7a5997e3f999d..e487784f4eeebf2df37d974a01432fb70e00d85a 100644 (file)
@@ -18,6 +18,7 @@ ApkBuilder::ApkBuilder(Builder &b):
        Tool(b, "APK")
 {
        set_command("jar");
+       set_run(_run);
 }
 
 Target *ApkBuilder::create_target(const vector<Target *> &sources, const string &)
@@ -43,12 +44,12 @@ void ApkBuilder::do_prepare()
        jarsigner->prepare();
 }
 
-Task *ApkBuilder::run(const Target &tgt) const
+Task *ApkBuilder::_run(const AndroidPackageFile &apk)
 {
-       const AndroidPackageFile &apk = dynamic_cast<const AndroidPackageFile &>(tgt);
+       const ApkBuilder &tool = dynamic_cast<const ApkBuilder &>(*apk.get_tool());
 
        ExternalTask::Arguments argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
        argv.push_back("u");
 
        FS::Path input_path;
@@ -74,6 +75,6 @@ Task *ApkBuilder::run(const Target &tgt) const
        task->set_stdin(FS::basename(input_path));
        task->set_stdout(FS::relative(apk.get_path(), work_dir));
        ChainedTask *chain = new ChainedTask(task);
-       chain->add_task(jarsigner->run(tgt));
+       chain->add_task(tool.jarsigner->run(apk));
        return chain;
 }
index 4a8c16b5e925238c3cb8faa66796f8e5b63f93de..09d849c659f6e72ddc2067366dd4f00d6a00a6b9 100644 (file)
@@ -3,6 +3,8 @@
 
 #include "tool.h"
 
+class AndroidPackageFile;
+
 class ApkBuilder: public Tool
 {
 private:
@@ -14,8 +16,9 @@ public:
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
 protected:
        void do_prepare() override;
-public:
-       Task *run(const Target &) const override;
+
+private:
+       static Task *_run(const AndroidPackageFile &);
 };
 
 #endif
index 855a80a3307db63e3e4f24222e8c092c1ba33f00..bbd4e980742c70c96621d234ff7eeda0845a1c0c 100644 (file)
 using namespace std;
 using namespace Msp;
 
-Target *CompileCommandsGenerator::create_target(const vector<Target *> &, const string &)
+CompileCommandsGenerator::CompileCommandsGenerator(Builder &b):
+       Tool(b, "CCJG")
 {
-       throw logic_error("Not implemented");
+       set_run_internal(_run);
 }
 
-Task *CompileCommandsGenerator::run(const Target &target) const
+Target *CompileCommandsGenerator::create_target(const vector<Target *> &, const string &)
 {
-       const CompileCommandsJson &cmds = dynamic_cast<const CompileCommandsJson &>(target);
-       return new InternalTask([&cmds]{ return _run(cmds); });
+       throw logic_error("Not implemented");
 }
 
 bool CompileCommandsGenerator::_run(const CompileCommandsJson &cmds)
index e3116f9c839312e5930c56d0c5342c9ea2805a03..a6fa6f9bb696cd2634624bbe8fabaac428df2a73 100644 (file)
@@ -8,10 +8,9 @@ class CompileCommandsJson;
 class CompileCommandsGenerator: public Tool
 {
 public:
-       CompileCommandsGenerator(Builder &b): Tool(b, "CCJG") { }
+       CompileCommandsGenerator(Builder &);
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
-       Task *run(const Target &) const override;
 
 private:
        static bool _run(const CompileCommandsJson &);
index 9bca33f3050989900407937c3fd68bb0536f76c6..8f6b81d46b8764e82b5a9e8ba7755888e34e8576 100644 (file)
 using namespace std;
 using namespace Msp;
 
+Copy::Copy(Builder &b):
+       Tool(b, "CP")
+{
+       set_run_internal(_run);
+}
+
 Target *Copy::create_target(const vector<Target *> &sources, const string &arg)
 {
        FileTarget &file_tgt = dynamic_cast<FileTarget &>(*sources.front());
@@ -23,12 +29,6 @@ Target *Copy::create_target(const vector<Target *> &sources, const string &arg)
        return inst;
 }
 
-Task *Copy::run(const Target &target) const
-{
-       const InstalledFile &install = dynamic_cast<const InstalledFile &>(target);
-       return new InternalTask([&install]{ return _run(install); });
-}
-
 bool Copy::_run(const InstalledFile &install)
 {
        const FileTarget &source = install.get_source();
index c0a433996a9c0a14625ebf918c9c6092eac6d9e0..d65bb05a0c70e62b87382cea20fb16950b8b5061 100644 (file)
@@ -11,10 +11,9 @@ Copies a file to another place.  Used by the InstalledFile target.
 class Copy: public Tool
 {
 public:
-       Copy(Builder &b): Tool(b, "CP") { }
+       Copy(Builder &);
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
-       Task *run(const Target &) const override;
 
 private:
        static bool _run(const InstalledFile &);
index b24de1396c22381ca279b9a27194f1cdc99e8541..1bc629ebdfe60724e4b0f5b0c10712b8821cc60e 100644 (file)
@@ -16,6 +16,7 @@ DataTool::DataTool(Builder &b):
        Tool(b, "DATA")
 {
        set_command("mspdatatool");
+       set_run(_run);
        input_suffixes.push_back(".mdt");
 }
 
@@ -67,13 +68,14 @@ string DataTool::create_build_signature(const BuildInfo &binfo) const
        return result;
 }
 
-Task *DataTool::run(const Target &tgt) const
+Task *DataTool::_run(const Target &tgt)
 {
+       const Tool &tool = *tgt.get_tool();
        const Component &comp = *tgt.get_component();
        FS::Path work_dir = comp.get_package().get_source_directory();
 
        vector<string> argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
 
        argv.push_back("-o");
        argv.push_back(FS::relative(dynamic_cast<const FileTarget &>(tgt).get_path(), work_dir).str());
index 128f8338eff0ccc744207d2fc23aeff6049ec69a..1cddebb6e58fdbcd467c232458461b3e141da0b4 100644 (file)
@@ -11,7 +11,9 @@ public:
        Target *create_source(const Component &, const Msp::FS::Path &) const override;
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
        std::string create_build_signature(const BuildInfo &) const override;
-       Task *run(const Target &) const override;
+
+private:
+       static Task *_run(const Target &);
 };
 
 #endif
index 24a022febd10e1a0ed711bfee58782a99ad75880..2f5ba24d6068d7c3f9c5d695b502a87d955f3d5c 100644 (file)
@@ -19,6 +19,7 @@ GnuArchiver::GnuArchiver(Builder &b, const Architecture &a):
        set_command("ar", true);
        input_suffixes.push_back(".o");
        processing_unit = COMPONENT;
+       set_run(_run);
 }
 
 Target *GnuArchiver::create_target(const vector<Target *> &sources, const string &)
@@ -37,13 +38,13 @@ Target *GnuArchiver::create_target(const vector<Target *> &sources, const string
        return lib;
 }
 
-Task *GnuArchiver::run(const Target &target) const
+Task *GnuArchiver::_run(const StaticLibrary &lib)
 {
-       const StaticLibrary &lib = dynamic_cast<const StaticLibrary &>(target);
+       const Tool &tool = *lib.get_tool();
        const Component &comp = *lib.get_component();
 
        vector<string> argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
        argv.push_back("rc");
 
        FS::Path work_dir = comp.get_package().get_source_directory();
index 0e4172bcadd97e29825d1c1e930c0864bbab0815..4d21abebaf4c27c56dc45729d713d1f63192029c 100644 (file)
@@ -3,13 +3,17 @@
 
 #include "tool.h"
 
+class StaticLibrary;
+
 class GnuArchiver: public Tool
 {
 public:
        GnuArchiver(Builder &, const Architecture &);
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
-       Task *run(const Target &) const override;
+
+private:
+       static Task *_run(const StaticLibrary &);
 };
 
 #endif
index b8b25152e70acfce73e0c9f9e313daf8460f3979..0ec9222a2d28587f8127f01cbaa1e01008496459 100644 (file)
@@ -51,6 +51,7 @@ GnuCompiler::GnuCompiler(Builder &b, const Architecture &a, const string &t):
                throw invalid_argument("GnuCompiler::GnuCompiler");
 
        set_command((tag=="CXX" ? "g++" : "gcc"), true);
+       set_run(_run);
 }
 
 Target *GnuCompiler::create_source(const Component &comp, const FS::Path &path) const
@@ -198,22 +199,24 @@ void GnuCompiler::prepare_version(const string &arg)
        { }
 }
 
-Task *GnuCompiler::run(const Target &target) const
+Task *GnuCompiler::_run(const ObjectFile &object)
 {
-       const ObjectFile &object = dynamic_cast<const ObjectFile &>(target);
+       const GnuCompiler &tool = dynamic_cast<const GnuCompiler &>(*object.get_tool());
+       const Architecture &arch = *tool.get_architecture();
 
        ExternalTask::Arguments argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
        argv.push_back("-c");
 
        BuildInfo binfo;
-       target.collect_build_info(binfo);
+       object.collect_build_info(binfo);
 
-       string tag_for_std = (tag=="OBJC" ? "CC" : tag);
+       const std::string &tool_tag = tool.get_tag();
+       string tag_for_std = (tool_tag=="OBJC" ? "CC" : tool_tag);
        if(binfo.standards.count(tag_for_std))
                argv.push_back("-std="+get_item(binfo.standards, tag_for_std).str());
-       if(tag=="OBJC" && binfo.standards.count(tag))
-               argv.push_back("-fobjc-std="+get_item(binfo.standards, tag).str());
+       if(tool_tag=="OBJC" && binfo.standards.count(tool_tag))
+               argv.push_back("-fobjc-std="+get_item(binfo.standards, tool_tag).str());
 
        if(binfo.warning_level>=1)
        {
@@ -222,7 +225,7 @@ Task *GnuCompiler::run(const Target &target) const
                {
                        argv.push_back("-Wextra");
                        argv.push_back("-Wundef");
-                       if(version>=0x80000)
+                       if(tool.version>=0x80000)
                                argv.push_back("-Wno-cast-function-type");
                }
                if(binfo.warning_level>=3)
@@ -230,7 +233,7 @@ Task *GnuCompiler::run(const Target &target) const
                        argv.push_back("-pedantic");
                        argv.push_back("-Wno-long-long");
                        argv.push_back("-Wshadow");
-                       if(tag=="CC")
+                       if(tool_tag=="CC")
                        {
                                argv.push_back("-Wc++-compat");
                                argv.push_back("-Wstrict-prototypes");
@@ -282,15 +285,15 @@ Task *GnuCompiler::run(const Target &target) const
                if(binfo.debug)
                        argv.push_back("-fno-omit-frame-pointer");
        }
-       if(binfo.threads && architecture->get_system()!="windows" && architecture->get_system()!="darwin")
+       if(binfo.threads && arch.get_system()!="windows" && arch.get_system()!="darwin")
                argv.push_back("-pthread");
-       if(object.is_used_in_shared_library() && architecture->get_system()!="windows")
+       if(object.is_used_in_shared_library() && arch.get_system()!="windows")
                argv.push_back("-fPIC");
 
-       if((architecture->get_type()=="x86" || architecture->get_type()=="ppc") && !architecture->is_native())
-               argv.push_back(format("-m%d", architecture->get_bits()));
+       if((arch.get_type()=="x86" || arch.get_type()=="ppc") && !arch.is_native())
+               argv.push_back(format("-m%d", arch.get_bits()));
 
-       string cpu = architecture->get_cpu();
+       string cpu = arch.get_cpu();
        if(!cpu.empty())
        {
                for(unsigned i=0; cpus[i]; i+=2)
@@ -302,25 +305,25 @@ Task *GnuCompiler::run(const Target &target) const
                argv.push_back("-march="+cpu);
        }
 
-       if(!architecture->get_fpu().empty())
+       if(!arch.get_fpu().empty())
        {
-               if(architecture->get_type()=="x86")
+               if(arch.get_type()=="x86")
                {
-                       if(architecture->get_fpu()=="387")
+                       if(arch.get_fpu()=="387")
                                argv.push_back("-mfpmath=387");
-                       else if(!architecture->get_fpu().compare(0, 3, "sse"))
+                       else if(!arch.get_fpu().compare(0, 3, "sse"))
                                argv.push_back("-mfpmath=sse");
 
-                       if(architecture->get_fpu()=="sse")
+                       if(arch.get_fpu()=="sse")
                                argv.push_back("-msse2");
-                       else if(architecture->get_fpu()=="sse3")
+                       else if(arch.get_fpu()=="sse3")
                                argv.push_back("-msse3");
-                       else if(architecture->get_fpu()=="sse4.1")
+                       else if(arch.get_fpu()=="sse4.1")
                                argv.push_back("-msse4.1");
                }
-               else if(architecture->get_type()=="arm")
+               else if(arch.get_type()=="arm")
                {
-                       argv.push_back("-mfpu="+architecture->get_fpu());
+                       argv.push_back("-mfpu="+arch.get_fpu());
                        argv.push_back("-mfloat-abi=softfp");
                }
        }
index 1983f79f9535298249f601697ea1809961f932e7..8257dd83576e7236233cc88ef49ac92bcb89e42e 100644 (file)
@@ -3,6 +3,8 @@
 
 #include "tool.h"
 
+class ObjectFile;
+
 /**
 Common base class for GNU compilers.  Turns SourceFiles into ObjectFiles.
 
@@ -27,8 +29,9 @@ protected:
        void prepare_syspath();
        void prepare_version();
        void prepare_version(const std::string &);
-public:
-       Task *run(const Target &) const override;
+
+private:
+       static Task *_run(const ObjectFile &);
 };
 
 #endif
index 56becc2c42ef0f6f9f32f30f7ba910213a077212..31440976e917d31a43c8d9d701ff057a0573a740 100644 (file)
@@ -175,11 +175,6 @@ void GnuLinker::do_prepare()
        }
 }
 
-Task *GnuLinker::run(const Target &) const
-{
-       throw logic_error("GnuLinker should not be run directly");
-}
-
 
 GnuLinker::Linker::Linker(GnuLinker &p, const string &ct):
        SubTool(p),
@@ -191,6 +186,8 @@ GnuLinker::Linker::Linker(GnuLinker &p, const string &ct):
                set_command("g++", true);
        else
                throw invalid_argument("GnuLinker::Linker::Linker");
+
+       set_run(_run);
 }
 
 string GnuLinker::Linker::create_build_signature(const BuildInfo &binfo) const
@@ -225,12 +222,14 @@ void GnuLinker::Linker::do_prepare()
        }
 }
 
-Task *GnuLinker::Linker::run(const Target &target) const
+Task *GnuLinker::Linker::_run(const Binary &bin)
 {
-       const Binary &bin = dynamic_cast<const Binary &>(target);
+       const Linker &tool = dynamic_cast<const Linker &>(*bin.get_tool());
+       const Builder &builder = tool.get_builder();
+       const Architecture &arch = *tool.get_architecture();
 
        ExternalTask::Arguments argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
 
        FS::Path work_dir = bin.get_component()->get_package().get_source_directory();
 
@@ -238,9 +237,9 @@ Task *GnuLinker::Linker::run(const Target &target) const
        {
                argv.push_back("-shared");
                argv.push_back("-fPIC");
-               if(architecture->get_system()!="windows" && !shlib->get_soname().empty())
+               if(arch.get_system()!="windows" && !shlib->get_soname().empty())
                {
-                       if(architecture->get_system()=="darwin")
+                       if(arch.get_system()=="darwin")
                        {
                                argv.push_back("-install_name");
                                argv.push_back(shlib->get_soname());
@@ -261,7 +260,7 @@ Task *GnuLinker::Linker::run(const Target &target) const
        }
 
        BuildInfo binfo;
-       target.collect_build_info(binfo);
+       bin.collect_build_info(binfo);
 
        const FS::Path &sysroot = binfo.sysroot;
        if(!sysroot.empty())
@@ -281,12 +280,12 @@ Task *GnuLinker::Linker::run(const Target &target) const
                argv.push_back("-L"+p.str());
        if(binfo.strip)
                argv.push_back("-s");
-       if(binfo.threads && architecture->get_system()!="windows" && architecture->get_system()!="darwin")
+       if(binfo.threads && arch.get_system()!="windows" && arch.get_system()!="darwin")
                argv.push_back("-pthread");
 
        const Architecture &native_arch = builder.get_native_arch();
-       if(architecture->is_native() && architecture->get_bits()!=native_arch.get_bits())
-               argv.push_back(format("-m%d", architecture->get_bits()));
+       if(arch.is_native() && arch.get_bits()!=native_arch.get_bits())
+               argv.push_back(format("-m%d", arch.get_bits()));
 
        argv.push_back("-o");
        argv.push_back(relative(bin.get_path(), work_dir).str());
@@ -296,7 +295,7 @@ Task *GnuLinker::Linker::run(const Target &target) const
 
        bool static_link_ok = (binfo.libmode<=BuildInfo::STATIC);
 
-       for(Target *d: target.get_dependencies())
+       for(Target *d: bin.get_dependencies())
        {
                FileTarget *file = dynamic_cast<FileTarget *>(d);
                Target *tgt = d->get_real_target();
@@ -332,14 +331,14 @@ Task *GnuLinker::Linker::run(const Target &target) const
                argv.push_back("-static");
        else
        {
-               if(compiler_tag=="CXX")
+               if(tool.compiler_tag=="CXX")
                {
                        auto i = binfo.libmodes.find("stdc++");
                        if(i!=binfo.libmodes.end() && i->second<=BuildInfo::STATIC)
                                argv.push_back("-static-libstdc++");
                }
 
-               if(architecture->get_system()=="windows")
+               if(arch.get_system()=="windows")
                        argv.push_back("-Wl,--enable-auto-import");
        }
 
index 821f7469f10f41c6d9bf870b464b519f36c81dd6..713b978064747ab570b15f9cbc764ddaa149b014 100644 (file)
@@ -3,6 +3,8 @@
 
 #include "tool.h"
 
+class Binary;
+
 /**
 The GNU linker.  Turns ObjectFiles into Executables and SharedLibraries.  To
 create a shared library, specify "shared" as the second argument to
@@ -24,8 +26,9 @@ private:
                std::string create_build_signature(const BuildInfo &) const override;
        private:
                void do_prepare() override;
+
        public:
-               Task *run(const Target &) const override;
+               static Task *_run(const Binary &);
        };
 
        Linker *default_linker = 0;
@@ -39,8 +42,6 @@ public:
        Target *create_install(Target &) const override;
 protected:
        void do_prepare() override;
-public:
-       Task *run(const Target &) const override;
 };
 
 #endif
index c8448d2c302c2ff7cdba2434ddf64509c7f22cbd..ac7c779b7c1c957c56d56c47505262c9f5bf6b3f 100644 (file)
@@ -13,6 +13,7 @@ JarSigner::JarSigner(Builder &b):
        Tool(b, "JSGN")
 {
        set_command("jarsigner");
+       set_run(_run);
 }
 
 Target *JarSigner::create_target(const vector<Target *> &, const string &)
@@ -20,12 +21,12 @@ Target *JarSigner::create_target(const vector<Target *> &, const string &)
        throw logic_error("not implemented");
 }
 
-Task *JarSigner::run(const Target &tgt) const
+Task *JarSigner::_run(const FileTarget &file)
 {
-       const FileTarget &file = dynamic_cast<const FileTarget &>(tgt);
+       const Tool &tool = *file.get_tool();
 
        ExternalTask::Arguments argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
 
        // TODO Make this generic
        FS::Path home_dir = Msp::getenv("HOME");
index 6f5124463fc8d378904be45320f03a2654ceabfb..f1b1c4fb6cc0669004e67f5fb8e22769ebaa113f 100644 (file)
@@ -3,13 +3,17 @@
 
 #include "tool.h"
 
+class FileTarget;
+
 class JarSigner: public Tool
 {
 public:
        JarSigner(Builder &);
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
-       Task *run(const Target &) const override;
+
+private:
+       static Task *_run(const FileTarget &);
 };
 
 #endif
index 922fe51a10b724c5daa0608e55e5efb90e2392fc..62ef7059a885d7a78d2dd216b2d2612c3eeabd42 100644 (file)
@@ -19,6 +19,7 @@ MingwDllTool::MingwDllTool(Builder &b, const Architecture &a):
        Tool(b, a, "DLL")
 {
        set_command("dlltool", true);
+       set_run(_run);
 }
 
 Target *MingwDllTool::create_target(const vector<Target *> &sources, const string &)
@@ -57,8 +58,10 @@ Target *MingwDllTool::create_install(Target &target) const
                return 0;
 }
 
-Task *MingwDllTool::run(const Target &target) const
+Task *MingwDllTool::_run(const Target &target)
 {
+       const Tool &tool = *target.get_tool();
+
        const ImportLibrary *imp = dynamic_cast<const ImportLibrary *>(&target);
        const ExportDefinitions *exp = 0;
        if(imp)
@@ -69,7 +72,7 @@ Task *MingwDllTool::run(const Target &target) const
                throw invalid_argument("MingwDllTool::run");
 
        vector<string> argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
 
        /* dlltool is stupid and puts temporary files in the working directory by
        default */
index 039ee7cb05370d734b2273f73c95882544ebaaf7..d9fb1cbf3bbbadbefebf032790b8e2f45a7d584b 100644 (file)
@@ -10,7 +10,9 @@ public:
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
        Target *create_install(Target &) const override;
-       Task *run(const Target &) const override;
+
+private:
+       static Task *_run(const Target &);
 };
 
 #endif
index 5544b2768532bc1f74b9499f0256e1e5139bb431..2d5d84260358734f4c8bac93d19cb8c594066796 100644 (file)
@@ -17,6 +17,7 @@ MsvcArchiver::MsvcArchiver(Builder &b, const Architecture &a, const MicrosoftToo
        input_suffixes.push_back(".o");
        processing_unit = COMPONENT;
        set_command((ms_tools.get_vc_bin_dir()/"lib.exe").str(), false);
+       set_run(_run);
 }
 
 Target *MsvcArchiver::create_target(const vector<Target *> &sources, const string &)
@@ -35,13 +36,13 @@ Target *MsvcArchiver::create_target(const vector<Target *> &sources, const strin
        return lib;
 }
 
-Task *MsvcArchiver::run(const Target &target) const
+Task *MsvcArchiver::_run(const StaticLibrary &lib)
 {
-       const StaticLibrary &lib = dynamic_cast<const StaticLibrary &>(target);
        const Component &comp = *lib.get_component();
+       const Tool &tool = *lib.get_tool();
 
        vector<string> argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
        argv.push_back("/NOLOGO");
 
        FS::Path work_dir = comp.get_package().get_source_directory();
index 03544a91c55fe6dc9ea6f26857ba1fb6a7c4984e..8b31bd99523fba40bea18e538ce7946d2b697b65 100644 (file)
@@ -4,6 +4,7 @@
 #include "tool.h"
 
 class MicrosoftTools;
+class StaticLibrary;
 
 class MsvcArchiver: public Tool
 {
@@ -15,7 +16,8 @@ public:
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
 
-       Task *run(const Target &) const override;
+private:
+       static Task *_run(const StaticLibrary &);
 };
 
 #endif
index dbbc64d41895baea735e41d2e7f8f5c19ec8dd59..099c1230b7e5e18518c429dd7bc3f865180ea9c8 100644 (file)
@@ -34,6 +34,7 @@ MsvcCompiler::MsvcCompiler(Builder &b, const Architecture &a, const string &t, c
                throw invalid_argument("MsvcCompiler::MsvcCompiler");
 
        set_command((ms_tools.get_vc_bin_dir()/"cl.exe").str(), false);
+       set_run(_run);
 }
 
 Target *MsvcCompiler::create_source(const Component &comp, const FS::Path &path) const
@@ -93,22 +94,22 @@ void MsvcCompiler::do_prepare()
        setenv("INCLUDE", path);
 }
 
-Task *MsvcCompiler::run(const Target &target) const
+Task *MsvcCompiler::_run(const ObjectFile &object)
 {
-       const ObjectFile &object = dynamic_cast<const ObjectFile &>(target);
+       const Tool &tool = *object.get_tool();
 
        ExternalTask::Arguments argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
        argv.push_back("/nologo");
        argv.push_back("/c");
 
        BuildInfo binfo;
-       target.collect_build_info(binfo);
+       object.collect_build_info(binfo);
 
-       if(binfo.standards.count(tag))
+       if(binfo.standards.count(tool.get_tag()))
        {
-               const BuildInfo::LanguageStandard &std = get_item(binfo.standards, tag);
-               if((tag=="CXX" && std.year>2011) || (tag=="CC" && std.year>1999))
+               const BuildInfo::LanguageStandard &std = get_item(binfo.standards, tool.get_tag());
+               if((tool.get_tag()=="CXX" && std.year>2011) || (tool.get_tag()=="CC" && std.year>1999))
                        argv.push_back("/std:"+std.str());
        }
 
index ef1da349d829c897bca06e68b601686e5ea24f00..484fe46ec1c88bdcf3fbda7acc51795e02170e27 100644 (file)
@@ -4,6 +4,7 @@
 #include "tool.h"
 
 class MicrosoftTools;
+class ObjectFile;
 
 class MsvcCompiler: public Tool
 {
@@ -22,7 +23,7 @@ protected:
        void do_prepare() override;
 
 public:
-       Task *run(const Target &) const override;
+       static Task *_run(const ObjectFile &);
 };
 
 #endif
index 78cf0b25b0d9fd5b395528c641111d877a7bb8df..62e9d2af0a8def642427bbcdbe43f1299652b08b 100644 (file)
@@ -26,6 +26,7 @@ MsvcLinker::MsvcLinker(Builder &b, const Architecture &a, const MicrosoftTools &
        processing_unit = COMPONENT;
 
        set_command((ms_tools.get_vc_bin_dir()/"link.exe").str(), false);
+       set_run(_run);
 }
 
 Target *MsvcLinker::create_target(const vector<Target *> &sources, const string &arg)
@@ -84,12 +85,12 @@ void MsvcLinker::do_prepare()
        setenv("LIB", path);
 }
 
-Task *MsvcLinker::run(const Target &target) const
+Task *MsvcLinker::_run(const Binary &bin)
 {
-       const Binary &bin = dynamic_cast<const Binary &>(target);
+       const Tool &tool = *bin.get_tool();
 
        vector<string> argv;
-       argv.push_back(executable->get_path().str());
+       argv.push_back(tool.get_executable()->get_path().str());
        argv.push_back("/NOLOGO");
 
        FS::Path work_dir = bin.get_component()->get_package().get_source_directory();
@@ -98,7 +99,7 @@ Task *MsvcLinker::run(const Target &target) const
                argv.push_back("/DLL");
 
        BuildInfo binfo;
-       target.collect_build_info(binfo);
+       bin.collect_build_info(binfo);
 
        /*for(const FS::Path &p: binfo.libpath)
                argv.push_back("/LIBPATH:"+p.str());*/
@@ -109,7 +110,7 @@ Task *MsvcLinker::run(const Target &target) const
 
        argv.push_back("/OUT:"+relative(bin.get_path(), work_dir).str());
 
-       for(Target *d: target.get_dependencies())
+       for(Target *d: bin.get_dependencies())
        {
                FileTarget *file = dynamic_cast<FileTarget *>(d);
                Target *tgt = d->get_real_target();
index 26b2abaaac250c83878c17e9894ee28f5628a6a8..95ff2a935799c18169ee92e8028f7f5a62d6d0f8 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "tool.h"
 
+class Binary;
 class MicrosoftTools;
 
 class MsvcLinker: public Tool
@@ -20,7 +21,7 @@ protected:
        void do_prepare() override;
 
 public:
-       Task *run(const Target &) const override;
+       static Task *_run(const Binary &);
 };
 
 #endif
index a6178a7328c5e66fa5ad22df0bc0686013e0367b..46387d35fda45e4ca4f4817edb2e4c3c6c9eacb7 100644 (file)
@@ -9,15 +9,15 @@
 using namespace std;
 using namespace Msp;
 
-Target *PkgConfigGenerator::create_target(const vector<Target *> &, const string &)
+PkgConfigGenerator::PkgConfigGenerator(Builder &b):
+       Tool(b, "PCG")
 {
-       throw logic_error("Not implemented");
+       set_run_internal(_run);
 }
 
-Task *PkgConfigGenerator::run(const Target &target) const
+Target *PkgConfigGenerator::create_target(const vector<Target *> &, const string &)
 {
-       const PkgConfigFile &pkgc = dynamic_cast<const PkgConfigFile &>(target);
-       return new InternalTask([&pkgc]{ return _run(pkgc); });
+       throw logic_error("Not implemented");
 }
 
 bool PkgConfigGenerator::_run(const PkgConfigFile &pkgc)
index 0f0886b851aa2583176d1499dcb0100d9a058168..761a2c0e8eaccb7e3276f40d2e2aa4971ecb26d1 100644 (file)
@@ -8,10 +8,9 @@ class PkgConfigFile;
 class PkgConfigGenerator: public Tool
 {
 public:
-       PkgConfigGenerator(Builder &b): Tool(b, "PCG") { }
+       PkgConfigGenerator(Builder &);
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
-       Task *run(const Target &) const override;
 
 private:
        static bool _run(const PkgConfigFile &);
index cfb01af22da70bb1a9256c481229cc2118ec1239..72297fd5eed411b19528681a6743492e16ca5e4a 100644 (file)
@@ -13,7 +13,9 @@ using namespace Msp;
 SourceGenerator::SourceGenerator(Builder &b, const SourcePackage &p, const string &t):
        Tool(b, t),
        package(p)
-{ }
+{
+       set_run(&_run);
+}
 
 Target *SourceGenerator::create_source(const Component &comp, const FS::Path &path) const
 {
@@ -69,21 +71,21 @@ Target *SourceGenerator::create_target(const vector<Target *> &sources, const st
        return primary;
 }
 
-Task *SourceGenerator::run(const Target &target) const
+Task *SourceGenerator::_run(const SourceFile &out_src)
 {
-       const SourceFile &out_src = dynamic_cast<const SourceFile &>(target);
        const FS::Path &work_dir = out_src.get_package()->get_source_directory();
+       const SourceGenerator &tool = dynamic_cast<const SourceGenerator &>(*out_src.get_tool());
 
        vector<string> args;
-       args.push_back(executable->get_path().str());
-       args.insert(args.end(), arguments.begin(), arguments.end());
+       args.push_back(tool.get_executable()->get_path().str());
+       args.insert(args.end(), tool.arguments.begin(), tool.arguments.end());
 
-       for(const Target *d: target.get_dependencies())
+       for(const Target *d: out_src.get_dependencies())
                if(const TemplateFile *tmpl = dynamic_cast<const TemplateFile *>(d))
                        args.push_back(FS::relative(tmpl->get_path(), work_dir).str());
 
-       if(!out_argument.empty())
-               args.push_back(out_argument);
+       if(!tool.out_argument.empty())
+               args.push_back(tool.out_argument);
        args.push_back(FS::relative(out_src.get_path(), work_dir).str());
 
        return new ExternalTask(args, work_dir);
index 3b96799dc81dccc06b199329532d451023cce9b7..e9fe3087e07e7eb864b00c32ab1b8985db3b24b7 100644 (file)
@@ -6,6 +6,8 @@
 #include "sourcepackage.h"
 #include "tool.h"
 
+class SourceFile;
+
 class SourceGenerator: public Tool
 {
 public:
@@ -35,7 +37,8 @@ public:
        Target *create_source(const Component &, const Msp::FS::Path &) const override;
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
 
-       Task *run(const Target &) const override;
+private:
+       static Task *_run(const SourceFile &);
 };
 
 #endif
index 446aa922a0c6baba68209219b800f57fc3dd0f61..07c14ce9282f3dcab5cf26bc2aaae46acc43501d 100644 (file)
@@ -16,6 +16,7 @@ Tar::Tar(Builder &b):
        Tool(b, "TAR")
 {
        processing_unit = COMPONENT;
+       set_run_internal(&_run);
 }
 
 Target *Tar::create_target(const vector<Target *> &sources, const string &arg)
@@ -32,12 +33,6 @@ Target *Tar::create_target(const vector<Target *> &sources, const string &arg)
        return tarball;
 }
 
-Task *Tar::run(const Target &target) const
-{
-       const TarBall &tarball = dynamic_cast<const TarBall &>(target);
-       return new InternalTask([&tarball]{ return _run(tarball); });
-}
-
 bool Tar::_run(const TarBall &tarball)
 {
        const FS::Path &pkg_src = tarball.get_package()->get_source_directory();
index fa4a4d6070100098f3da70520caa7efa696cac4f..befebb814db6f7e95dd5f58a94ffa66c562e11dc 100644 (file)
@@ -11,7 +11,6 @@ public:
        Tar(Builder &);
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
-       Task *run(const Target &) const override;
 
 private:
        static bool _run(const TarBall &);
index 852fa2d5805b294b4d74b5a5ab165039b08feaad..402d20d0b8722ae09d09e15af9eec27955180cae 100644 (file)
@@ -20,6 +20,11 @@ void Tool::set_command(const string &cmd, bool cross)
                command = cmd;
 }
 
+void Tool::set_run(function<Task *(const Target &)> f)
+{
+       run_func = move(f);
+}
+
 bool Tool::accepts_suffix(const string &suffix, bool aux) const
 {
        return (any_equals(input_suffixes, suffix) || (aux && any_equals(aux_suffixes, suffix)));
index 6fa4fb5c127090bf81a0ded5574c14bd2aa0bc69..ec5bf02b37d9fbf29b94eac121c82f0131f7fca8 100644 (file)
@@ -1,10 +1,12 @@
 #ifndef TOOL_H_
 #define TOOL_H_
 
+#include <functional>
 #include <string>
 #include <vector>
 #include <msp/fs/path.h>
 #include "buildinfo.h"
+#include "internaltask.h"
 #include "virtualfilesystem.h"
 
 class Architecture;
@@ -13,7 +15,6 @@ class BuildInfo;
 class Component;
 class FileTarget;
 class Target;
-class Task;
 
 /**
 Base class for tools.  Tools are used to turn targets into other targets.
@@ -40,6 +41,7 @@ protected:
        ProcessingUnit processing_unit = ONE_FILE;
        VirtualFileSystem::SearchPath system_path;
        BuildInfo build_info;
+       std::function<Task *(const Target &)> run_func;
        bool prepared = false;
        std::vector<std::string> problems;
 
@@ -50,12 +52,24 @@ private:
 public:
        virtual ~Tool() { }
 
+       Builder &get_builder() const { return builder; }
+
        const std::string &get_tag() const { return tag; }
 
        /** Returns the architecture this tool builds for.  May return null if the
        tool is architecture-agnostic. */
        const Architecture *get_architecture() const { return architecture; }
 
+protected:
+       void set_run(std::function<Task *(const Target &)>);
+
+       template<typename T>
+       void set_run(Task *(*)(const T &));
+
+       template<typename T>
+       void set_run_internal(bool (*)(const T &));
+
+public:
        /** Overrides the command used by the tool.  The new command should accept
        the same command line arguments.  Only works on tools that use an external
        command.  If cross is true and the architecture is not native, a cross
@@ -120,7 +134,7 @@ public:
 
        /** Invokes the tool to build a target.  This should not be called directly;
        use Target::build() instead. */
-       virtual Task *run(const Target &) const = 0;
+       Task *run(const Target &t) const { return run_func(t); }
 };
 
 /**
@@ -144,6 +158,22 @@ public:
 };
 
 
+template<typename T>
+void Tool::set_run(Task *(*f)(const T &))
+{
+       set_run([f](const Target &t){ return f(dynamic_cast<const T &>(t)); });
+}
+
+template<typename T>
+void Tool::set_run_internal(bool (*f)(const T &))
+{
+       set_run([f](const Target &t){
+               const T &ct = dynamic_cast<const T &>(t);
+               return new InternalTask([f, &ct]{ return f(ct); });
+       });
+}
+
+
 void operator>>(const Msp::LexicalConverter &, Tool::ProcessingUnit &);
 
 #endif
index bafa8d94f42ee629d84454171be34514e4b603e5..8cfc12aa28b9570f8075f603b901d67ea7c4197b 100644 (file)
 using namespace std;
 using namespace Msp;
 
-Target *VcxProjectGenerator::create_target(const vector<Target *> &, const string &)
+VcxProjectGenerator::VcxProjectGenerator(Builder &b):
+       Tool(b, "VCXG")
 {
-       throw logic_error("Not implemented");
+       set_run_internal(_run);
 }
 
-Task *VcxProjectGenerator::run(const Target &target) const
+Target *VcxProjectGenerator::create_target(const vector<Target *> &, const string &)
 {
-       const VcxProjectFile &project = dynamic_cast<const VcxProjectFile &>(target);
-       return new InternalTask([&project]{ return _run(project); });
+       throw logic_error("Not implemented");
 }
 
 bool VcxProjectGenerator::_run(const VcxProjectFile &project)
index 05f740183d26abf9bd719e7701f4576cfe810c9a..f8283ff2fe16d900e3c6b169c078665bde61646a 100644 (file)
@@ -8,10 +8,9 @@ class VcxProjectFile;
 class VcxProjectGenerator: public Tool
 {
 public:
-       VcxProjectGenerator(Builder &b): Tool(b, "VCXG") { }
+       VcxProjectGenerator(Builder &);
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
-       Task *run(const Target &) const override;
 
 private:
        static bool _run(const VcxProjectFile &);
index 5fd8e4dff2a10d0371227f9f76c136ef0d04ba4b..7dce0767e78ebd1138966d80442c80e9606c1436 100644 (file)
 using namespace std;
 using namespace Msp;
 
-Target *VsSolutionGenerator::create_target(const vector<Target *> &, const string &)
+VsSolutionGenerator::VsSolutionGenerator(Builder &b):
+       Tool(b, "VSSG")
 {
-       throw logic_error("Not implemented");
+       set_run_internal(_run);
 }
 
-Task *VsSolutionGenerator::run(const Target &target) const
+Target *VsSolutionGenerator::create_target(const vector<Target *> &, const string &)
 {
-       const VsSolutionFile &solution = dynamic_cast<const VsSolutionFile &>(target);
-       return new InternalTask([&solution]{ return _run(solution); });
+       throw logic_error("Not implemented");
 }
 
 bool VsSolutionGenerator::_run(const VsSolutionFile &solution)
index b7eaf31c056256ca13993d1daf3c58d0c3431400..ca332374f33875e04751fc1a5a28821897a723a2 100644 (file)
@@ -8,10 +8,9 @@ class VsSolutionFile;
 class VsSolutionGenerator: public Tool
 {
 public:
-       VsSolutionGenerator(Builder &b): Tool(b, "VSSG") { }
+       VsSolutionGenerator(Builder &);
 
        Target *create_target(const std::vector<Target *> &, const std::string &) override;
-       Task *run(const Target &) const override;
 
 private:
        static bool _run(const VsSolutionFile &);