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 11 namespace { 12 13 typedef 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. 18 void 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. 33 void 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 54 Target::Target(const Settings* settings, const Label& label) 55 : Item(settings, label), 56 output_type_(UNKNOWN), 57 hard_dep_(false), 58 external_(false) { 59 } 60 61 Target::~Target() { 62 } 63 64 // static 65 const 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 COPY_FILES: 78 return "Copy"; 79 case CUSTOM: 80 return "Custom"; 81 default: 82 return ""; 83 } 84 } 85 86 Target* Target::AsTarget() { 87 return this; 88 } 89 90 const Target* Target::AsTarget() const { 91 return this; 92 } 93 94 void Target::OnResolved() { 95 DCHECK(output_type_ != UNKNOWN); 96 97 // Convert any groups we depend on to just direct dependencies on that 98 // group's deps. We insert the new deps immediately after the group so that 99 // the ordering is preserved. We need to keep the original group so that any 100 // flags, etc. that it specifies itself are applied to us. 101 size_t original_deps_size = deps_.size(); 102 for (size_t i = 0; i < original_deps_size; i++) { 103 const Target* dep = deps_[i].ptr; 104 if (dep->output_type_ == GROUP) { 105 deps_.insert(deps_.begin() + i + 1, dep->deps_.begin(), dep->deps_.end()); 106 i += dep->deps_.size(); 107 } 108 } 109 110 // Only add each config once. First remember the target's configs. 111 ConfigSet unique_configs; 112 for (size_t i = 0; i < configs_.size(); i++) 113 unique_configs.insert(configs_[i].ptr); 114 115 // Copy our own dependent configs to the list of configs applying to us. 116 for (size_t i = 0; i < all_dependent_configs_.size(); i++) { 117 if (unique_configs.find(all_dependent_configs_[i].ptr) == 118 unique_configs.end()) { 119 unique_configs.insert(all_dependent_configs_[i].ptr); 120 configs_.push_back(all_dependent_configs_[i]); 121 } 122 } 123 for (size_t i = 0; i < direct_dependent_configs_.size(); i++) { 124 if (unique_configs.find(direct_dependent_configs_[i].ptr) == 125 unique_configs.end()) { 126 unique_configs.insert(direct_dependent_configs_[i].ptr); 127 configs_.push_back(direct_dependent_configs_[i]); 128 } 129 } 130 131 // Copy our own libs and lib_dirs to the final set. This will be from our 132 // target and all of our configs. We do this specially since these must be 133 // inherited through the dependency tree (other flags don't work this way). 134 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) { 135 const ConfigValues& cur = iter.cur(); 136 all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end()); 137 all_libs_.append(cur.libs().begin(), cur.libs().end()); 138 } 139 140 if (output_type_ != GROUP) { 141 // Don't pull target info like libraries and configs from dependencies into 142 // a group target. When A depends on a group G, the G's dependents will 143 // be treated as direct dependencies of A, so this is unnecessary and will 144 // actually result in duplicated settings (since settings will also be 145 // pulled from G to A in case G has configs directly on it). 146 PullDependentTargetInfo(&unique_configs); 147 } 148 } 149 150 bool Target::IsLinkable() const { 151 return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY; 152 } 153 154 void Target::PullDependentTargetInfo(std::set<const Config*>* unique_configs) { 155 // Gather info from our dependents we need. 156 for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) { 157 const Target* dep = deps_[dep_i].ptr; 158 MergeAllDependentConfigsFrom(dep, unique_configs, &configs_, 159 &all_dependent_configs_); 160 MergeDirectDependentConfigsFrom(dep, unique_configs, &configs_); 161 162 // Direct dependent libraries. 163 if (dep->output_type() == STATIC_LIBRARY || 164 dep->output_type() == SHARED_LIBRARY || 165 dep->output_type() == SOURCE_SET) 166 inherited_libraries_.insert(dep); 167 168 // Inherited libraries and flags are inherited across static library 169 // boundaries. 170 if (dep->output_type() != SHARED_LIBRARY && 171 dep->output_type() != EXECUTABLE) { 172 const std::set<const Target*> inherited = dep->inherited_libraries(); 173 for (std::set<const Target*>::const_iterator i = inherited.begin(); 174 i != inherited.end(); ++i) 175 inherited_libraries_.insert(*i); 176 177 // Inherited library settings. 178 all_lib_dirs_.append(dep->all_lib_dirs()); 179 all_libs_.append(dep->all_libs()); 180 } 181 } 182 183 // Forward direct dependent configs if requested. 184 for (size_t dep = 0; dep < forward_dependent_configs_.size(); dep++) { 185 const Target* from_target = forward_dependent_configs_[dep].ptr; 186 187 // The forward_dependent_configs_ must be in the deps already, so we 188 // don't need to bother copying to our configs, only forwarding. 189 DCHECK(std::find_if(deps_.begin(), deps_.end(), 190 LabelPtrPtrEquals<Target>(from_target)) != 191 deps_.end()); 192 direct_dependent_configs_.insert( 193 direct_dependent_configs_.end(), 194 from_target->direct_dependent_configs().begin(), 195 from_target->direct_dependent_configs().end()); 196 } 197 } 198