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/item_node.h" 6 7 #include <algorithm> 8 9 #include "base/callback.h" 10 #include "base/logging.h" 11 #include "tools/gn/build_settings.h" 12 #include "tools/gn/item.h" 13 14 ItemNode::ItemNode(Item* i) 15 : state_(REFERENCED), 16 item_(i), 17 should_generate_(false) { 18 } 19 20 ItemNode::~ItemNode() { 21 } 22 23 bool ItemNode::SetShouldGenerate(const BuildSettings* build_settings, 24 Err* err) { 25 if (should_generate_) 26 return true; 27 should_generate_ = true; 28 29 if (state_ == DEFINED) { 30 if (!ScheduleDepsLoad(build_settings, err)) 31 return false; 32 } else if (state_ == RESOLVED) { 33 // The item may have been resolved even if we didn't set the generate bit 34 // if all of its deps were loaded some other way. In this case, we need 35 // to run the closure which we skipped when it became resolved. 36 if (!resolved_closure_.is_null()) 37 resolved_closure_.Run(); 38 } 39 40 // Pass the generate bit to all deps. 41 for (ItemNodeMap::iterator i = direct_dependencies_.begin(); 42 i != direct_dependencies_.end(); ++i) { 43 if (!i->first->SetShouldGenerate(build_settings, err)) 44 return false; 45 } 46 return true; 47 } 48 49 bool ItemNode::AddDependency(const BuildSettings* build_settings, 50 const LocationRange& specified_from_here, 51 ItemNode* node, 52 Err* err) { 53 // Can't add more deps once it's been defined. 54 DCHECK(state_ == REFERENCED); 55 56 if (direct_dependencies_.find(node) != direct_dependencies_.end()) 57 return true; // Already have this dep. 58 59 direct_dependencies_[node] = specified_from_here; 60 61 if (node->state() != RESOLVED) { 62 // Wire up the pending resolution info. 63 unresolved_dependencies_[node] = specified_from_here; 64 node->waiting_on_resolution_[this] = specified_from_here; 65 } 66 67 if (should_generate_) { 68 if (!node->SetShouldGenerate(build_settings, err)) 69 return false; 70 } 71 return true; 72 } 73 74 void ItemNode::MarkDirectDependencyResolved(ItemNode* node) { 75 DCHECK(unresolved_dependencies_.find(node) != unresolved_dependencies_.end()); 76 unresolved_dependencies_.erase(node); 77 } 78 79 void ItemNode::SwapOutWaitingDependencySet(ItemNodeMap* out_map) { 80 waiting_on_resolution_.swap(*out_map); 81 DCHECK(waiting_on_resolution_.empty()); 82 } 83 84 bool ItemNode::SetDefined(const BuildSettings* build_settings, Err* err) { 85 DCHECK(state_ == REFERENCED); 86 state_ = DEFINED; 87 88 if (should_generate_) 89 return ScheduleDepsLoad(build_settings, err); 90 return true; 91 } 92 93 void ItemNode::SetResolved() { 94 DCHECK(state_ != RESOLVED); 95 state_ = RESOLVED; 96 97 if (should_generate_ && !resolved_closure_.is_null()) 98 resolved_closure_.Run(); 99 } 100 101 bool ItemNode::ScheduleDepsLoad(const BuildSettings* build_settings, 102 Err* err) { 103 DCHECK(state_ == DEFINED); 104 DCHECK(should_generate_); // Shouldn't be requesting deps for ungenerated 105 // items. 106 107 for (ItemNodeMap::const_iterator i = unresolved_dependencies_.begin(); 108 i != unresolved_dependencies_.end(); ++i) { 109 Label toolchain_label = i->first->item()->label().GetToolchainLabel(); 110 SourceDir dir_to_load = i->first->item()->label().dir(); 111 112 if (!build_settings->toolchain_manager().ScheduleInvocationLocked( 113 i->second, toolchain_label, dir_to_load, err)) 114 return false; 115 } 116 117 state_ = PENDING_DEPS; 118 return true; 119 } 120