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/target_manager.h" 6 7 #include <deque> 8 9 #include "base/bind.h" 10 #include "base/strings/string_piece.h" 11 #include "tools/gn/build_settings.h" 12 #include "tools/gn/err.h" 13 #include "tools/gn/filesystem_utils.h" 14 #include "tools/gn/item_node.h" 15 #include "tools/gn/scheduler.h" 16 #include "tools/gn/toolchain_manager.h" 17 #include "tools/gn/value.h" 18 19 TargetManager::TargetManager(const BuildSettings* build_settings) 20 : build_settings_(build_settings) { 21 } 22 23 TargetManager::~TargetManager() { 24 } 25 26 Target* TargetManager::GetTarget(const Label& label, 27 const LocationRange& specified_from_here, 28 Target* dep_from, 29 Err* err) { 30 DCHECK(!label.is_null()); 31 DCHECK(!label.toolchain_dir().value().empty()); 32 DCHECK(!label.toolchain_name().empty()); 33 34 base::AutoLock lock(build_settings_->item_tree().lock()); 35 36 ItemNode* target_node = 37 build_settings_->item_tree().GetExistingNodeLocked(label); 38 Target* target = NULL; 39 if (!target_node) { 40 // First time we've seen this, may need to load the file. 41 42 // Compute the settings. The common case is that we have a dep_from and 43 // the toolchains match, so we can use the settings from there rather than 44 // querying the toolchain manager (which requires locking, etc.). 45 const Settings* settings; 46 if (dep_from && dep_from->label().ToolchainsEqual(label)) { 47 settings = dep_from->settings(); 48 } else { 49 settings = 50 build_settings_->toolchain_manager().GetSettingsForToolchainLocked( 51 specified_from_here, label.GetToolchainLabel(), err); 52 if (!settings) 53 return NULL; 54 } 55 56 target = new Target(settings, label); 57 58 target_node = new ItemNode(target); 59 if (settings->greedy_target_generation()) { 60 if (!target_node->SetShouldGenerate(build_settings_, err)) 61 return NULL; 62 } 63 target_node->set_originally_referenced_from_here(specified_from_here); 64 65 build_settings_->item_tree().AddNodeLocked(target_node); 66 67 // We're generating a node when there is no referencing one. 68 if (!dep_from) 69 target_node->set_generated_from_here(specified_from_here); 70 71 } else if ((target = target_node->item()->AsTarget())) { 72 // Previously saw this item as a target. 73 74 // If we have no dep_from, we're generating it. 75 if (!dep_from) { 76 // In this case, it had better not already be generated. 77 if (target_node->state() != ItemNode::REFERENCED) { 78 *err = Err(specified_from_here, 79 "Duplicate target.", 80 "\"" + label.GetUserVisibleName(true) + 81 "\" being defined here."); 82 err->AppendSubErr(Err(target_node->generated_from_here(), 83 "Originally defined here.")); 84 return NULL; 85 } else { 86 target_node->set_generated_from_here(specified_from_here); 87 } 88 } 89 } else { 90 // Error, we previously saw this thing as a non-target. 91 *err = Err(specified_from_here, "Not previously a target.", 92 "The target being declared here was previously seen referenced as a\n" 93 "non-target (like a config)"); 94 err->AppendSubErr(Err(target_node->originally_referenced_from_here(), 95 "Originally referenced from here.")); 96 return NULL; 97 } 98 99 // Keep a record of the guy asking us for this dependency. We know if 100 // somebody is adding a dependency, that guy it himself not resolved. 101 if (dep_from && target_node->state() != ItemNode::RESOLVED) { 102 ItemNode* from_node = 103 build_settings_->item_tree().GetExistingNodeLocked(dep_from->label()); 104 if (!from_node->AddDependency(build_settings_, specified_from_here, 105 target_node, err)) 106 return NULL; 107 } 108 109 return target; 110 } 111 112 bool TargetManager::TargetGenerationComplete(const Label& label, 113 Err* err) { 114 base::AutoLock lock(build_settings_->item_tree().lock()); 115 return build_settings_->item_tree().MarkItemDefinedLocked( 116 build_settings_, label, err); 117 } 118 119 void TargetManager::GetAllTargets( 120 std::vector<const Target*>* all_targets) const { 121 base::AutoLock lock(build_settings_->item_tree().lock()); 122 123 std::vector<const Item*> all_items; 124 build_settings_->item_tree().GetAllItemsLocked(&all_items); 125 for (size_t i = 0; i < all_items.size(); i++) { 126 const Target* t = all_items[i]->AsTarget(); 127 if (t) 128 all_targets->push_back(t); 129 } 130 } 131