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 "gn/builder.h"
6
7 #include <stddef.h>
8 #include <utility>
9
10 #include "gn/action_values.h"
11 #include "gn/config.h"
12 #include "gn/deps_iterator.h"
13 #include "gn/err.h"
14 #include "gn/loader.h"
15 #include "gn/pool.h"
16 #include "gn/scheduler.h"
17 #include "gn/settings.h"
18 #include "gn/target.h"
19 #include "gn/trace.h"
20
21 namespace {
22
23 using BuilderRecordSet = BuilderRecord::BuilderRecordSet;
24
25 // Recursively looks in the tree for a given node, returning true if it
26 // was found in the dependecy graph. This is used to see if a given node
27 // participates in a cycle.
28 //
29 // If this returns true, the cycle will be in *path. This should point to an
30 // empty vector for the first call. During computation, the path will contain
31 // the full dependency path to the current node.
32 //
33 // Return false means no cycle was found.
RecursiveFindCycle(const BuilderRecord * search_in,std::vector<const BuilderRecord * > * path)34 bool RecursiveFindCycle(const BuilderRecord* search_in,
35 std::vector<const BuilderRecord*>* path) {
36 path->push_back(search_in);
37 for (auto* cur : search_in->unresolved_deps()) {
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::~Builder() = default;
60
ItemDefined(std::unique_ptr<Item> item)61 void Builder::ItemDefined(std::unique_ptr<Item> item) {
62 ScopedTrace trace(TraceItem::TRACE_DEFINE_TARGET, item->label());
63 trace.SetToolchain(item->settings()->toolchain_label());
64
65 BuilderRecord::ItemType type = BuilderRecord::TypeOfItem(item.get());
66
67 Err err;
68 BuilderRecord* record =
69 GetOrCreateRecordOfType(item->label(), item->defined_from(), type, &err);
70 if (!record) {
71 g_scheduler->FailWithError(err);
72 return;
73 }
74
75 // Check that it's not been already defined.
76 if (record->item()) {
77 err = Err(item->defined_from(), "Duplicate definition.",
78 "The item\n " + item->label().GetUserVisibleName(false) +
79 "\nwas already defined.");
80 err.AppendSubErr(
81 Err(record->item()->defined_from(), "Previous definition:"));
82 g_scheduler->FailWithError(err);
83 return;
84 }
85
86 record->set_item(std::move(item));
87
88 // Do target-specific dependency setup. This will also schedule dependency
89 // loads for targets that are required.
90 switch (type) {
91 case BuilderRecord::ITEM_TARGET:
92 TargetDefined(record, &err);
93 break;
94 case BuilderRecord::ITEM_CONFIG:
95 ConfigDefined(record, &err);
96 break;
97 case BuilderRecord::ITEM_TOOLCHAIN:
98 ToolchainDefined(record, &err);
99 break;
100 default:
101 break;
102 }
103 if (err.has_error()) {
104 g_scheduler->FailWithError(err);
105 return;
106 }
107
108 if (record->can_resolve()) {
109 if (!ResolveItem(record, &err)) {
110 g_scheduler->FailWithError(err);
111 return;
112 }
113 }
114 }
115
GetItem(const Label & label) const116 const Item* Builder::GetItem(const Label& label) const {
117 const BuilderRecord* record = GetRecord(label);
118 if (!record)
119 return nullptr;
120 return record->item();
121 }
122
GetToolchain(const Label & label) const123 const Toolchain* Builder::GetToolchain(const Label& label) const {
124 const BuilderRecord* record = GetRecord(label);
125 if (!record)
126 return nullptr;
127 if (!record->item())
128 return nullptr;
129 return record->item()->AsToolchain();
130 }
131
GetAllRecords() const132 std::vector<const BuilderRecord*> Builder::GetAllRecords() const {
133 std::vector<const BuilderRecord*> result;
134 result.reserve(records_.size());
135 for (const auto& record : records_)
136 result.push_back(record.second.get());
137 return result;
138 }
139
GetAllResolvedItems() const140 std::vector<const Item*> Builder::GetAllResolvedItems() const {
141 std::vector<const Item*> result;
142 result.reserve(records_.size());
143 for (const auto& record : records_) {
144 if (record.second->type() != BuilderRecord::ITEM_UNKNOWN &&
145 record.second->should_generate() && record.second->item()) {
146 result.push_back(record.second->item());
147 }
148 }
149
150 return result;
151 }
152
GetAllResolvedTargets() const153 std::vector<const Target*> Builder::GetAllResolvedTargets() const {
154 std::vector<const Target*> result;
155 result.reserve(records_.size());
156 for (const auto& record : records_) {
157 if (record.second->type() == BuilderRecord::ITEM_TARGET &&
158 record.second->should_generate() && record.second->item())
159 result.push_back(record.second->item()->AsTarget());
160 }
161 return result;
162 }
163
GetRecord(const Label & label) const164 const BuilderRecord* Builder::GetRecord(const Label& label) const {
165 // Forward to the non-const version.
166 return const_cast<Builder*>(this)->GetRecord(label);
167 }
168
GetRecord(const Label & label)169 BuilderRecord* Builder::GetRecord(const Label& label) {
170 auto found = records_.find(label);
171 return (found != records_.end()) ? found->second.get() : nullptr;
172 }
173
CheckForBadItems(Err * err) const174 bool Builder::CheckForBadItems(Err* err) const {
175 // Look for errors where we find a defined node with an item that refers to
176 // an undefined one with no item. There may be other nodes in turn depending
177 // on our defined one, but listing those isn't helpful: we want to find the
178 // broken link.
179 //
180 // This finds normal "missing dependency" errors but does not find circular
181 // dependencies because in this case all items in the cycle will be GENERATED
182 // but none will be resolved. If this happens, we'll check explicitly for
183 // that below.
184 std::vector<const BuilderRecord*> bad_records;
185 std::string depstring;
186 for (const auto& record_pair : records_) {
187 const BuilderRecord* src = record_pair.second.get();
188 if (!src->should_generate())
189 continue; // Skip ungenerated nodes.
190
191 if (!src->resolved()) {
192 bad_records.push_back(src);
193
194 // Check dependencies.
195 for (auto* dest : src->unresolved_deps()) {
196 if (!dest->item()) {
197 depstring += src->label().GetUserVisibleName(true) + "\n needs " +
198 dest->label().GetUserVisibleName(true) + "\n";
199 }
200 }
201 }
202 }
203
204 if (!depstring.empty()) {
205 *err = Err(Location(), "Unresolved dependencies.", depstring);
206 return false;
207 }
208
209 if (!bad_records.empty()) {
210 // Our logic above found a bad node but didn't identify the problem. This
211 // normally means a circular dependency.
212 depstring = CheckForCircularDependencies(bad_records);
213 if (depstring.empty()) {
214 // Something's very wrong, just dump out the bad nodes.
215 depstring =
216 "I have no idea what went wrong, but these are unresolved, "
217 "possibly due to an\ninternal error:";
218 for (auto* bad_record : bad_records) {
219 depstring +=
220 "\n\"" + bad_record->label().GetUserVisibleName(false) + "\"";
221 }
222 *err = Err(Location(), "", depstring);
223 } else {
224 *err = Err(Location(), "Dependency cycle:", depstring);
225 }
226 return false;
227 }
228
229 return true;
230 }
231
TargetDefined(BuilderRecord * record,Err * err)232 bool Builder::TargetDefined(BuilderRecord* record, Err* err) {
233 Target* target = record->item()->AsTarget();
234
235 if (!AddDeps(record, target->public_deps(), err) ||
236 !AddDeps(record, target->private_deps(), err) ||
237 !AddDeps(record, target->data_deps(), err) ||
238 !AddDeps(record, target->configs().vector(), err) ||
239 !AddDeps(record, target->all_dependent_configs(), err) ||
240 !AddDeps(record, target->public_configs(), err) ||
241 !AddActionValuesDep(record, target->action_values(), err) ||
242 !AddToolchainDep(record, target, err))
243 return false;
244
245 // All targets in the default toolchain get generated by default. We also
246 // check if this target was previously marked as "required" and force setting
247 // the bit again so the target's dependencies (which we now know) get the
248 // required bit pushed to them.
249 if (record->should_generate() || target->settings()->is_default())
250 RecursiveSetShouldGenerate(record, true);
251
252 return true;
253 }
254
ConfigDefined(BuilderRecord * record,Err * err)255 bool Builder::ConfigDefined(BuilderRecord* record, Err* err) {
256 Config* config = record->item()->AsConfig();
257 if (!AddDeps(record, config->configs(), err))
258 return false;
259
260 // Make sure all deps of this config are scheduled to be loaded. For other
261 // item types like targets, the "should generate" flag is propagated around
262 // to mark whether this should happen. We could call
263 // RecursiveSetShouldGenerate to do this step here, but since configs nor
264 // anything they depend on is actually written, the "generate" flag isn't
265 // relevant and means extra book keeping. Just force load any deps of this
266 // config.
267 for (auto* cur : record->all_deps())
268 ScheduleItemLoadIfNecessary(cur);
269
270 return true;
271 }
272
ToolchainDefined(BuilderRecord * record,Err * err)273 bool Builder::ToolchainDefined(BuilderRecord* record, Err* err) {
274 Toolchain* toolchain = record->item()->AsToolchain();
275
276 if (!AddDeps(record, toolchain->deps(), err))
277 return false;
278
279 for (const auto& tool : toolchain->tools()) {
280 if (tool.second->pool().label.is_null())
281 continue;
282
283 BuilderRecord* dep_record = GetOrCreateRecordOfType(
284 tool.second->pool().label, tool.second->pool().origin,
285 BuilderRecord::ITEM_POOL, err);
286 if (!dep_record)
287 return false;
288 record->AddDep(dep_record);
289 }
290
291 // The default toolchain gets generated by default. Also propogate the
292 // generate flag if it depends on items in a non-default toolchain.
293 if (record->should_generate() ||
294 toolchain->settings()->default_toolchain_label() == toolchain->label())
295 RecursiveSetShouldGenerate(record, true);
296
297 loader_->ToolchainLoaded(toolchain);
298 return true;
299 }
300
GetOrCreateRecordOfType(const Label & label,const ParseNode * request_from,BuilderRecord::ItemType type,Err * err)301 BuilderRecord* Builder::GetOrCreateRecordOfType(const Label& label,
302 const ParseNode* request_from,
303 BuilderRecord::ItemType type,
304 Err* err) {
305 BuilderRecord* record = GetRecord(label);
306 if (!record) {
307 // Not seen this record yet, create a new one.
308 auto new_record = std::make_unique<BuilderRecord>(type, label);
309 new_record->set_originally_referenced_from(request_from);
310 record = new_record.get();
311 records_[label] = std::move(new_record);
312 return record;
313 }
314
315 // Check types.
316 if (record->type() != type) {
317 std::string msg =
318 "The type of " + label.GetUserVisibleName(false) + "\nhere is a " +
319 BuilderRecord::GetNameForType(type) + " but was previously seen as a " +
320 BuilderRecord::GetNameForType(record->type()) +
321 ".\n\n"
322 "The most common cause is that the label of a config was put in the\n"
323 "in the deps section of a target (or vice-versa).";
324 *err = Err(request_from, "Item type does not match.", msg);
325 if (record->originally_referenced_from()) {
326 err->AppendSubErr(
327 Err(record->originally_referenced_from(), std::string()));
328 }
329 return nullptr;
330 }
331
332 return record;
333 }
334
GetResolvedRecordOfType(const Label & label,const ParseNode * origin,BuilderRecord::ItemType type,Err * err)335 BuilderRecord* Builder::GetResolvedRecordOfType(const Label& label,
336 const ParseNode* origin,
337 BuilderRecord::ItemType type,
338 Err* err) {
339 BuilderRecord* record = GetRecord(label);
340 if (!record) {
341 *err = Err(origin, "Item not found",
342 "\"" + label.GetUserVisibleName(false) +
343 "\" doesn't\n"
344 "refer to an existent thing.");
345 return nullptr;
346 }
347
348 const Item* item = record->item();
349 if (!item) {
350 *err = Err(
351 origin, "Item not resolved.",
352 "\"" + label.GetUserVisibleName(false) + "\" hasn't been resolved.\n");
353 return nullptr;
354 }
355
356 if (!BuilderRecord::IsItemOfType(item, type)) {
357 *err =
358 Err(origin,
359 std::string("This is not a ") + BuilderRecord::GetNameForType(type),
360 "\"" + label.GetUserVisibleName(false) + "\" refers to a " +
361 item->GetItemTypeName() + " instead of a " +
362 BuilderRecord::GetNameForType(type) + ".");
363 return nullptr;
364 }
365 return record;
366 }
367
AddDeps(BuilderRecord * record,const LabelConfigVector & configs,Err * err)368 bool Builder::AddDeps(BuilderRecord* record,
369 const LabelConfigVector& configs,
370 Err* err) {
371 for (const auto& config : configs) {
372 BuilderRecord* dep_record = GetOrCreateRecordOfType(
373 config.label, config.origin, BuilderRecord::ITEM_CONFIG, err);
374 if (!dep_record)
375 return false;
376 record->AddDep(dep_record);
377 }
378 return true;
379 }
380
AddDeps(BuilderRecord * record,const UniqueVector<LabelConfigPair> & configs,Err * err)381 bool Builder::AddDeps(BuilderRecord* record,
382 const UniqueVector<LabelConfigPair>& configs,
383 Err* err) {
384 for (const auto& config : configs) {
385 BuilderRecord* dep_record = GetOrCreateRecordOfType(
386 config.label, config.origin, BuilderRecord::ITEM_CONFIG, err);
387 if (!dep_record)
388 return false;
389 record->AddDep(dep_record);
390 }
391 return true;
392 }
393
AddDeps(BuilderRecord * record,const LabelTargetVector & targets,Err * err)394 bool Builder::AddDeps(BuilderRecord* record,
395 const LabelTargetVector& targets,
396 Err* err) {
397 for (const auto& target : targets) {
398 BuilderRecord* dep_record = GetOrCreateRecordOfType(
399 target.label, target.origin, BuilderRecord::ITEM_TARGET, err);
400 if (!dep_record)
401 return false;
402 record->AddDep(dep_record);
403 }
404 return true;
405 }
406
AddActionValuesDep(BuilderRecord * record,const ActionValues & action_values,Err * err)407 bool Builder::AddActionValuesDep(BuilderRecord* record,
408 const ActionValues& action_values,
409 Err* err) {
410 if (action_values.pool().label.is_null())
411 return true;
412
413 BuilderRecord* pool_record = GetOrCreateRecordOfType(
414 action_values.pool().label, action_values.pool().origin,
415 BuilderRecord::ITEM_POOL, err);
416 if (!pool_record)
417 return false;
418 record->AddDep(pool_record);
419
420 return true;
421 }
422
AddToolchainDep(BuilderRecord * record,const Target * target,Err * err)423 bool Builder::AddToolchainDep(BuilderRecord* record,
424 const Target* target,
425 Err* err) {
426 BuilderRecord* toolchain_record = GetOrCreateRecordOfType(
427 target->settings()->toolchain_label(), target->defined_from(),
428 BuilderRecord::ITEM_TOOLCHAIN, err);
429 if (!toolchain_record)
430 return false;
431 record->AddDep(toolchain_record);
432
433 return true;
434 }
435
RecursiveSetShouldGenerate(BuilderRecord * record,bool force)436 void Builder::RecursiveSetShouldGenerate(BuilderRecord* record, bool force) {
437 if (!record->should_generate()) {
438 record->set_should_generate(true);
439
440 // This may have caused the item to go into "resolved and generated" state.
441 if (record->resolved() && resolved_and_generated_callback_)
442 resolved_and_generated_callback_(record);
443 } else if (!force) {
444 return; // Already set and we're not required to iterate dependencies.
445 }
446
447 for (auto* cur : record->all_deps()) {
448 if (!cur->should_generate()) {
449 ScheduleItemLoadIfNecessary(cur);
450 RecursiveSetShouldGenerate(cur, false);
451 }
452 }
453 }
454
ScheduleItemLoadIfNecessary(BuilderRecord * record)455 void Builder::ScheduleItemLoadIfNecessary(BuilderRecord* record) {
456 const ParseNode* origin = record->originally_referenced_from();
457 loader_->Load(record->label(), origin ? origin->GetRange() : LocationRange());
458 }
459
ResolveItem(BuilderRecord * record,Err * err)460 bool Builder::ResolveItem(BuilderRecord* record, Err* err) {
461 DCHECK(record->can_resolve() && !record->resolved());
462
463 if (record->type() == BuilderRecord::ITEM_TARGET) {
464 Target* target = record->item()->AsTarget();
465 if (!ResolveDeps(&target->public_deps(), err) ||
466 !ResolveDeps(&target->private_deps(), err) ||
467 !ResolveDeps(&target->data_deps(), err) ||
468 !ResolveConfigs(&target->configs(), err) ||
469 !ResolveConfigs(&target->all_dependent_configs(), err) ||
470 !ResolveConfigs(&target->public_configs(), err) ||
471 !ResolveActionValues(&target->action_values(), err) ||
472 !ResolveToolchain(target, err))
473 return false;
474 } else if (record->type() == BuilderRecord::ITEM_CONFIG) {
475 Config* config = record->item()->AsConfig();
476 if (!ResolveConfigs(&config->configs(), err))
477 return false;
478 } else if (record->type() == BuilderRecord::ITEM_TOOLCHAIN) {
479 Toolchain* toolchain = record->item()->AsToolchain();
480 if (!ResolveDeps(&toolchain->deps(), err))
481 return false;
482 if (!ResolvePools(toolchain, err))
483 return false;
484 }
485
486 record->set_resolved(true);
487
488 if (!record->item()->OnResolved(err))
489 return false;
490 if (record->should_generate() && resolved_and_generated_callback_)
491 resolved_and_generated_callback_(record);
492
493 // Recursively update everybody waiting on this item to be resolved.
494 for (BuilderRecord* waiting : record->waiting_on_resolution()) {
495 DCHECK(waiting->unresolved_deps().find(record) !=
496 waiting->unresolved_deps().end());
497 waiting->unresolved_deps().erase(record);
498
499 if (waiting->can_resolve()) {
500 if (!ResolveItem(waiting, err))
501 return false;
502 }
503 }
504 record->waiting_on_resolution().clear();
505 return true;
506 }
507
ResolveDeps(LabelTargetVector * deps,Err * err)508 bool Builder::ResolveDeps(LabelTargetVector* deps, Err* err) {
509 for (LabelTargetPair& cur : *deps) {
510 DCHECK(!cur.ptr);
511
512 BuilderRecord* record = GetResolvedRecordOfType(
513 cur.label, cur.origin, BuilderRecord::ITEM_TARGET, err);
514 if (!record)
515 return false;
516 cur.ptr = record->item()->AsTarget();
517 }
518 return true;
519 }
520
ResolveConfigs(UniqueVector<LabelConfigPair> * configs,Err * err)521 bool Builder::ResolveConfigs(UniqueVector<LabelConfigPair>* configs, Err* err) {
522 for (const auto& cur : *configs) {
523 DCHECK(!cur.ptr);
524
525 BuilderRecord* record = GetResolvedRecordOfType(
526 cur.label, cur.origin, BuilderRecord::ITEM_CONFIG, err);
527 if (!record)
528 return false;
529 const_cast<LabelConfigPair&>(cur).ptr = record->item()->AsConfig();
530 }
531 return true;
532 }
533
ResolveToolchain(Target * target,Err * err)534 bool Builder::ResolveToolchain(Target* target, Err* err) {
535 BuilderRecord* record = GetResolvedRecordOfType(
536 target->settings()->toolchain_label(), target->defined_from(),
537 BuilderRecord::ITEM_TOOLCHAIN, err);
538 if (!record) {
539 *err = Err(
540 target->defined_from(), "Toolchain for target not defined.",
541 "I was hoping to find a toolchain " +
542 target->settings()->toolchain_label().GetUserVisibleName(false));
543 return false;
544 }
545
546 if (!target->SetToolchain(record->item()->AsToolchain(), err))
547 return false;
548
549 return true;
550 }
551
ResolveActionValues(ActionValues * action_values,Err * err)552 bool Builder::ResolveActionValues(ActionValues* action_values, Err* err) {
553 if (action_values->pool().label.is_null())
554 return true;
555
556 BuilderRecord* record = GetResolvedRecordOfType(
557 action_values->pool().label, action_values->pool().origin,
558 BuilderRecord::ITEM_POOL, err);
559 if (!record)
560 return false;
561 action_values->set_pool(LabelPtrPair<Pool>(record->item()->AsPool()));
562
563 return true;
564 }
565
ResolvePools(Toolchain * toolchain,Err * err)566 bool Builder::ResolvePools(Toolchain* toolchain, Err* err) {
567 for (const auto& tool : toolchain->tools()) {
568 if (tool.second->pool().label.is_null())
569 continue;
570
571 BuilderRecord* record = GetResolvedRecordOfType(
572 tool.second->pool().label, toolchain->defined_from(),
573 BuilderRecord::ITEM_POOL, err);
574 if (!record) {
575 *err = Err(tool.second->pool().origin, "Pool for tool not defined.",
576 "I was hoping to find a pool " +
577 tool.second->pool().label.GetUserVisibleName(false));
578 return false;
579 }
580
581 tool.second->set_pool(LabelPtrPair<Pool>(record->item()->AsPool()));
582 }
583
584 return true;
585 }
586
CheckForCircularDependencies(const std::vector<const BuilderRecord * > & bad_records) const587 std::string Builder::CheckForCircularDependencies(
588 const std::vector<const BuilderRecord*>& bad_records) const {
589 std::vector<const BuilderRecord*> cycle;
590 if (!RecursiveFindCycle(bad_records[0], &cycle))
591 return std::string(); // Didn't find a cycle, something else is wrong.
592
593 std::string ret;
594 for (size_t i = 0; i < cycle.size(); i++) {
595 ret += " " + cycle[i]->label().GetUserVisibleName(false);
596 if (i != cycle.size() - 1)
597 ret += " ->";
598 ret += "\n";
599 }
600
601 return ret;
602 }
603