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.h" 6 7#include "base/bind.h" 8#include "tools/gn/config_values_extractors.h" 9#include "tools/gn/scheduler.h" 10 11namespace { 12 13typedef std::set<const Config*> ConfigSet; 14 15// Merges the dependent configs from the given target to the given config list. 16// The unique_configs list is used for de-duping so values already added will 17// not be added again. 18void MergeDirectDependentConfigsFrom(const Target* from_target, 19 ConfigSet* unique_configs, 20 LabelConfigVector* dest) { 21 const LabelConfigVector& direct = from_target->direct_dependent_configs(); 22 for (size_t i = 0; i < direct.size(); i++) { 23 if (unique_configs->find(direct[i].ptr) == unique_configs->end()) { 24 unique_configs->insert(direct[i].ptr); 25 dest->push_back(direct[i]); 26 } 27 } 28} 29 30// Like MergeDirectDependentConfigsFrom above except does the "all dependent" 31// ones. This additionally adds all configs to the all_dependent_configs_ of 32// the dest target given in *all_dest. 33void MergeAllDependentConfigsFrom(const Target* from_target, 34 ConfigSet* unique_configs, 35 LabelConfigVector* dest, 36 LabelConfigVector* all_dest) { 37 const LabelConfigVector& all = from_target->all_dependent_configs(); 38 for (size_t i = 0; i < all.size(); i++) { 39 // Always add it to all_dependent_configs_ since it might not be in that 40 // list even if we've seen it applied to this target before. This may 41 // introduce some duplicates in all_dependent_configs_, but those will 42 // we removed when they're actually applied to a target. 43 all_dest->push_back(all[i]); 44 if (unique_configs->find(all[i].ptr) == unique_configs->end()) { 45 // One we haven't seen yet, also apply it to ourselves. 46 dest->push_back(all[i]); 47 unique_configs->insert(all[i].ptr); 48 } 49 } 50} 51 52} // namespace 53 54Target::Target(const Settings* settings, const Label& label) 55 : Item(settings, label), 56 output_type_(UNKNOWN), 57 all_headers_public_(true), 58 hard_dep_(false) { 59} 60 61Target::~Target() { 62} 63 64// static 65const char* Target::GetStringForOutputType(OutputType type) { 66 switch (type) { 67 case UNKNOWN: 68 return "Unknown"; 69 case GROUP: 70 return "Group"; 71 case EXECUTABLE: 72 return "Executable"; 73 case SHARED_LIBRARY: 74 return "Shared library"; 75 case STATIC_LIBRARY: 76 return "Static library"; 77 case SOURCE_SET: 78 return "Source set"; 79 case COPY_FILES: 80 return "Copy"; 81 case ACTION: 82 return "Action"; 83 case ACTION_FOREACH: 84 return "ActionForEach"; 85 default: 86 return ""; 87 } 88} 89 90Target* Target::AsTarget() { 91 return this; 92} 93 94const Target* Target::AsTarget() const { 95 return this; 96} 97 98void Target::OnResolved() { 99 DCHECK(output_type_ != UNKNOWN); 100 101 // Convert any groups we depend on to just direct dependencies on that 102 // group's deps. We insert the new deps immediately after the group so that 103 // the ordering is preserved. We need to keep the original group so that any 104 // flags, etc. that it specifies itself are applied to us. 105 for (size_t i = 0; i < deps_.size(); i++) { 106 const Target* dep = deps_[i].ptr; 107 if (dep->output_type_ == GROUP) { 108 deps_.insert(deps_.begin() + i + 1, dep->deps_.begin(), dep->deps_.end()); 109 i += dep->deps_.size(); 110 } 111 } 112 113 // Only add each config once. First remember the target's configs. 114 ConfigSet unique_configs; 115 for (size_t i = 0; i < configs_.size(); i++) 116 unique_configs.insert(configs_[i].ptr); 117 118 // Copy our own dependent configs to the list of configs applying to us. 119 for (size_t i = 0; i < all_dependent_configs_.size(); i++) { 120 if (unique_configs.find(all_dependent_configs_[i].ptr) == 121 unique_configs.end()) { 122 unique_configs.insert(all_dependent_configs_[i].ptr); 123 configs_.push_back(all_dependent_configs_[i]); 124 } 125 } 126 for (size_t i = 0; i < direct_dependent_configs_.size(); i++) { 127 if (unique_configs.find(direct_dependent_configs_[i].ptr) == 128 unique_configs.end()) { 129 unique_configs.insert(direct_dependent_configs_[i].ptr); 130 configs_.push_back(direct_dependent_configs_[i]); 131 } 132 } 133 134 // Copy our own libs and lib_dirs to the final set. This will be from our 135 // target and all of our configs. We do this specially since these must be 136 // inherited through the dependency tree (other flags don't work this way). 137 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) { 138 const ConfigValues& cur = iter.cur(); 139 all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end()); 140 all_libs_.append(cur.libs().begin(), cur.libs().end()); 141 } 142 143 if (output_type_ != GROUP) { 144 // Don't pull target info like libraries and configs from dependencies into 145 // a group target. When A depends on a group G, the G's dependents will 146 // be treated as direct dependencies of A, so this is unnecessary and will 147 // actually result in duplicated settings (since settings will also be 148 // pulled from G to A in case G has configs directly on it). 149 PullDependentTargetInfo(&unique_configs); 150 } 151 PullForwardedDependentConfigs(); 152 PullRecursiveHardDeps(); 153} 154 155bool Target::IsLinkable() const { 156 return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY; 157} 158 159void Target::PullDependentTargetInfo(std::set<const Config*>* unique_configs) { 160 // Gather info from our dependents we need. 161 for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) { 162 const Target* dep = deps_[dep_i].ptr; 163 MergeAllDependentConfigsFrom(dep, unique_configs, &configs_, 164 &all_dependent_configs_); 165 MergeDirectDependentConfigsFrom(dep, unique_configs, &configs_); 166 167 // Direct dependent libraries. 168 if (dep->output_type() == STATIC_LIBRARY || 169 dep->output_type() == SHARED_LIBRARY || 170 dep->output_type() == SOURCE_SET) 171 inherited_libraries_.insert(dep); 172 173 // Inherited libraries and flags are inherited across static library 174 // boundaries. 175 if (dep->output_type() != SHARED_LIBRARY && 176 dep->output_type() != EXECUTABLE) { 177 const std::set<const Target*> inherited = dep->inherited_libraries(); 178 for (std::set<const Target*>::const_iterator i = inherited.begin(); 179 i != inherited.end(); ++i) 180 inherited_libraries_.insert(*i); 181 182 // Inherited library settings. 183 all_lib_dirs_.append(dep->all_lib_dirs()); 184 all_libs_.append(dep->all_libs()); 185 } 186 } 187} 188 189void Target::PullForwardedDependentConfigs() { 190 // Groups implicitly forward all if its dependency's configs. 191 if (output_type() == GROUP) 192 forward_dependent_configs_ = deps_; 193 194 // Forward direct dependent configs if requested. 195 for (size_t dep = 0; dep < forward_dependent_configs_.size(); dep++) { 196 const Target* from_target = forward_dependent_configs_[dep].ptr; 197 198 // The forward_dependent_configs_ must be in the deps already, so we 199 // don't need to bother copying to our configs, only forwarding. 200 DCHECK(std::find_if(deps_.begin(), deps_.end(), 201 LabelPtrPtrEquals<Target>(from_target)) != 202 deps_.end()); 203 direct_dependent_configs_.insert( 204 direct_dependent_configs_.end(), 205 from_target->direct_dependent_configs().begin(), 206 from_target->direct_dependent_configs().end()); 207 } 208} 209 210void Target::PullRecursiveHardDeps() { 211 for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) { 212 const Target* dep = deps_[dep_i].ptr; 213 if (dep->hard_dep()) 214 recursive_hard_deps_.insert(dep); 215 216 // Android STL doesn't like insert(begin, end) so do it manually. 217 // TODO(brettw) this can be changed to insert(dep->begin(), dep->end()) when 218 // Android uses a better STL. 219 for (std::set<const Target*>::const_iterator cur = 220 dep->recursive_hard_deps().begin(); 221 cur != dep->recursive_hard_deps().end(); ++cur) 222 recursive_hard_deps_.insert(*cur); 223 } 224} 225