#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;
class Component;
class FileTarget;
class Target;
-class Task;
/**
Base class for tools. Tools are used to turn targets into other targets.
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;
+ ProcessingUnit processing_unit = ONE_FILE;
VirtualFileSystem::SearchPath system_path;
BuildInfo build_info;
- bool prepared;
+ std::function<Task *(const Target &)> run_func;
+ bool prepared = false;
std::vector<std::string> problems;
- Tool(Builder &, const std::string &);
- Tool(Builder &, const Architecture &, const std::string &);
+ Tool(Builder &b, const std::string &t): Tool(b, 0, t) { }
+ Tool(Builder &b, const Architecture &a, const std::string &t): Tool(b, &a, t) { }
+private:
+ Tool(Builder &b, const Architecture *a, const std::string &t): builder(b), architecture(a), tag(t) { }
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; }
+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
/** 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); }
};
/**
protected:
Tool &parent;
- SubTool(Tool &);
+ SubTool(Tool &t): Tool(t), parent(t) { }
public:
Target *create_source(const Component &, const Msp::FS::Path &) const override;
};
+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