1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "tools/gn/builder.h"
6
7 #include "tools/gn/config.h"
8 #include "tools/gn/err.h"
9 #include "tools/gn/loader.h"
10 #include "tools/gn/scheduler.h"
11 #include "tools/gn/settings.h"
12 #include "tools/gn/target.h"
13 #include "tools/gn/trace.h"
14
15 namespace {
16
17 typedef BuilderRecord::BuilderRecordSet BuilderRecordSet;
18
19 // Recursively looks in the tree for a given node, returning true if it
20 // was found in the dependecy graph. This is used to see if a given node
21 // participates in a cycle.
22 //
23 // If this returns true, the cycle will be in *path. This should point to an
24 // empty vector for the first call. During computation, the path will contain
25 // the full dependency path to the current node.
26 //
27 // Return false means no cycle was found.
RecursiveFindCycle(const BuilderRecord * search_in,std::vector<const BuilderRecord * > * path)28 bool RecursiveFindCycle(const BuilderRecord* search_in,
29 std::vector<const BuilderRecord*>* path) {
30 path->push_back(search_in);
31
32 const BuilderRecord::BuilderRecordSet& unresolved =
33 search_in->unresolved_deps();
34 for (BuilderRecord::BuilderRecordSet::const_iterator i = unresolved.begin();
35 i != unresolved.end(); ++i) {
36 const BuilderRecord* cur = *i;
37
38 std::vector<const BuilderRecord*>::iterator found =
39 std::find(path->begin(), path->end(), cur);
40 if (found != path->end()) {
41 // This item is already in the set, we found the cycle. Everything before
42 // the first definition of cur is irrelevant to the cycle.
43 path->erase(path->begin(), found);
44 path->push_back(cur);
45 return true;
46 }
47
48 if (RecursiveFindCycle(cur, path))
49 return true; // Found cycle.
50 }
51 path->pop_back();
52 return false;
53 }
54
55 } // namespace
56
Builder(Loader * loader)57 Builder::Builder(Loader* loader) : loader_(loader) {
58 }
59
~Builder()60 Builder::~Builder() {
61 }
62
ItemDefined(scoped_ptr<Item> item)63 void Builder::ItemDefined(scoped_ptr<Item> item) {
64 ScopedTrace trace(TraceItem::TRACE_DEFINE_TARGET, item->label());
65 trace.SetToolchain(item->settings()->toolchain_label());
66
67 BuilderRecord::ItemType type = BuilderRecord::TypeOfItem(item.get());
68
69 Err err;
70 BuilderRecord* record =
71 GetOrCreateRecordOfType(item->label(), item->defined_from(), type, &err);
72 if (!record) {
73 g_scheduler->FailWithError(err);
74 return;
75 }
76
77 // Check that it's not been already defined.
78 if (record->item()) {
79 err = Err(item->defined_from(), "Duplicate definition.",
80 "The item\n " + item->label().GetUserVisibleName(false) +
81 "\nwas already defined.");
82 err.AppendSubErr(Err(record->item()->defined_from(),
83 "Previous definition:"));
84 g_scheduler->FailWithError(err);
85 return;
86 }
87
88 record->set_item(item.Pass());
89
90 // Do target-specific dependency setup. This will also schedule dependency
91 // loads for targets that are required.
92 switch (type) {
93 case BuilderRecord::ITEM_TARGET:
94 if (!TargetDefined(record, &err)) {
95 g_scheduler->FailWithError(err);
96 return;
97 }
98 break;
99 case BuilderRecord::ITEM_TOOLCHAIN:
100 loader_->ToolchainLoaded(record->item()->AsToolchain());
101 break;
102 default:
103 break;
104 }
105
106 if (record->can_resolve()) {
107 if (!ResolveItem(record, &err)) {
108 g_scheduler->FailWithError(err);
109 return;
110 }
111 }
112 }
113
GetItem(const Label & label) const114 const Item* Builder::GetItem(const Label& label) const {
115 const BuilderRecord* record = GetRecord(label);
116 if (!record)
117 return NULL;
118 return record->item();
119 }
120
GetToolchain(const Label & label) const121 const Toolchain* Builder::GetToolchain(const Label& label) const {
122 const BuilderRecord* record = GetRecord(label);
123 if (!record)
124 return NULL;
125 if (!record->item())
126 return NULL;
127 return record->item()->AsToolchain();
128 }
129
GetAllRecords() const130 std::vector<const BuilderRecord*> Builder::GetAllRecords() const {
131 std::vector<const BuilderRecord*> result;
132 result.reserve(records_.size());
133 for (RecordMap::const_iterator i = records_.begin();
134 i != records_.end(); ++i)
135 result.push_back(i->second);
136 return result;
137 }
138
GetAllResolvedTargets() const139 std::vector<const Target*> Builder::GetAllResolvedTargets() const {
140 std::vector<const Target*> result;
141 result.reserve(records_.size());
142 for (RecordMap::const_iterator i = records_.begin();
143 i != records_.end(); ++i) {
144 if (i->second->type() == BuilderRecord::ITEM_TARGET &&
145 i->second->should_generate() && i->second->item())
146 result.push_back(i->second->item()->AsTarget());
147 }
148 return result;
149 }
150
GetRecord(const Label & label) const151 const BuilderRecord* Builder::GetRecord(const Label& label) const {
152 // Forward to the non-const version.
153 return const_cast<Builder*>(this)->GetRecord(label);
154 }
155
GetRecord(const Label & label)156 BuilderRecord* Builder::GetRecord(const Label& label) {
157 RecordMap::iterator found = records_.find(label);
158 if (found == records_.end())
159 return NULL;
160 return found->second;
161 }
162
CheckForBadItems(Err * err) const163 bool Builder::CheckForBadItems(Err* err) const {
164 // Look for errors where we find a defined node with an item that refers to
165 // an undefined one with no item. There may be other nodes in turn depending
166 // on our defined one, but listing those isn't helpful: we want to find the
167 // broken link.
168 //
169 // This finds normal "missing dependency" errors but does not find circular
170 // dependencies because in this case all items in the cycle will be GENERATED
171 // but none will be resolved. If this happens, we'll check explicitly for
172 // that below.
173 std::vector<const BuilderRecord*> bad_records;
174 std::string depstring;
175 for (RecordMap::const_iterator i = records_.begin();
176 i != records_.end(); ++i) {
177 const BuilderRecord* src = i->second;
178 if (!src->should_generate())
179 continue; // Skip ungenerated nodes.
180
181 if (!src->resolved()) {
182 bad_records.push_back(src);
183
184 // Check dependencies.
185 for (BuilderRecord::BuilderRecordSet::const_iterator dest_iter =
186 src->unresolved_deps().begin();
187 dest_iter != src->unresolved_deps().end();
188 ++dest_iter) {
189 const BuilderRecord* dest = *dest_iter;
190 if (!dest->item()) {
191 depstring += src->label().GetUserVisibleName(true) +
192 "\n needs " + dest->label().GetUserVisibleName(true) + "\n";
193 }
194 }
195 }
196 }
197
198 if (!depstring.empty()) {
199 *err = Err(Location(), "Unresolved dependencies.", depstring);
200 return false;
201 }
202
203 if (!bad_records.empty()) {
204 // Our logic above found a bad node but didn't identify the problem. This
205 // normally means a circular dependency.
206 depstring = CheckForCircularDependencies(bad_records);
207 if (depstring.empty()) {
208 // Something's very wrong, just dump out the bad nodes.
209 depstring = "I have no idea what went wrong, but these are unresolved, "
210 "possible due to an\ninternal error:";
211 for (size_t i = 0; i < bad_records.size(); i++) {
212 depstring += "\n\"" +
213 bad_records[i]->label().GetUserVisibleName(false) + "\"";
214 }
215 *err = Err(Location(), "", depstring);
216 } else {
217 *err = Err(Location(), "Dependency cycle:", depstring);
218 }
219 return false;
220 }
221
222 return true;
223 }
224
TargetDefined(BuilderRecord * record,Err * err)225 bool Builder::TargetDefined(BuilderRecord* record, Err* err) {
226 Target* target = record->item()->AsTarget();
227
228 if (!AddDeps(record, target->deps(), err) ||
229 !AddDeps(record, target->datadeps(), err) ||
230 !AddDeps(record, target->configs(), err) ||
231 !AddDeps(record, target->all_dependent_configs(), err) ||
232 !AddDeps(record, target->direct_dependent_configs(), err) ||
233 !AddToolchainDep(record, target, err))
234 return false;
235
236 // All targets in the default toolchain get generated by default. We also
237 // check if this target was previously marked as "required" and force setting
238 // the bit again so the target's dependencies (which we now know) get the
239 // required bit pushed to them.
240 if (record->should_generate() || target->settings()->is_default())
241 RecursiveSetShouldGenerate(record, true);
242
243 return true;
244 }
245
GetOrCreateRecordOfType(const Label & label,const ParseNode * request_from,BuilderRecord::ItemType type,Err * err)246 BuilderRecord* Builder::GetOrCreateRecordOfType(const Label& label,
247 const ParseNode* request_from,
248 BuilderRecord::ItemType type,
249 Err* err) {
250 BuilderRecord* record = GetRecord(label);
251 if (!record) {
252 // Not seen this record yet, create a new one.
253 record = new BuilderRecord(type, label);
254 records_[label] = record;
255 return record;
256 }
257
258 // Check types.
259 if (record->type() != type) {
260 *err = Err(request_from, "Item type does not match.",
261 "The item \"" + label.GetUserVisibleName(false) +
262 "\" was expected\nto be a " +
263 BuilderRecord::GetNameForType(type) +
264 " but was previously\n referenced as a " +
265 BuilderRecord::GetNameForType(record->type()));
266 err->AppendSubErr(Err(record->originally_referenced_from(),
267 "The previous reference was here."));
268 return NULL;
269 }
270
271 return record;
272 }
273
GetResolvedRecordOfType(const Label & label,const ParseNode * origin,BuilderRecord::ItemType type,Err * err)274 BuilderRecord* Builder::GetResolvedRecordOfType(const Label& label,
275 const ParseNode* origin,
276 BuilderRecord::ItemType type,
277 Err* err) {
278 BuilderRecord* record = GetRecord(label);
279 if (!record) {
280 *err = Err(origin, "Item not found",
281 "\"" + label.GetUserVisibleName(false) + "\" doesn't\n"
282 "refer to an existant thing.");
283 return NULL;
284 }
285
286 const Item* item = record->item();
287 if (!item) {
288 *err = Err(origin, "Item not resolved.",
289 "\"" + label.GetUserVisibleName(false) + "\" hasn't been resolved.\n");
290 return NULL;
291 }
292
293 if (!BuilderRecord::IsItemOfType(item, type)) {
294 *err = Err(origin,
295 std::string("This is not a ") + BuilderRecord::GetNameForType(type),
296 "\"" + label.GetUserVisibleName(false) + "\" refers to a " +
297 item->GetItemTypeName() + " instead of a " +
298 BuilderRecord::GetNameForType(type) + ".");
299 return NULL;
300 }
301 return record;
302 }
303
AddDeps(BuilderRecord * record,const LabelConfigVector & configs,Err * err)304 bool Builder::AddDeps(BuilderRecord* record,
305 const LabelConfigVector& configs,
306 Err* err) {
307 for (size_t i = 0; i < configs.size(); i++) {
308 BuilderRecord* dep_record = GetOrCreateRecordOfType(
309 configs[i].label, configs[i].origin, BuilderRecord::ITEM_CONFIG, err);
310 if (!dep_record)
311 return false;
312 record->AddDep(dep_record);
313 }
314 return true;
315 }
316
AddDeps(BuilderRecord * record,const LabelTargetVector & targets,Err * err)317 bool Builder::AddDeps(BuilderRecord* record,
318 const LabelTargetVector& targets,
319 Err* err) {
320 for (size_t i = 0; i < targets.size(); i++) {
321 BuilderRecord* dep_record = GetOrCreateRecordOfType(
322 targets[i].label, targets[i].origin, BuilderRecord::ITEM_TARGET, err);
323 if (!dep_record)
324 return false;
325 record->AddDep(dep_record);
326 }
327 return true;
328 }
329
AddToolchainDep(BuilderRecord * record,const Target * target,Err * err)330 bool Builder::AddToolchainDep(BuilderRecord* record,
331 const Target* target,
332 Err* err) {
333 BuilderRecord* toolchain_record = GetOrCreateRecordOfType(
334 target->settings()->toolchain_label(), target->defined_from(),
335 BuilderRecord::ITEM_TOOLCHAIN, err);
336 if (!toolchain_record)
337 return false;
338 record->AddDep(toolchain_record);
339
340 return true;
341 }
342
RecursiveSetShouldGenerate(BuilderRecord * record,bool force)343 void Builder::RecursiveSetShouldGenerate(BuilderRecord* record,
344 bool force) {
345 if (!force && record->should_generate())
346 return; // Already set.
347 record->set_should_generate(true);
348
349 const BuilderRecordSet& deps = record->all_deps();
350 for (BuilderRecordSet::const_iterator i = deps.begin();
351 i != deps.end(); i++) {
352 BuilderRecord* cur = *i;
353 if (!cur->should_generate()) {
354 ScheduleItemLoadIfNecessary(cur);
355 RecursiveSetShouldGenerate(cur, false);
356 }
357 }
358 }
359
ScheduleItemLoadIfNecessary(BuilderRecord * record)360 void Builder::ScheduleItemLoadIfNecessary(BuilderRecord* record) {
361 loader_->Load(record->label());
362 }
363
ResolveItem(BuilderRecord * record,Err * err)364 bool Builder::ResolveItem(BuilderRecord* record, Err* err) {
365 DCHECK(record->can_resolve() && !record->resolved());
366
367 if (record->type() == BuilderRecord::ITEM_TARGET) {
368 Target* target = record->item()->AsTarget();
369 if (!ResolveDeps(&target->deps(), err) ||
370 !ResolveDeps(&target->datadeps(), err) ||
371 !ResolveConfigs(&target->configs(), err) ||
372 !ResolveConfigs(&target->all_dependent_configs(), err) ||
373 !ResolveConfigs(&target->direct_dependent_configs(), err) ||
374 !ResolveForwardDependentConfigs(target, err))
375 return false;
376 }
377
378 record->set_resolved(true);
379 record->item()->OnResolved();
380 if (!resolved_callback_.is_null())
381 resolved_callback_.Run(record->item());
382
383 // Recursively update everybody waiting on this item to be resolved.
384 BuilderRecordSet& waiting_set = record->waiting_on_resolution();
385 for (BuilderRecordSet::iterator i = waiting_set.begin();
386 i != waiting_set.end(); ++i) {
387 BuilderRecord* waiting = *i;
388 DCHECK(waiting->unresolved_deps().find(record) !=
389 waiting->unresolved_deps().end());
390 waiting->unresolved_deps().erase(record);
391
392 if (waiting->can_resolve()) {
393 if (!ResolveItem(waiting, err))
394 return false;
395 }
396 }
397 waiting_set.clear();
398 return true;
399 }
400
ResolveDeps(LabelTargetVector * deps,Err * err)401 bool Builder::ResolveDeps(LabelTargetVector* deps, Err* err) {
402 for (size_t i = 0; i < deps->size(); i++) {
403 LabelTargetPair& cur = (*deps)[i];
404 DCHECK(!cur.ptr);
405
406 BuilderRecord* record = GetResolvedRecordOfType(
407 cur.label, cur.origin, BuilderRecord::ITEM_TARGET, err);
408 if (!record)
409 return false;
410 cur.ptr = record->item()->AsTarget();
411 }
412 return true;
413 }
414
ResolveConfigs(LabelConfigVector * configs,Err * err)415 bool Builder::ResolveConfigs(LabelConfigVector* configs, Err* err) {
416 for (size_t i = 0; i < configs->size(); i++) {
417 LabelConfigPair& cur = (*configs)[i];
418 DCHECK(!cur.ptr);
419
420 BuilderRecord* record = GetResolvedRecordOfType(
421 cur.label, cur.origin, BuilderRecord::ITEM_CONFIG, err);
422 if (!record)
423 return false;
424 cur.ptr = record->item()->AsConfig();
425 }
426 return true;
427 }
428
429 // "Forward dependent configs" should refer to targets in the deps that should
430 // have their configs forwarded.
ResolveForwardDependentConfigs(Target * target,Err * err)431 bool Builder::ResolveForwardDependentConfigs(Target* target, Err* err) {
432 const LabelTargetVector& deps = target->deps();
433 LabelTargetVector& configs = target->forward_dependent_configs();
434
435 // Assume that the lists are small so that brute-force n^2 is appropriate.
436 for (size_t config_i = 0; config_i < configs.size(); config_i++) {
437 for (size_t dep_i = 0; dep_i < deps.size(); dep_i++) {
438 if (configs[config_i].label == deps[dep_i].label) {
439 DCHECK(deps[dep_i].ptr); // Should already be resolved.
440 configs[config_i].ptr = deps[dep_i].ptr;
441 break;
442 }
443 }
444 if (!configs[config_i].ptr) {
445 *err = Err(target->defined_from(),
446 "Target in forward_dependent_configs_from was not listed in the deps",
447 "The target \"" + configs[config_i].label.GetUserVisibleName(false) +
448 "\"\n was not present in the deps. This thing is used to forward\n"
449 "configs from direct dependents.");
450 return false;
451 }
452 }
453 return true;
454 }
455
CheckForCircularDependencies(const std::vector<const BuilderRecord * > & bad_records) const456 std::string Builder::CheckForCircularDependencies(
457 const std::vector<const BuilderRecord*>& bad_records) const {
458 std::vector<const BuilderRecord*> cycle;
459 if (!RecursiveFindCycle(bad_records[0], &cycle))
460 return std::string(); // Didn't find a cycle, something else is wrong.
461
462 // Walk backwards since the dependency arrows point in the reverse direction.
463 std::string ret;
464 for (int i = static_cast<int>(cycle.size()) - 1; i >= 0; i--) {
465 ret += " " + cycle[i]->label().GetUserVisibleName(false);
466 if (i != 0)
467 ret += " ->\n";
468 }
469
470 return ret;
471 }
472