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