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. 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 57 Builder::Builder(Loader* loader) : loader_(loader) { 58 } 59 60 Builder::~Builder() { 61 } 62 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 114 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 121 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 130 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 139 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 151 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 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 163 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 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 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 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 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 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 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 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 360 void Builder::ScheduleItemLoadIfNecessary(BuilderRecord* record) { 361 loader_->Load(record->label()); 362 } 363 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 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 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. 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 456 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