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