Removing uses of X11 native key events.
[chromium-blink-merge.git] / tools / gn / builder.cc
blob6198777b65977f353c538368a4e997a47dbdf403
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.
5 #include "tools/gn/builder.h"
7 #include "tools/gn/config.h"
8 #include "tools/gn/deps_iterator.h"
9 #include "tools/gn/err.h"
10 #include "tools/gn/loader.h"
11 #include "tools/gn/scheduler.h"
12 #include "tools/gn/settings.h"
13 #include "tools/gn/target.h"
14 #include "tools/gn/trace.h"
16 namespace {
18 typedef BuilderRecord::BuilderRecordSet BuilderRecordSet;
20 // Recursively looks in the tree for a given node, returning true if it
21 // was found in the dependecy graph. This is used to see if a given node
22 // participates in a cycle.
24 // If this returns true, the cycle will be in *path. This should point to an
25 // empty vector for the first call. During computation, the path will contain
26 // the full dependency path to the current node.
28 // Return false means no cycle was found.
29 bool RecursiveFindCycle(const BuilderRecord* search_in,
30 std::vector<const BuilderRecord*>* path) {
31 path->push_back(search_in);
33 const BuilderRecord::BuilderRecordSet& unresolved =
34 search_in->unresolved_deps();
35 for (BuilderRecord::BuilderRecordSet::const_iterator i = unresolved.begin();
36 i != unresolved.end(); ++i) {
37 const BuilderRecord* cur = *i;
39 std::vector<const BuilderRecord*>::iterator found =
40 std::find(path->begin(), path->end(), cur);
41 if (found != path->end()) {
42 // This item is already in the set, we found the cycle. Everything before
43 // the first definition of cur is irrelevant to the cycle.
44 path->erase(path->begin(), found);
45 path->push_back(cur);
46 return true;
49 if (RecursiveFindCycle(cur, path))
50 return true; // Found cycle.
52 path->pop_back();
53 return false;
56 } // namespace
58 Builder::Builder(Loader* loader) : loader_(loader) {
61 Builder::~Builder() {
64 void Builder::ItemDefined(scoped_ptr<Item> item) {
65 ScopedTrace trace(TraceItem::TRACE_DEFINE_TARGET, item->label());
66 trace.SetToolchain(item->settings()->toolchain_label());
68 BuilderRecord::ItemType type = BuilderRecord::TypeOfItem(item.get());
70 Err err;
71 BuilderRecord* record =
72 GetOrCreateRecordOfType(item->label(), item->defined_from(), type, &err);
73 if (!record) {
74 g_scheduler->FailWithError(err);
75 return;
78 // Check that it's not been already defined.
79 if (record->item()) {
80 err = Err(item->defined_from(), "Duplicate definition.",
81 "The item\n " + item->label().GetUserVisibleName(false) +
82 "\nwas already defined.");
83 err.AppendSubErr(Err(record->item()->defined_from(),
84 "Previous definition:"));
85 g_scheduler->FailWithError(err);
86 return;
89 record->set_item(item.Pass());
91 // Do target-specific dependency setup. This will also schedule dependency
92 // loads for targets that are required.
93 switch (type) {
94 case BuilderRecord::ITEM_TARGET:
95 TargetDefined(record, &err);
96 break;
97 case BuilderRecord::ITEM_TOOLCHAIN:
98 ToolchainDefined(record, &err);
99 break;
100 default:
101 break;
103 if (err.has_error()) {
104 g_scheduler->FailWithError(err);
105 return;
108 if (record->can_resolve()) {
109 if (!ResolveItem(record, &err)) {
110 g_scheduler->FailWithError(err);
111 return;
116 const Item* Builder::GetItem(const Label& label) const {
117 const BuilderRecord* record = GetRecord(label);
118 if (!record)
119 return NULL;
120 return record->item();
123 const Toolchain* Builder::GetToolchain(const Label& label) const {
124 const BuilderRecord* record = GetRecord(label);
125 if (!record)
126 return NULL;
127 if (!record->item())
128 return NULL;
129 return record->item()->AsToolchain();
132 std::vector<const BuilderRecord*> Builder::GetAllRecords() const {
133 std::vector<const BuilderRecord*> result;
134 result.reserve(records_.size());
135 for (RecordMap::const_iterator i = records_.begin();
136 i != records_.end(); ++i)
137 result.push_back(i->second);
138 return result;
141 std::vector<const Target*> Builder::GetAllResolvedTargets() const {
142 std::vector<const Target*> result;
143 result.reserve(records_.size());
144 for (RecordMap::const_iterator i = records_.begin();
145 i != records_.end(); ++i) {
146 if (i->second->type() == BuilderRecord::ITEM_TARGET &&
147 i->second->should_generate() && i->second->item())
148 result.push_back(i->second->item()->AsTarget());
150 return result;
153 const BuilderRecord* Builder::GetRecord(const Label& label) const {
154 // Forward to the non-const version.
155 return const_cast<Builder*>(this)->GetRecord(label);
158 BuilderRecord* Builder::GetRecord(const Label& label) {
159 RecordMap::iterator found = records_.find(label);
160 if (found == records_.end())
161 return NULL;
162 return found->second;
165 bool Builder::CheckForBadItems(Err* err) const {
166 // Look for errors where we find a defined node with an item that refers to
167 // an undefined one with no item. There may be other nodes in turn depending
168 // on our defined one, but listing those isn't helpful: we want to find the
169 // broken link.
171 // This finds normal "missing dependency" errors but does not find circular
172 // dependencies because in this case all items in the cycle will be GENERATED
173 // but none will be resolved. If this happens, we'll check explicitly for
174 // that below.
175 std::vector<const BuilderRecord*> bad_records;
176 std::string depstring;
177 for (RecordMap::const_iterator i = records_.begin();
178 i != records_.end(); ++i) {
179 const BuilderRecord* src = i->second;
180 if (!src->should_generate())
181 continue; // Skip ungenerated nodes.
183 if (!src->resolved()) {
184 bad_records.push_back(src);
186 // Check dependencies.
187 for (BuilderRecord::BuilderRecordSet::const_iterator dest_iter =
188 src->unresolved_deps().begin();
189 dest_iter != src->unresolved_deps().end();
190 ++dest_iter) {
191 const BuilderRecord* dest = *dest_iter;
192 if (!dest->item()) {
193 depstring += src->label().GetUserVisibleName(true) +
194 "\n needs " + dest->label().GetUserVisibleName(true) + "\n";
200 if (!depstring.empty()) {
201 *err = Err(Location(), "Unresolved dependencies.", depstring);
202 return false;
205 if (!bad_records.empty()) {
206 // Our logic above found a bad node but didn't identify the problem. This
207 // normally means a circular dependency.
208 depstring = CheckForCircularDependencies(bad_records);
209 if (depstring.empty()) {
210 // Something's very wrong, just dump out the bad nodes.
211 depstring = "I have no idea what went wrong, but these are unresolved, "
212 "possibly due to an\ninternal error:";
213 for (size_t i = 0; i < bad_records.size(); i++) {
214 depstring += "\n\"" +
215 bad_records[i]->label().GetUserVisibleName(false) + "\"";
217 *err = Err(Location(), "", depstring);
218 } else {
219 *err = Err(Location(), "Dependency cycle:", depstring);
221 return false;
224 return true;
227 bool Builder::TargetDefined(BuilderRecord* record, Err* err) {
228 Target* target = record->item()->AsTarget();
230 if (!AddDeps(record, target->public_deps(), err) ||
231 !AddDeps(record, target->private_deps(), err) ||
232 !AddDeps(record, target->data_deps(), err) ||
233 !AddDeps(record, target->configs().vector(), err) ||
234 !AddDeps(record, target->all_dependent_configs(), err) ||
235 !AddDeps(record, target->public_configs(), err) ||
236 !AddToolchainDep(record, target, err))
237 return false;
239 // All targets in the default toolchain get generated by default. We also
240 // check if this target was previously marked as "required" and force setting
241 // the bit again so the target's dependencies (which we now know) get the
242 // required bit pushed to them.
243 if (record->should_generate() || target->settings()->is_default())
244 RecursiveSetShouldGenerate(record, true);
246 return true;
249 bool Builder::ToolchainDefined(BuilderRecord* record, Err* err) {
250 Toolchain* toolchain = record->item()->AsToolchain();
252 if (!AddDeps(record, toolchain->deps(), err))
253 return false;
255 // The default toolchain gets generated by default. Also propogate the
256 // generate flag if it depends on items in a non-default toolchain.
257 if (record->should_generate() ||
258 toolchain->settings()->default_toolchain_label() == toolchain->label())
259 RecursiveSetShouldGenerate(record, true);
261 loader_->ToolchainLoaded(toolchain);
262 return true;
265 BuilderRecord* Builder::GetOrCreateRecordOfType(const Label& label,
266 const ParseNode* request_from,
267 BuilderRecord::ItemType type,
268 Err* err) {
269 BuilderRecord* record = GetRecord(label);
270 if (!record) {
271 // Not seen this record yet, create a new one.
272 record = new BuilderRecord(type, label);
273 record->set_originally_referenced_from(request_from);
274 records_[label] = record;
275 return record;
278 // Check types.
279 if (record->type() != type) {
280 std::string msg =
281 "The type of " + label.GetUserVisibleName(false) +
282 "\nhere is a " + BuilderRecord::GetNameForType(type) +
283 " but was previously seen as a " +
284 BuilderRecord::GetNameForType(record->type()) + ".\n\n"
285 "The most common cause is that the label of a config was put in the\n"
286 "in the deps section of a target (or vice-versa).";
287 *err = Err(request_from, "Item type does not match.", msg);
288 if (record->originally_referenced_from()) {
289 err->AppendSubErr(Err(record->originally_referenced_from(),
290 std::string()));
292 return NULL;
295 return record;
298 BuilderRecord* Builder::GetResolvedRecordOfType(const Label& label,
299 const ParseNode* origin,
300 BuilderRecord::ItemType type,
301 Err* err) {
302 BuilderRecord* record = GetRecord(label);
303 if (!record) {
304 *err = Err(origin, "Item not found",
305 "\"" + label.GetUserVisibleName(false) + "\" doesn't\n"
306 "refer to an existent thing.");
307 return NULL;
310 const Item* item = record->item();
311 if (!item) {
312 *err = Err(origin, "Item not resolved.",
313 "\"" + label.GetUserVisibleName(false) + "\" hasn't been resolved.\n");
314 return NULL;
317 if (!BuilderRecord::IsItemOfType(item, type)) {
318 *err = Err(origin,
319 std::string("This is not a ") + BuilderRecord::GetNameForType(type),
320 "\"" + label.GetUserVisibleName(false) + "\" refers to a " +
321 item->GetItemTypeName() + " instead of a " +
322 BuilderRecord::GetNameForType(type) + ".");
323 return NULL;
325 return record;
328 bool Builder::AddDeps(BuilderRecord* record,
329 const LabelConfigVector& configs,
330 Err* err) {
331 for (size_t i = 0; i < configs.size(); i++) {
332 BuilderRecord* dep_record = GetOrCreateRecordOfType(
333 configs[i].label, configs[i].origin, BuilderRecord::ITEM_CONFIG, err);
334 if (!dep_record)
335 return false;
336 record->AddDep(dep_record);
338 return true;
341 bool Builder::AddDeps(BuilderRecord* record,
342 const UniqueVector<LabelConfigPair>& configs,
343 Err* err) {
344 for (size_t i = 0; i < configs.size(); i++) {
345 BuilderRecord* dep_record = GetOrCreateRecordOfType(
346 configs[i].label, configs[i].origin, BuilderRecord::ITEM_CONFIG, err);
347 if (!dep_record)
348 return false;
349 record->AddDep(dep_record);
351 return true;
354 bool Builder::AddDeps(BuilderRecord* record,
355 const LabelTargetVector& targets,
356 Err* err) {
357 for (size_t i = 0; i < targets.size(); i++) {
358 BuilderRecord* dep_record = GetOrCreateRecordOfType(
359 targets[i].label, targets[i].origin, BuilderRecord::ITEM_TARGET, err);
360 if (!dep_record)
361 return false;
362 record->AddDep(dep_record);
364 return true;
367 bool Builder::AddToolchainDep(BuilderRecord* record,
368 const Target* target,
369 Err* err) {
370 BuilderRecord* toolchain_record = GetOrCreateRecordOfType(
371 target->settings()->toolchain_label(), target->defined_from(),
372 BuilderRecord::ITEM_TOOLCHAIN, err);
373 if (!toolchain_record)
374 return false;
375 record->AddDep(toolchain_record);
377 return true;
380 void Builder::RecursiveSetShouldGenerate(BuilderRecord* record,
381 bool force) {
382 if (!force && record->should_generate())
383 return; // Already set.
384 record->set_should_generate(true);
386 const BuilderRecordSet& deps = record->all_deps();
387 for (BuilderRecordSet::const_iterator i = deps.begin();
388 i != deps.end(); i++) {
389 BuilderRecord* cur = *i;
390 if (!cur->should_generate()) {
391 ScheduleItemLoadIfNecessary(cur);
392 RecursiveSetShouldGenerate(cur, false);
397 void Builder::ScheduleItemLoadIfNecessary(BuilderRecord* record) {
398 const ParseNode* origin = record->originally_referenced_from();
399 loader_->Load(record->label(),
400 origin ? origin->GetRange() : LocationRange());
403 bool Builder::ResolveItem(BuilderRecord* record, Err* err) {
404 DCHECK(record->can_resolve() && !record->resolved());
406 if (record->type() == BuilderRecord::ITEM_TARGET) {
407 Target* target = record->item()->AsTarget();
408 if (!ResolveDeps(&target->public_deps(), err) ||
409 !ResolveDeps(&target->private_deps(), err) ||
410 !ResolveDeps(&target->data_deps(), err) ||
411 !ResolveConfigs(&target->configs(), err) ||
412 !ResolveConfigs(&target->all_dependent_configs(), err) ||
413 !ResolveConfigs(&target->public_configs(), err) ||
414 !ResolveForwardDependentConfigs(target, err) ||
415 !ResolveToolchain(target, err))
416 return false;
417 } else if (record->type() == BuilderRecord::ITEM_TOOLCHAIN) {
418 Toolchain* toolchain = record->item()->AsToolchain();
419 if (!ResolveDeps(&toolchain->deps(), err))
420 return false;
423 record->set_resolved(true);
425 if (!record->item()->OnResolved(err))
426 return false;
427 if (!resolved_callback_.is_null())
428 resolved_callback_.Run(record);
430 // Recursively update everybody waiting on this item to be resolved.
431 BuilderRecordSet& waiting_set = record->waiting_on_resolution();
432 for (BuilderRecordSet::iterator i = waiting_set.begin();
433 i != waiting_set.end(); ++i) {
434 BuilderRecord* waiting = *i;
435 DCHECK(waiting->unresolved_deps().find(record) !=
436 waiting->unresolved_deps().end());
437 waiting->unresolved_deps().erase(record);
439 if (waiting->can_resolve()) {
440 if (!ResolveItem(waiting, err))
441 return false;
444 waiting_set.clear();
445 return true;
448 bool Builder::ResolveDeps(LabelTargetVector* deps, Err* err) {
449 for (size_t i = 0; i < deps->size(); i++) {
450 LabelTargetPair& cur = (*deps)[i];
451 DCHECK(!cur.ptr);
453 BuilderRecord* record = GetResolvedRecordOfType(
454 cur.label, cur.origin, BuilderRecord::ITEM_TARGET, err);
455 if (!record)
456 return false;
457 cur.ptr = record->item()->AsTarget();
459 return true;
462 bool Builder::ResolveConfigs(UniqueVector<LabelConfigPair>* configs, Err* err) {
463 for (size_t i = 0; i < configs->size(); i++) {
464 const LabelConfigPair& cur = (*configs)[i];
465 DCHECK(!cur.ptr);
467 BuilderRecord* record = GetResolvedRecordOfType(
468 cur.label, cur.origin, BuilderRecord::ITEM_CONFIG, err);
469 if (!record)
470 return false;
471 const_cast<LabelConfigPair&>(cur).ptr = record->item()->AsConfig();
473 return true;
476 // "Forward dependent configs" should refer to targets in the deps that should
477 // have their configs forwarded.
478 bool Builder::ResolveForwardDependentConfigs(Target* target, Err* err) {
479 const UniqueVector<LabelTargetPair>& configs =
480 target->forward_dependent_configs();
482 // Assume that the lists are small so that brute-force n^2 is appropriate.
483 for (size_t config_i = 0; config_i < configs.size(); config_i++) {
484 for (DepsIterator dep_iter(target, DepsIterator::LINKED_ONLY);
485 !dep_iter.done(); dep_iter.Advance()) {
486 if (configs[config_i].label == dep_iter.label()) {
487 DCHECK(dep_iter.target()); // Should already be resolved.
488 // UniqueVector's contents are constant so uniqueness is preserved, but
489 // we want to update this pointer which doesn't change uniqueness
490 // (uniqueness in this vector is determined by the label only).
491 const_cast<LabelTargetPair&>(configs[config_i]).ptr = dep_iter.target();
492 break;
495 if (!configs[config_i].ptr) {
496 *err = Err(target->defined_from(),
497 "Target in forward_dependent_configs_from was not listed in the deps",
498 "This target has a forward_dependent_configs_from entry that was "
499 "not present in\nthe deps. A target can only forward things it "
500 "depends on. It was forwarding:\n " +
501 configs[config_i].label.GetUserVisibleName(false));
502 return false;
505 return true;
508 bool Builder::ResolveToolchain(Target* target, Err* err) {
509 BuilderRecord* record = GetResolvedRecordOfType(
510 target->settings()->toolchain_label(), target->defined_from(),
511 BuilderRecord::ITEM_TOOLCHAIN, err);
512 if (!record) {
513 *err = Err(target->defined_from(),
514 "Toolchain for target not defined.",
515 "I was hoping to find a toolchain " +
516 target->settings()->toolchain_label().GetUserVisibleName(false));
517 return false;
520 if (!target->SetToolchain(record->item()->AsToolchain(), err))
521 return false;
523 return true;
526 std::string Builder::CheckForCircularDependencies(
527 const std::vector<const BuilderRecord*>& bad_records) const {
528 std::vector<const BuilderRecord*> cycle;
529 if (!RecursiveFindCycle(bad_records[0], &cycle))
530 return std::string(); // Didn't find a cycle, something else is wrong.
532 std::string ret;
533 for (size_t i = 0; i < cycle.size(); i++) {
534 ret += " " + cycle[i]->label().GetUserVisibleName(false);
535 if (i != cycle.size() - 1)
536 ret += " ->";
537 ret += "\n";
540 return ret;