]> git.tdb.fi Git - builder.git/blob - source/lib/target.h
Refactor transitive dependencies to work on all targets
[builder.git] / source / lib / target.h
1 #ifndef TARGET_H_
2 #define TARGET_H_
3
4 #include <map>
5 #include <set>
6 #include <string>
7 #include <vector>
8 #include <sigc++/signal.h>
9 #include <msp/core/noncopyable.h>
10 #include <msp/time/timestamp.h>
11 #include "libbuilder_api.h"
12
13 class Builder;
14 class BuildInfo;
15 class Component;
16 class SourcePackage;
17 class Task;
18 class Tool;
19
20 /**
21 Targets make up the build graph.  This class is a base for all target types and
22 handles many common tasks.  See also FileTarget and VirtualTarget.
23
24 Targets can depend on other targets.  There are two kinds of dependencies:
25 normal and transitive.  Normal dependencies will need to be built before the
26 target itself, and will cause the target to be rebuilt if modified.  Transitive
27 dependencies can be used by other targets further down the chain.
28 */
29 class LIBBUILDER_API Target
30 {
31 public:
32         using Dependencies = std::vector<Target *>;
33
34 protected:
35         enum State
36         {
37                 INIT,
38                 PREPARING,
39                 REBUILD,
40                 BUILDING,
41                 UPTODATE,
42                 BROKEN
43         };
44
45         struct PushPrepare: Msp::NonCopyable
46         {
47                 PushPrepare(Target *t) { prepare_stack.push_back(t); }
48                 ~PushPrepare() { prepare_stack.pop_back(); }
49         };
50
51 public:
52         sigc::signal<void> signal_bubble_rebuild;
53         sigc::signal<void> signal_modified;
54
55 protected:
56         Builder &builder;
57         const SourcePackage *package = 0;
58         const Component *component = 0;
59         std::string name;
60
61         Tool *tool = 0;
62         State state = INIT;
63         std::string rebuild_reason;
64         std::vector<std::string> problems;
65
66         Dependencies depends;
67         Dependencies trans_depends;
68         Dependencies side_effects;
69         Target *primary_target = 0;
70         bool rescan_trans_deps = false;
71
72         static std::vector<Target *> prepare_stack;
73
74         Target(Builder &, const std::string &);
75 public:
76         virtual ~Target() { }
77
78         virtual const char *get_type() const = 0;
79         const std::string &get_name() const { return name; }
80         const SourcePackage *get_package() const { return package; }
81         const Component *get_component() const { return component; }
82
83         /** Adds a dependency for the target.  Order is preseved and is important
84         for some target types.  It is an error to create dependency cycles, although
85         this won't be detected until the targets are prepared. */
86         void add_dependency(Target &);
87
88         void add_transitive_dependency(Target &);
89
90         /** Adds a side effect for the target.  Side effects are not built on their
91         own, but together with their primary target. */
92         void add_side_effect(Target &);
93
94 protected:
95         /** Finds dependencies for the target.  Called during preparation.  If the
96         target needs to recursively inspect its dependencies, it should prepare its
97         direct dependencies first. */
98         virtual void find_dependencies() { }
99
100 private:
101         bool find_transitive_dependencies();
102         void find_transitive_dependencies(Target &, std::vector<Target *> &) const;
103
104 protected:
105         virtual Target *resolve_transitive_dependency(Target &, Target &dep) const { return &dep; }
106
107 public:
108         /// Returns the dependencies of the target, in the order they were added.
109         const Dependencies &get_dependencies() const { return depends; }
110
111         const Dependencies &get_transitive_dependencies() const { return trans_depends; }
112
113         /// Returns the side effects of the target.
114         const Dependencies &get_side_effects() const { return side_effects; }
115
116         /// Returns the primary target associated with a side effect target.
117         Target *get_primary_target() const { return primary_target; }
118
119         /** Tries to locate a target that will help getting this target built.  If
120         all dependencies are up-to-date, returns this target.  If there are no
121         targets ready to be built (maybe because they are being built right now),
122         returns 0. */
123         virtual Target *get_buildable_target();
124
125         /** If this target is a proxy for another (such as InstalledFile), return
126         that target.  Otherwise, return the target itself.  Implementors should call
127         the function recursively to find the final target. */
128         virtual Target *get_real_target() { return this; }
129
130         void set_tool(Tool &);
131
132         /** Returns the tool used to build the target.  To actually build it, call
133         the build() function. */
134         const Tool *get_tool() const { return tool; }
135
136         virtual void collect_build_info(BuildInfo &) const;
137
138         /** Indicates if it's possible to build this target. */
139         bool is_buildable() const { return tool!=0; }
140
141         /** Indicates if this target needs rebuilding.  Only makes sense after the
142         target has been prepared. */
143         bool needs_rebuild() const { return state>PREPARING && state<UPTODATE; }
144
145         /** Returns the reason for rebuilding this target.  Only makes sense after
146         the target has been prepared. */
147         const std::string &get_rebuild_reason() const { return rebuild_reason; }
148
149         /** Forces rebuild of the target. */
150         void force_rebuild();
151
152 protected:
153         /** Marks the target to be rebuilt and specified a reason for it. */
154         void mark_rebuild(const std::string &);
155
156         /** Checks if the target needs to be rebuilt and why. */
157         virtual void check_rebuild() = 0;
158
159 public:
160         bool is_broken() const { return state==BROKEN; }
161
162         const std::vector<std::string> &get_problems() const { return problems; }
163
164         /** Prepares the target by finding dependencies, recursively preparing them
165         and then checking whether rebuilding is needed. */
166         void prepare();
167
168         /** Invokes the associated Tool to build the target and returns the
169         resulting Task.  The task must be started by the caller. */
170         virtual Task *build();
171
172 protected:
173         /** Targets can override this to do additional setup on the Task.  This is
174         also called on side effects, which normally do not get built by themselves. */
175         virtual void build(Task &) { }
176
177         /** Handler for Task::signal_finished. */
178         virtual void build_finished(bool);
179
180         virtual void modified() { }
181
182 public:
183         /** Removes any results of building the target. */
184         virtual void clean() { }
185 };
186
187 #endif