]> git.tdb.fi Git - builder.git/blob - source/lib/tool.h
Add visibility decorations to the library and plugins
[builder.git] / source / lib / 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 "libbuilder_api.h"
12 #include "sourcepackage.h"
13 #include "target.h"
14 #include "virtualfilesystem.h"
15
16 class Architecture;
17 class Builder;
18 class BuildInfo;
19 class Component;
20 class FileTarget;
21
22 class ToolData
23 {
24 public:
25         VirtualFileSystem::SearchPath system_path;
26         BuildInfo build_info;
27         Msp::Variant extra_data;
28         std::vector<std::string> problems;
29 };
30
31 /**
32 Base class for tools.  Tools are used to turn targets into other targets.
33 Examples include compilers and linkers.
34 */
35 class LIBBUILDER_API Tool: protected ToolData
36 {
37 public:
38         enum ProcessingUnit
39         {
40                 ONE_FILE,
41                 DIRECTORY,
42                 COMPONENT
43         };
44
45 protected:
46         Builder &builder;
47         const Architecture *architecture = 0;
48         std::string tag;
49         std::string command;
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;
56
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) { }
59
60 public:
61         virtual ~Tool() { }
62
63         Builder &get_builder() const { return builder; }
64
65         const std::string &get_tag() const { return tag; }
66
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; }
70
71         virtual const Tool *get_base_tool() const { return this; }
72
73 protected:
74         void set_run(std::function<Task *(const Target &)>);
75
76         template<typename T>
77         void set_run_external(ExternalTask::Arguments (*)(const T &, Msp::FS::Path &));
78
79         template<typename T>
80         void set_run_internal(bool (*)(const T &));
81
82 public:
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
87         called. */
88         void set_command(const std::string &cmd, bool cross = false);
89
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; }
93
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; }
96
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; }
100
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;
104
105         /** Returns the grouping unit this tool prefers to process. */
106         ProcessingUnit get_processing_unit() const { return processing_unit; }
107
108         /// Returns the systemwide search path for source files.
109         const VirtualFileSystem::SearchPath &get_system_path() const { return system_path; }
110
111         /** Returns tool-specific build info.  This can be used by other tools down
112         the chain. */
113         const BuildInfo &get_build_info() const { return build_info; }
114
115         const Msp::Variant &get_extra_data() const { return extra_data; }
116
117         /// Creates a source file appropriate for this tool.
118         virtual Target *create_source(const Component &, const Msp::FS::Path &) const { return 0; }
119
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
122         the file. */
123         virtual Target *create_source(const Msp::FS::Path &) const { return 0; }
124
125         /// Convenience function to create a target from a single source.
126         Target *create_target(Target &, const std::string & = std::string());
127
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;
132
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; }
136
137         virtual std::string create_build_signature(const BuildInfo &) const;
138
139         void prepare();
140         void prepare(Tool &) const;
141
142 protected:
143         virtual void do_prepare(ToolData &) const { }
144
145 public:
146         bool is_broken() const { return !problems.empty(); }
147         const std::vector<std::string> &get_problems() const { return problems; }
148
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); }
152 };
153
154
155 template<typename T>
156 void Tool::set_run_external(ExternalTask::Arguments (*f)(const T &, Msp::FS::Path &))
157 {
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);
162         });
163 }
164
165 template<typename T>
166 void Tool::set_run_internal(bool (*f)(const T &))
167 {
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); });
171         });
172 }
173
174
175 void operator>>(const Msp::LexicalConverter &, Tool::ProcessingUnit &);
176
177 #endif