OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "tools/gn/builder.h" | 5 #include "tools/gn/builder.h" |
6 | 6 |
7 #include "tools/gn/config.h" | 7 #include "tools/gn/config.h" |
8 #include "tools/gn/deps_iterator.h" | 8 #include "tools/gn/deps_iterator.h" |
9 #include "tools/gn/err.h" | 9 #include "tools/gn/err.h" |
10 #include "tools/gn/loader.h" | 10 #include "tools/gn/loader.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 // participates in a cycle. | 22 // participates in a cycle. |
23 // | 23 // |
24 // If this returns true, the cycle will be in *path. This should point to an | 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 | 25 // empty vector for the first call. During computation, the path will contain |
26 // the full dependency path to the current node. | 26 // the full dependency path to the current node. |
27 // | 27 // |
28 // Return false means no cycle was found. | 28 // Return false means no cycle was found. |
29 bool RecursiveFindCycle(const BuilderRecord* search_in, | 29 bool RecursiveFindCycle(const BuilderRecord* search_in, |
30 std::vector<const BuilderRecord*>* path) { | 30 std::vector<const BuilderRecord*>* path) { |
31 path->push_back(search_in); | 31 path->push_back(search_in); |
32 | 32 for (const auto& cur : search_in->unresolved_deps()) { |
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; | |
38 | |
39 std::vector<const BuilderRecord*>::iterator found = | 33 std::vector<const BuilderRecord*>::iterator found = |
40 std::find(path->begin(), path->end(), cur); | 34 std::find(path->begin(), path->end(), cur); |
41 if (found != path->end()) { | 35 if (found != path->end()) { |
42 // This item is already in the set, we found the cycle. Everything before | 36 // This item is already in the set, we found the cycle. Everything before |
43 // the first definition of cur is irrelevant to the cycle. | 37 // the first definition of cur is irrelevant to the cycle. |
44 path->erase(path->begin(), found); | 38 path->erase(path->begin(), found); |
45 path->push_back(cur); | 39 path->push_back(cur); |
46 return true; | 40 return true; |
47 } | 41 } |
48 | 42 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 if (!record) | 119 if (!record) |
126 return NULL; | 120 return NULL; |
127 if (!record->item()) | 121 if (!record->item()) |
128 return NULL; | 122 return NULL; |
129 return record->item()->AsToolchain(); | 123 return record->item()->AsToolchain(); |
130 } | 124 } |
131 | 125 |
132 std::vector<const BuilderRecord*> Builder::GetAllRecords() const { | 126 std::vector<const BuilderRecord*> Builder::GetAllRecords() const { |
133 std::vector<const BuilderRecord*> result; | 127 std::vector<const BuilderRecord*> result; |
134 result.reserve(records_.size()); | 128 result.reserve(records_.size()); |
135 for (RecordMap::const_iterator i = records_.begin(); | 129 for (const auto& record : records_) |
136 i != records_.end(); ++i) | 130 result.push_back(record.second); |
137 result.push_back(i->second); | |
138 return result; | 131 return result; |
139 } | 132 } |
140 | 133 |
141 std::vector<const Target*> Builder::GetAllResolvedTargets() const { | 134 std::vector<const Target*> Builder::GetAllResolvedTargets() const { |
142 std::vector<const Target*> result; | 135 std::vector<const Target*> result; |
143 result.reserve(records_.size()); | 136 result.reserve(records_.size()); |
144 for (RecordMap::const_iterator i = records_.begin(); | 137 for (const auto& record : records_) { |
145 i != records_.end(); ++i) { | 138 if (record.second->type() == BuilderRecord::ITEM_TARGET && |
146 if (i->second->type() == BuilderRecord::ITEM_TARGET && | 139 record.second->should_generate() && record.second->item()) |
147 i->second->should_generate() && i->second->item()) | 140 result.push_back(record.second->item()->AsTarget()); |
148 result.push_back(i->second->item()->AsTarget()); | |
149 } | 141 } |
150 return result; | 142 return result; |
151 } | 143 } |
152 | 144 |
153 const BuilderRecord* Builder::GetRecord(const Label& label) const { | 145 const BuilderRecord* Builder::GetRecord(const Label& label) const { |
154 // Forward to the non-const version. | 146 // Forward to the non-const version. |
155 return const_cast<Builder*>(this)->GetRecord(label); | 147 return const_cast<Builder*>(this)->GetRecord(label); |
156 } | 148 } |
157 | 149 |
158 BuilderRecord* Builder::GetRecord(const Label& label) { | 150 BuilderRecord* Builder::GetRecord(const Label& label) { |
159 RecordMap::iterator found = records_.find(label); | 151 RecordMap::iterator found = records_.find(label); |
160 if (found == records_.end()) | 152 if (found == records_.end()) |
161 return NULL; | 153 return NULL; |
162 return found->second; | 154 return found->second; |
163 } | 155 } |
164 | 156 |
165 bool Builder::CheckForBadItems(Err* err) const { | 157 bool Builder::CheckForBadItems(Err* err) const { |
166 // Look for errors where we find a defined node with an item that refers to | 158 // 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 | 159 // 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 | 160 // on our defined one, but listing those isn't helpful: we want to find the |
169 // broken link. | 161 // broken link. |
170 // | 162 // |
171 // This finds normal "missing dependency" errors but does not find circular | 163 // 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 | 164 // 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 | 165 // but none will be resolved. If this happens, we'll check explicitly for |
174 // that below. | 166 // that below. |
175 std::vector<const BuilderRecord*> bad_records; | 167 std::vector<const BuilderRecord*> bad_records; |
176 std::string depstring; | 168 std::string depstring; |
177 for (RecordMap::const_iterator i = records_.begin(); | 169 for (const auto& record_pair : records_) { |
178 i != records_.end(); ++i) { | 170 const BuilderRecord* src = record_pair.second; |
179 const BuilderRecord* src = i->second; | |
180 if (!src->should_generate()) | 171 if (!src->should_generate()) |
181 continue; // Skip ungenerated nodes. | 172 continue; // Skip ungenerated nodes. |
182 | 173 |
183 if (!src->resolved()) { | 174 if (!src->resolved()) { |
184 bad_records.push_back(src); | 175 bad_records.push_back(src); |
185 | 176 |
186 // Check dependencies. | 177 // Check dependencies. |
187 for (BuilderRecord::BuilderRecordSet::const_iterator dest_iter = | 178 for (const auto& dest : src->unresolved_deps()) { |
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()) { | 179 if (!dest->item()) { |
193 depstring += src->label().GetUserVisibleName(true) + | 180 depstring += src->label().GetUserVisibleName(true) + |
194 "\n needs " + dest->label().GetUserVisibleName(true) + "\n"; | 181 "\n needs " + dest->label().GetUserVisibleName(true) + "\n"; |
195 } | 182 } |
196 } | 183 } |
197 } | 184 } |
198 } | 185 } |
199 | 186 |
200 if (!depstring.empty()) { | 187 if (!depstring.empty()) { |
201 *err = Err(Location(), "Unresolved dependencies.", depstring); | 188 *err = Err(Location(), "Unresolved dependencies.", depstring); |
202 return false; | 189 return false; |
203 } | 190 } |
204 | 191 |
205 if (!bad_records.empty()) { | 192 if (!bad_records.empty()) { |
206 // Our logic above found a bad node but didn't identify the problem. This | 193 // Our logic above found a bad node but didn't identify the problem. This |
207 // normally means a circular dependency. | 194 // normally means a circular dependency. |
208 depstring = CheckForCircularDependencies(bad_records); | 195 depstring = CheckForCircularDependencies(bad_records); |
209 if (depstring.empty()) { | 196 if (depstring.empty()) { |
210 // Something's very wrong, just dump out the bad nodes. | 197 // Something's very wrong, just dump out the bad nodes. |
211 depstring = "I have no idea what went wrong, but these are unresolved, " | 198 depstring = "I have no idea what went wrong, but these are unresolved, " |
212 "possibly due to an\ninternal error:"; | 199 "possibly due to an\ninternal error:"; |
213 for (size_t i = 0; i < bad_records.size(); i++) { | 200 for (const auto& bad_record : bad_records) { |
214 depstring += "\n\"" + | 201 depstring += "\n\"" + |
215 bad_records[i]->label().GetUserVisibleName(false) + "\""; | 202 bad_record->label().GetUserVisibleName(false) + "\""; |
216 } | 203 } |
217 *err = Err(Location(), "", depstring); | 204 *err = Err(Location(), "", depstring); |
218 } else { | 205 } else { |
219 *err = Err(Location(), "Dependency cycle:", depstring); | 206 *err = Err(Location(), "Dependency cycle:", depstring); |
220 } | 207 } |
221 return false; | 208 return false; |
222 } | 209 } |
223 | 210 |
224 return true; | 211 return true; |
225 } | 212 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 item->GetItemTypeName() + " instead of a " + | 308 item->GetItemTypeName() + " instead of a " + |
322 BuilderRecord::GetNameForType(type) + "."); | 309 BuilderRecord::GetNameForType(type) + "."); |
323 return NULL; | 310 return NULL; |
324 } | 311 } |
325 return record; | 312 return record; |
326 } | 313 } |
327 | 314 |
328 bool Builder::AddDeps(BuilderRecord* record, | 315 bool Builder::AddDeps(BuilderRecord* record, |
329 const LabelConfigVector& configs, | 316 const LabelConfigVector& configs, |
330 Err* err) { | 317 Err* err) { |
331 for (size_t i = 0; i < configs.size(); i++) { | 318 for (const auto& config : configs) { |
332 BuilderRecord* dep_record = GetOrCreateRecordOfType( | 319 BuilderRecord* dep_record = GetOrCreateRecordOfType( |
333 configs[i].label, configs[i].origin, BuilderRecord::ITEM_CONFIG, err); | 320 config.label, config.origin, BuilderRecord::ITEM_CONFIG, err); |
334 if (!dep_record) | 321 if (!dep_record) |
335 return false; | 322 return false; |
336 record->AddDep(dep_record); | 323 record->AddDep(dep_record); |
337 } | 324 } |
338 return true; | 325 return true; |
339 } | 326 } |
340 | 327 |
341 bool Builder::AddDeps(BuilderRecord* record, | 328 bool Builder::AddDeps(BuilderRecord* record, |
342 const UniqueVector<LabelConfigPair>& configs, | 329 const UniqueVector<LabelConfigPair>& configs, |
343 Err* err) { | 330 Err* err) { |
344 for (size_t i = 0; i < configs.size(); i++) { | 331 for (const auto& config : configs) { |
345 BuilderRecord* dep_record = GetOrCreateRecordOfType( | 332 BuilderRecord* dep_record = GetOrCreateRecordOfType( |
346 configs[i].label, configs[i].origin, BuilderRecord::ITEM_CONFIG, err); | 333 config.label, config.origin, BuilderRecord::ITEM_CONFIG, err); |
347 if (!dep_record) | 334 if (!dep_record) |
348 return false; | 335 return false; |
349 record->AddDep(dep_record); | 336 record->AddDep(dep_record); |
350 } | 337 } |
351 return true; | 338 return true; |
352 } | 339 } |
353 | 340 |
354 bool Builder::AddDeps(BuilderRecord* record, | 341 bool Builder::AddDeps(BuilderRecord* record, |
355 const LabelTargetVector& targets, | 342 const LabelTargetVector& targets, |
356 Err* err) { | 343 Err* err) { |
357 for (size_t i = 0; i < targets.size(); i++) { | 344 for (const auto& target : targets) { |
358 BuilderRecord* dep_record = GetOrCreateRecordOfType( | 345 BuilderRecord* dep_record = GetOrCreateRecordOfType( |
359 targets[i].label, targets[i].origin, BuilderRecord::ITEM_TARGET, err); | 346 target.label, target.origin, BuilderRecord::ITEM_TARGET, err); |
360 if (!dep_record) | 347 if (!dep_record) |
361 return false; | 348 return false; |
362 record->AddDep(dep_record); | 349 record->AddDep(dep_record); |
363 } | 350 } |
364 return true; | 351 return true; |
365 } | 352 } |
366 | 353 |
367 bool Builder::AddToolchainDep(BuilderRecord* record, | 354 bool Builder::AddToolchainDep(BuilderRecord* record, |
368 const Target* target, | 355 const Target* target, |
369 Err* err) { | 356 Err* err) { |
370 BuilderRecord* toolchain_record = GetOrCreateRecordOfType( | 357 BuilderRecord* toolchain_record = GetOrCreateRecordOfType( |
371 target->settings()->toolchain_label(), target->defined_from(), | 358 target->settings()->toolchain_label(), target->defined_from(), |
372 BuilderRecord::ITEM_TOOLCHAIN, err); | 359 BuilderRecord::ITEM_TOOLCHAIN, err); |
373 if (!toolchain_record) | 360 if (!toolchain_record) |
374 return false; | 361 return false; |
375 record->AddDep(toolchain_record); | 362 record->AddDep(toolchain_record); |
376 | 363 |
377 return true; | 364 return true; |
378 } | 365 } |
379 | 366 |
380 void Builder::RecursiveSetShouldGenerate(BuilderRecord* record, | 367 void Builder::RecursiveSetShouldGenerate(BuilderRecord* record, |
381 bool force) { | 368 bool force) { |
382 if (!force && record->should_generate()) | 369 if (!force && record->should_generate()) |
383 return; // Already set. | 370 return; // Already set. |
384 record->set_should_generate(true); | 371 record->set_should_generate(true); |
385 | 372 |
386 const BuilderRecordSet& deps = record->all_deps(); | 373 for (const auto& cur : 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()) { | 374 if (!cur->should_generate()) { |
391 ScheduleItemLoadIfNecessary(cur); | 375 ScheduleItemLoadIfNecessary(cur); |
392 RecursiveSetShouldGenerate(cur, false); | 376 RecursiveSetShouldGenerate(cur, false); |
393 } | 377 } |
394 } | 378 } |
395 } | 379 } |
396 | 380 |
397 void Builder::ScheduleItemLoadIfNecessary(BuilderRecord* record) { | 381 void Builder::ScheduleItemLoadIfNecessary(BuilderRecord* record) { |
398 const ParseNode* origin = record->originally_referenced_from(); | 382 const ParseNode* origin = record->originally_referenced_from(); |
399 loader_->Load(record->label(), | 383 loader_->Load(record->label(), |
(...skipping 21 matching lines...) Expand all Loading... |
421 } | 405 } |
422 | 406 |
423 record->set_resolved(true); | 407 record->set_resolved(true); |
424 | 408 |
425 if (!record->item()->OnResolved(err)) | 409 if (!record->item()->OnResolved(err)) |
426 return false; | 410 return false; |
427 if (!resolved_callback_.is_null()) | 411 if (!resolved_callback_.is_null()) |
428 resolved_callback_.Run(record); | 412 resolved_callback_.Run(record); |
429 | 413 |
430 // Recursively update everybody waiting on this item to be resolved. | 414 // Recursively update everybody waiting on this item to be resolved. |
431 BuilderRecordSet& waiting_set = record->waiting_on_resolution(); | 415 for (BuilderRecord* waiting : 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) != | 416 DCHECK(waiting->unresolved_deps().find(record) != |
436 waiting->unresolved_deps().end()); | 417 waiting->unresolved_deps().end()); |
437 waiting->unresolved_deps().erase(record); | 418 waiting->unresolved_deps().erase(record); |
438 | 419 |
439 if (waiting->can_resolve()) { | 420 if (waiting->can_resolve()) { |
440 if (!ResolveItem(waiting, err)) | 421 if (!ResolveItem(waiting, err)) |
441 return false; | 422 return false; |
442 } | 423 } |
443 } | 424 } |
444 waiting_set.clear(); | 425 record->waiting_on_resolution().clear(); |
445 return true; | 426 return true; |
446 } | 427 } |
447 | 428 |
448 bool Builder::ResolveDeps(LabelTargetVector* deps, Err* err) { | 429 bool Builder::ResolveDeps(LabelTargetVector* deps, Err* err) { |
449 for (size_t i = 0; i < deps->size(); i++) { | 430 for (LabelTargetPair& cur : *deps) { |
450 LabelTargetPair& cur = (*deps)[i]; | |
451 DCHECK(!cur.ptr); | 431 DCHECK(!cur.ptr); |
452 | 432 |
453 BuilderRecord* record = GetResolvedRecordOfType( | 433 BuilderRecord* record = GetResolvedRecordOfType( |
454 cur.label, cur.origin, BuilderRecord::ITEM_TARGET, err); | 434 cur.label, cur.origin, BuilderRecord::ITEM_TARGET, err); |
455 if (!record) | 435 if (!record) |
456 return false; | 436 return false; |
457 cur.ptr = record->item()->AsTarget(); | 437 cur.ptr = record->item()->AsTarget(); |
458 } | 438 } |
459 return true; | 439 return true; |
460 } | 440 } |
461 | 441 |
462 bool Builder::ResolveConfigs(UniqueVector<LabelConfigPair>* configs, Err* err) { | 442 bool Builder::ResolveConfigs(UniqueVector<LabelConfigPair>* configs, Err* err) { |
463 for (size_t i = 0; i < configs->size(); i++) { | 443 for (const auto& cur : *configs) { |
464 const LabelConfigPair& cur = (*configs)[i]; | |
465 DCHECK(!cur.ptr); | 444 DCHECK(!cur.ptr); |
466 | 445 |
467 BuilderRecord* record = GetResolvedRecordOfType( | 446 BuilderRecord* record = GetResolvedRecordOfType( |
468 cur.label, cur.origin, BuilderRecord::ITEM_CONFIG, err); | 447 cur.label, cur.origin, BuilderRecord::ITEM_CONFIG, err); |
469 if (!record) | 448 if (!record) |
470 return false; | 449 return false; |
471 const_cast<LabelConfigPair&>(cur).ptr = record->item()->AsConfig(); | 450 const_cast<LabelConfigPair&>(cur).ptr = record->item()->AsConfig(); |
472 } | 451 } |
473 return true; | 452 return true; |
474 } | 453 } |
475 | 454 |
476 // "Forward dependent configs" should refer to targets in the deps that should | 455 // "Forward dependent configs" should refer to targets in the deps that should |
477 // have their configs forwarded. | 456 // have their configs forwarded. |
478 bool Builder::ResolveForwardDependentConfigs(Target* target, Err* err) { | 457 bool Builder::ResolveForwardDependentConfigs(Target* target, Err* err) { |
479 const UniqueVector<LabelTargetPair>& configs = | 458 const UniqueVector<LabelTargetPair>& configs = |
480 target->forward_dependent_configs(); | 459 target->forward_dependent_configs(); |
481 | 460 |
482 // Assume that the lists are small so that brute-force n^2 is appropriate. | 461 // 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++) { | 462 for (const auto& config : configs) { |
484 for (const auto& dep_pair : target->GetDeps(Target::DEPS_LINKED)) { | 463 for (const auto& dep_pair : target->GetDeps(Target::DEPS_LINKED)) { |
485 if (configs[config_i].label == dep_pair.label) { | 464 if (config.label == dep_pair.label) { |
486 DCHECK(dep_pair.ptr); // Should already be resolved. | 465 DCHECK(dep_pair.ptr); // Should already be resolved. |
487 // UniqueVector's contents are constant so uniqueness is preserved, but | 466 // UniqueVector's contents are constant so uniqueness is preserved, but |
488 // we want to update this pointer which doesn't change uniqueness | 467 // we want to update this pointer which doesn't change uniqueness |
489 // (uniqueness in this vector is determined by the label only). | 468 // (uniqueness in this vector is determined by the label only). |
490 const_cast<LabelTargetPair&>(configs[config_i]).ptr = dep_pair.ptr; | 469 const_cast<LabelTargetPair&>(config).ptr = dep_pair.ptr; |
491 break; | 470 break; |
492 } | 471 } |
493 } | 472 } |
494 if (!configs[config_i].ptr) { | 473 if (!config.ptr) { |
495 *err = Err(target->defined_from(), | 474 *err = Err(target->defined_from(), |
496 "Target in forward_dependent_configs_from was not listed in the deps", | 475 "Target in forward_dependent_configs_from was not listed in the deps", |
497 "This target has a forward_dependent_configs_from entry that was " | 476 "This target has a forward_dependent_configs_from entry that was " |
498 "not present in\nthe deps. A target can only forward things it " | 477 "not present in\nthe deps. A target can only forward things it " |
499 "depends on. It was forwarding:\n " + | 478 "depends on. It was forwarding:\n " + |
500 configs[config_i].label.GetUserVisibleName(false)); | 479 config.label.GetUserVisibleName(false)); |
501 return false; | 480 return false; |
502 } | 481 } |
503 } | 482 } |
504 return true; | 483 return true; |
505 } | 484 } |
506 | 485 |
507 bool Builder::ResolveToolchain(Target* target, Err* err) { | 486 bool Builder::ResolveToolchain(Target* target, Err* err) { |
508 BuilderRecord* record = GetResolvedRecordOfType( | 487 BuilderRecord* record = GetResolvedRecordOfType( |
509 target->settings()->toolchain_label(), target->defined_from(), | 488 target->settings()->toolchain_label(), target->defined_from(), |
510 BuilderRecord::ITEM_TOOLCHAIN, err); | 489 BuilderRecord::ITEM_TOOLCHAIN, err); |
(...skipping 20 matching lines...) Expand all Loading... |
531 std::string ret; | 510 std::string ret; |
532 for (size_t i = 0; i < cycle.size(); i++) { | 511 for (size_t i = 0; i < cycle.size(); i++) { |
533 ret += " " + cycle[i]->label().GetUserVisibleName(false); | 512 ret += " " + cycle[i]->label().GetUserVisibleName(false); |
534 if (i != cycle.size() - 1) | 513 if (i != cycle.size() - 1) |
535 ret += " ->"; | 514 ret += " ->"; |
536 ret += "\n"; | 515 ret += "\n"; |
537 } | 516 } |
538 | 517 |
539 return ret; | 518 return ret; |
540 } | 519 } |
OLD | NEW |