]> git.tdb.fi Git - builder.git/blob - source/target.cpp
Reorder class members
[builder.git] / source / target.cpp
1 /* $Id$
2
3 This file is part of builder
4 Copyright © 2006-2009  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <msp/fs/stat.h>
9 #include <msp/fs/utils.h>
10 #include <msp/time/utils.h>
11 #include "action.h"
12 #include "builder.h"
13 #include "package.h"
14 #include "sourcepackage.h"
15 #include "target.h"
16
17 using namespace std;
18 using namespace Msp;
19
20 Target::Target(Builder &b, const Package *p, const string &n):
21         builder(b),
22         package(p),
23         name(n),
24         buildable(false),
25         building(false),
26         rebuild(false),
27         deps_ready(false),
28         prepared(false),
29         counted(false)
30 {
31         builder.add_target(this);
32
33         struct stat st;
34         if(!FS::stat(name, st))
35                 mtime=Time::TimeStamp::from_unixtime(st.st_mtime);
36 }
37
38 Target *Target::get_buildable_target()
39 {
40         if(!rebuild)
41                 return 0;
42
43         bool self_ok=!building;
44         for(TargetList::iterator i=depends.begin(); i!=depends.end(); ++i)
45         {
46                 Target *tgt=(*i)->get_buildable_target();
47                 if(tgt)
48                         return tgt;
49                 else if((*i)->get_rebuild())
50                         self_ok=false;
51         }
52
53         if(self_ok)
54                 return this;
55
56         return 0;
57 }
58
59 void Target::add_depend(Target *dep)
60 {
61         if(dep==this)
62                 throw InvalidParameterValue("A target can't depend on itself");
63         depends.push_back(dep);
64         dep->rdepends.push_back(this);
65 }
66
67 void Target::prepare()
68 {
69         if(prepared)
70                 return;
71
72         prepared=true;
73         for(TargetList::iterator i=depends.begin(); i!=depends.end(); ++i)
74                 (*i)->prepare();
75
76         check_rebuild();
77
78 }
79
80 Action *Target::build()
81 {
82         if(!buildable)
83         {
84                 rebuild=false;
85                 return 0;
86         }
87
88         if(!builder.get_dry_run() && FS::exists(name))
89                 FS::unlink(name);
90
91         Action *action=create_action();
92         if(action)
93         {
94                 action->signal_done.connect(sigc::mem_fun(this, &Target::build_done));
95
96                 building=true;
97         }
98
99         return action;
100 }
101
102 unsigned Target::count_rebuild()
103 {
104         if(counted)
105                 return 0;
106
107         counted=true;
108         unsigned count=rebuild;
109         for(TargetList::iterator i=depends.begin(); i!=depends.end(); ++i)
110                 count+=(*i)->count_rebuild();
111         return count;
112 }
113
114 void Target::touch()
115 {
116         mtime=Time::now();
117 }
118
119 void Target::mark_rebuild(const std::string &reason)
120 {
121         rebuild=true;
122         rebuild_reason=reason;
123 }
124
125 void Target::check_rebuild()
126 {
127         if(!buildable)
128                 return;
129
130         if(builder.get_build_all())
131                 mark_rebuild("Rebuilding everything");
132         else if(!mtime)
133                 mark_rebuild("Does not exist");
134         else
135         {
136                 for(TargetList::iterator i=depends.begin(); (i!=depends.end() && !rebuild); ++i)
137                 {
138                         if((*i)->get_mtime()>mtime)
139                                 mark_rebuild(FS::basename((*i)->get_name())+" has changed");
140                         else if((*i)->get_rebuild())
141                                 mark_rebuild(FS::basename((*i)->get_name())+" needs rebuilding");
142                 }
143         }
144
145         const SourcePackage *spkg=dynamic_cast<const SourcePackage *>(package);
146         if(!rebuild && spkg && spkg->get_config().get_mtime()>mtime)
147                 mark_rebuild("Package options changed");
148 }
149
150 void Target::build_done()
151 {
152         building=false;
153         rebuild=false;
154 }