7 #include <msp/fs/path.h>
9 #include "externaltask.h"
10 #include "internaltask.h"
11 #include "libbuilder_api.h"
12 #include "sourcepackage.h"
14 #include "virtualfilesystem.h"
25 VirtualFileSystem::SearchPath system_path;
27 Msp::Variant extra_data;
28 std::vector<std::string> problems;
32 Base class for tools. Tools are used to turn targets into other targets.
33 Examples include compilers and linkers.
35 class LIBBUILDER_API Tool: protected ToolData
47 const Architecture *architecture = 0;
50 FileTarget *executable = 0;
51 std::vector<std::string> input_suffixes;
52 std::vector<std::string> aux_suffixes;
53 ProcessingUnit processing_unit = ONE_FILE;
54 std::function<Task *(const Target &)> run_func;
55 bool prepared = false;
57 Tool(Builder &b, const std::string &t): Tool(b, 0, t) { }
58 Tool(Builder &b, const Architecture *a, const std::string &t): builder(b), architecture(a), tag(t) { }
63 Builder &get_builder() const { return builder; }
65 const std::string &get_tag() const { return tag; }
67 /** Returns the architecture this tool builds for. May return null if the
68 tool is architecture-agnostic. */
69 const Architecture *get_architecture() const { return architecture; }
71 virtual const Tool *get_base_tool() const { return this; }
74 void set_run(std::function<Task *(const Target &)>);
77 void set_run_external(ExternalTask::Arguments (*)(const T &, Msp::FS::Path &));
80 void set_run_internal(bool (*)(const T &));
83 /** Overrides the command used by the tool. The new command should accept
84 the same command line arguments. Only works on tools that use an external
85 command. If cross is true and the architecture is not native, a cross
86 prefix is added to the command. May have no effect after prepare() has been
88 void set_command(const std::string &cmd, bool cross = false);
90 /** Returns a target for the tool's own executable. If the tool does not
91 use an external program, returns null. The tool must be prepared first. */
92 FileTarget *get_executable() const { return executable; }
94 /// Returns a list of suffixes that can be processed with this tool.
95 const std::vector<std::string> &get_input_suffixes() const { return input_suffixes; }
97 /** Returns a list of suffixes that are associated with this tool, but can't
98 be processed directly. For example C and C++ headers. */
99 const std::vector<std::string> &get_auxiliary_suffixes() const { return aux_suffixes; }
101 /** Indicates whether the tool can accept a suffix. If aux is true,
102 auxiliary suffixes are considered as well */
103 bool accepts_suffix(const std::string &, bool aux = false) const;
105 /** Returns the grouping unit this tool prefers to process. */
106 ProcessingUnit get_processing_unit() const { return processing_unit; }
108 /// Returns the systemwide search path for source files.
109 const VirtualFileSystem::SearchPath &get_system_path() const { return system_path; }
111 /** Returns tool-specific build info. This can be used by other tools down
113 const BuildInfo &get_build_info() const { return build_info; }
115 const Msp::Variant &get_extra_data() const { return extra_data; }
117 /// Creates a source file appropriate for this tool.
118 virtual Target *create_source(const Component &, const Msp::FS::Path &) const { return 0; }
120 /** Creates a package-less source file appropriate for this tool. This is
121 called during dependency discovery when no package has created a target for
123 virtual Target *create_source(const Msp::FS::Path &) const { return 0; }
125 /// Convenience function to create a target from a single source.
126 Target *create_target(Target &, const std::string & = std::string());
128 /** Creates a target from sources. The exact types of accepted sources
129 depends on the tool. The optional second argument can be used to select an
130 alternative target type for tools that can create multiple kinds of targets. */
131 virtual Target *create_target(const std::vector<Target *> &, const std::string & = std::string()) = 0;
133 /** Creates an install target for a target created by this tool. Can return
134 null if the tool does not want to handle installing in a special way. */
135 virtual Target *create_install(Target &) const { return 0; }
137 virtual std::string create_build_signature(const BuildInfo &) const;
140 void prepare(Tool &) const;
143 virtual void do_prepare(ToolData &) const { }
146 bool is_broken() const { return !problems.empty(); }
147 const std::vector<std::string> &get_problems() const { return problems; }
149 /** Invokes the tool to build a target. This should not be called directly;
150 use Target::build() instead. */
151 Task *run(const Target &t) const { return run_func(t); }
156 void Tool::set_run_external(ExternalTask::Arguments (*f)(const T &, Msp::FS::Path &))
158 set_run([f](const Target &t){
159 Msp::FS::Path work_dir = t.get_package()->get_source_directory();
160 ExternalTask::Arguments args = f(dynamic_cast<const T &>(t), work_dir);
161 return new ExternalTask(args, work_dir);
166 void Tool::set_run_internal(bool (*f)(const T &))
168 set_run([f](const Target &t){
169 const T &ct = dynamic_cast<const T &>(t);
170 return new InternalTask([f, &ct]{ return f(ct); });
175 void operator>>(const Msp::LexicalConverter &, Tool::ProcessingUnit &);