]> git.tdb.fi Git - builder.git/blob - source/tool.h
b756563242ba4099152f0ce125bd93a6504d9ffb
[builder.git] / source / tool.h
1 #ifndef TOOL_H_
2 #define TOOL_H_
3
4 #include <functional>
5 #include <string>
6 #include <vector>
7 #include <msp/fs/path.h>
8 #include "buildinfo.h"
9 #include "externaltask.h"
10 #include "internaltask.h"
11 #include "sourcepackage.h"
12 #include "target.h"
13 #include "virtualfilesystem.h"
14
15 class Architecture;
16 class Builder;
17 class BuildInfo;
18 class Component;
19 class FileTarget;
20
21 class ToolData
22 {
23 public:
24         VirtualFileSystem::SearchPath system_path;
25         BuildInfo build_info;
26         Msp::Variant extra_data;
27         std::vector<std::string> problems;
28 };
29
30 /**
31 Base class for tools.  Tools are used to turn targets into other targets.
32 Examples include compilers and linkers.
33 */
34 class Tool: protected ToolData
35 {
36 public:
37         enum ProcessingUnit
38         {
39                 ONE_FILE,
40                 DIRECTORY,
41                 COMPONENT
42         };
43
44 protected:
45         Builder &builder;
46         const Architecture *architecture = 0;
47         std::string tag;
48         std::string command;
49         FileTarget *executable = 0;
50         std::vector<std::string> input_suffixes;
51         std::vector<std::string> aux_suffixes;
52         ProcessingUnit processing_unit = ONE_FILE;
53         std::function<Task *(const Target &)> run_func;
54         bool prepared = false;
55
56         Tool(Builder &b, const std::string &t): Tool(b, 0, t) { }
57         Tool(Builder &b, const Architecture *a, const std::string &t): builder(b), architecture(a), tag(t) { }
58
59 public:
60         virtual ~Tool() { }
61
62         Builder &get_builder() const { return builder; }
63
64         const std::string &get_tag() const { return tag; }
65
66         /** Returns the architecture this tool builds for.  May return null if the
67         tool is architecture-agnostic. */
68         const Architecture *get_architecture() const { return architecture; }
69
70         virtual const Tool *get_base_tool() const { return this; }
71
72 protected:
73         void set_run(std::function<Task *(const Target &)>);
74
75         template<typename T>
76         void set_run_external(ExternalTask::Arguments (*)(const T &, Msp::FS::Path &));
77
78         template<typename T>
79         void set_run_internal(bool (*)(const T &));
80
81 public:
82         /** Overrides the command used by the tool.  The new command should accept
83         the same command line arguments.  Only works on tools that use an external
84         command.  If cross is true and the architecture is not native, a cross
85         prefix is added to the command.  May have no effect after prepare() has been
86         called. */
87         void set_command(const std::string &cmd, bool cross = false);
88
89         /** Returns a target for the tool's own executable.  If the tool does not
90         use an external program, returns null.  The tool must be prepared first. */
91         FileTarget *get_executable() const { return executable; }
92
93         /// Returns a list of suffixes that can be processed with this tool.
94         const std::vector<std::string> &get_input_suffixes() const { return input_suffixes; }
95
96         /** Returns a list of suffixes that are associated with this tool, but can't
97         be processed directly.  For example C and C++ headers. */
98         const std::vector<std::string> &get_auxiliary_suffixes() const { return aux_suffixes; }
99
100         /** Indicates whether the tool can accept a suffix.  If aux is true,
101         auxiliary suffixes are considered as well */
102         bool accepts_suffix(const std::string &, bool aux = false) const;
103
104         /** Returns the grouping unit this tool prefers to process. */
105         ProcessingUnit get_processing_unit() const { return processing_unit; }
106
107         /// Returns the systemwide search path for source files.
108         const VirtualFileSystem::SearchPath &get_system_path() const { return system_path; }
109
110         /** Returns tool-specific build info.  This can be used by other tools down
111         the chain. */
112         const BuildInfo &get_build_info() const { return build_info; }
113
114         const Msp::Variant &get_extra_data() const { return extra_data; }
115
116         /// Creates a source file appropriate for this tool.
117         virtual Target *create_source(const Component &, const Msp::FS::Path &) const { return 0; }
118
119         /** Creates a package-less source file appropriate for this tool.  This is
120         called during dependency discovery when no package has created a target for
121         the file. */
122         virtual Target *create_source(const Msp::FS::Path &) const { return 0; }
123
124         /// Convenience function to create a target from a single source.
125         Target *create_target(Target &, const std::string & = std::string());
126
127         /** Creates a target from sources.  The exact types of accepted sources
128         depends on the tool.  The optional second argument can be used to select an
129         alternative target type for tools that can create multiple kinds of targets. */ 
130         virtual Target *create_target(const std::vector<Target *> &, const std::string & = std::string()) = 0;
131
132         /** Creates an install target for a target created by this tool.  Can return
133         null if the tool does not want to handle installing in a special way. */
134         virtual Target *create_install(Target &) const { return 0; }
135
136         virtual std::string create_build_signature(const BuildInfo &) const;
137
138         void prepare();
139         void prepare(Tool &) const;
140
141 protected:
142         virtual void do_prepare(ToolData &) const { }
143
144 public:
145         const std::vector<std::string> &get_problems() const { return problems; }
146
147         /** Invokes the tool to build a target.  This should not be called directly;
148         use Target::build() instead. */
149         Task *run(const Target &t) const { return run_func(t); }
150 };
151
152
153 template<typename T>
154 void Tool::set_run_external(ExternalTask::Arguments (*f)(const T &, Msp::FS::Path &))
155 {
156         set_run([f](const Target &t){
157                 Msp::FS::Path work_dir = t.get_package()->get_source_directory();
158                 ExternalTask::Arguments args = f(dynamic_cast<const T &>(t), work_dir);
159                 return new ExternalTask(args, work_dir);
160         });
161 }
162
163 template<typename T>
164 void Tool::set_run_internal(bool (*f)(const T &))
165 {
166         set_run([f](const Target &t){
167                 const T &ct = dynamic_cast<const T &>(t);
168                 return new InternalTask([f, &ct]{ return f(ct); });
169         });
170 }
171
172
173 void operator>>(const Msp::LexicalConverter &, Tool::ProcessingUnit &);
174
175 #endif