• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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