1 #include <msp/core/algorithm.h>
2 #include <msp/fs/stat.h>
3 #include <msp/fs/utils.h>
4 #include <msp/strings/utils.h>
6 #include "filetarget.h"
7 #include "sourcepackage.h"
15 vector<Target *> Target::prepare_stack;
17 Target::Target(Builder &b, const string &n):
21 builder.get_build_graph().add_target(this);
24 void Target::add_dependency(Target &dep)
27 throw invalid_argument("Target::add_depend");
28 depends.push_back(&dep);
30 dep.signal_bubble_rebuild.connect(sigc::mem_fun(this, &Target::check_rebuild));
33 void Target::add_transitive_dependency(Target &dep)
36 throw invalid_argument("Target::add_transitive_dependency");
37 trans_depends.push_back(&dep);
40 void Target::add_side_effect(Target &se)
42 side_effects.push_back(&se);
45 se.primary_target = this;
46 /* Side effects are checked for rebuild after the primary target. Recheck
47 the primary if a side effect is marked for rebuild. */
48 se.signal_bubble_rebuild.connect(sigc::mem_fun(this, &Target::check_rebuild));
51 Target *Target::get_buildable_target()
54 return primary_target->get_buildable_target();
58 bool self_ok = state!=BUILDING;
59 for(Target *d: depends)
61 // Avoid infinite recursion if a target depends on its own side effect
62 if(any_equals(side_effects, d))
65 Target *tgt = d->get_buildable_target();
68 else if(d->needs_rebuild())
78 void Target::set_tool(Tool &t)
81 for(Target *s: side_effects)
85 void Target::collect_build_info(BuildInfo &binfo) const
88 binfo.update_from(tool->get_build_info());
90 binfo.update_from(component->get_build_info());
92 binfo.update_from(package->get_build_info());
95 void Target::force_rebuild()
98 throw logic_error("Target::force_rebuild");
99 mark_rebuild("Forced rebuild");
102 void Target::mark_rebuild(const string &reason)
105 throw invalid_argument("No reason given for rebuilding "+name);
108 rebuild_reason = reason;
110 builder.get_logger().log("rebuild", "Rebuilding %s: %s", name, reason);
112 signal_bubble_rebuild.emit();
115 void Target::prepare()
117 if(primary_target && primary_target->state<PREPARING)
118 primary_target->prepare();
124 auto i = find(prepare_stack, this);
125 if(i!=prepare_stack.end())
128 for(; i!=prepare_stack.end(); ++i)
129 append(cycle, " -> ", (*i)->name);
130 append(cycle, " -> ", name);
131 builder.get_logger().log("problems", "Dependency cycle detected: %s", cycle);
132 problems.push_back(format("Dependency cycle detected: %s", cycle));
136 builder.get_logger().log("problems", "Dependency cycle detected at %s", name);
137 problems.push_back("Dependency cycle detected");
143 PushPrepare _push(this);
145 /* Prepare existing dependencies early, because their information may be
146 needed to find other dependencies. */
147 for(Target *d: depends)
153 bool broken = !problems.empty();
157 if(FileTarget *tool_exe = tool->get_executable())
158 add_dependency(*tool_exe);
159 broken |= tool->is_broken();
161 // Only check package and component brokenness for buildable targets
162 broken |= (package && package->is_broken());
163 broken |= (component && component->is_broken());
166 /* Now that all dependencies are known, prepare them again. This will do
167 nothing to already prepared targets. */
168 for(Target *d: depends)
171 broken |= d->is_broken();
173 for(Target *d: trans_depends)
179 else if(state==PREPARING)
182 for(Target *d: depends)
183 d->signal_bubble_rebuild.connect(sigc::mem_fun(this, &Target::check_rebuild));
186 Task *Target::build()
189 return primary_target->build();
191 Task *task = tool->run(*this);
192 task->signal_finished.connect(sigc::mem_fun(this, &Target::build_finished));
196 for(Target *s: side_effects)
202 void Target::build_finished(bool success)
208 for(Target *s: side_effects)
209 s->build_finished(success);
210 signal_modified.emit();