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