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