]> git.tdb.fi Git - builder.git/blobdiff - source/tool.h
Refactor the use of external tasks in tools
[builder.git] / source / tool.h
index ce08a00af62aedc0aae64b8d901d579881103797..b756563242ba4099152f0ce125bd93a6504d9ffb 100644 (file)
@@ -1,10 +1,15 @@
 #ifndef TOOL_H_
 #define TOOL_H_
 
+#include <functional>
 #include <string>
 #include <vector>
 #include <msp/fs/path.h>
 #include "buildinfo.h"
+#include "externaltask.h"
+#include "internaltask.h"
+#include "sourcepackage.h"
+#include "target.h"
 #include "virtualfilesystem.h"
 
 class Architecture;
@@ -12,14 +17,21 @@ class Builder;
 class BuildInfo;
 class Component;
 class FileTarget;
-class Target;
-class Task;
+
+class ToolData
+{
+public:
+       VirtualFileSystem::SearchPath system_path;
+       BuildInfo build_info;
+       Msp::Variant extra_data;
+       std::vector<std::string> problems;
+};
 
 /**
 Base class for tools.  Tools are used to turn targets into other targets.
 Examples include compilers and linkers.
 */
-class Tool
+class Tool: protected ToolData
 {
 public:
        enum ProcessingUnit
@@ -31,29 +43,42 @@ public:
 
 protected:
        Builder &builder;
-       const Architecture *architecture;
+       const Architecture *architecture = 0;
        std::string tag;
        std::string command;
-       FileTarget *executable;
+       FileTarget *executable = 0;
        std::vector<std::string> input_suffixes;
        std::vector<std::string> aux_suffixes;
-       ProcessingUnit processing_unit;
-       VirtualFileSystem::SearchPath system_path;
-       BuildInfo build_info;
-       bool prepared;
-       std::vector<std::string> problems;
+       ProcessingUnit processing_unit = ONE_FILE;
+       std::function<Task *(const Target &)> run_func;
+       bool prepared = false;
+
+       Tool(Builder &b, const std::string &t): Tool(b, 0, t) { }
+       Tool(Builder &b, const Architecture *a, const std::string &t): builder(b), architecture(a), tag(t) { }
 
-       Tool(Builder &, const std::string &);
-       Tool(Builder &, const Architecture &, const std::string &);
 public:
        virtual ~Tool() { }
 
+       Builder &get_builder() const { return builder; }
+
        const std::string &get_tag() const { return tag; }
 
-       /** Returns the architecture this tool build for.  May return null if the
+       /** Returns the architecture this tool builds for.  May return null if the
        tool is architecture-agnostic. */
        const Architecture *get_architecture() const { return architecture; }
 
+       virtual const Tool *get_base_tool() const { return this; }
+
+protected:
+       void set_run(std::function<Task *(const Target &)>);
+
+       template<typename T>
+       void set_run_external(ExternalTask::Arguments (*)(const T &, Msp::FS::Path &));
+
+       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
@@ -86,6 +111,8 @@ public:
        the chain. */
        const BuildInfo &get_build_info() const { return build_info; }
 
+       const Msp::Variant &get_extra_data() const { return extra_data; }
+
        /// Creates a source file appropriate for this tool.
        virtual Target *create_source(const Component &, const Msp::FS::Path &) const { return 0; }
 
@@ -109,37 +136,38 @@ public:
        virtual std::string create_build_signature(const BuildInfo &) const;
 
        void prepare();
+       void prepare(Tool &) const;
 
 protected:
-       virtual void do_prepare() { }
+       virtual void do_prepare(ToolData &) const { }
 
 public:
        const std::vector<std::string> &get_problems() const { return problems; }
 
        /** 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); }
 };
 
-/**
-Intermediate base class for tool facets.  For example, a linker may need to
-use different commands depending on whether C++ source files are present or
-not, but their presence can't be directly determined from the object files.
-*/
-class SubTool: public Tool
-{
-protected:
-       Tool &parent;
-
-       SubTool(Tool &);
 
-public:
-       Target *create_source(const Component &, const Msp::FS::Path &) const override;
-       Target *create_source(const Msp::FS::Path &) const override;
-       Target *create_target(const std::vector<Target *> &, const std::string & = std::string()) override;
-       Target *create_install(Target &) const override;
-       std::string create_build_signature(const BuildInfo &) const override;
-};
+template<typename T>
+void Tool::set_run_external(ExternalTask::Arguments (*f)(const T &, Msp::FS::Path &))
+{
+       set_run([f](const Target &t){
+               Msp::FS::Path work_dir = t.get_package()->get_source_directory();
+               ExternalTask::Arguments args = f(dynamic_cast<const T &>(t), work_dir);
+               return new ExternalTask(args, work_dir);
+       });
+}
+
+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 &);