| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "tools/gn/target.h" | 5 #include "tools/gn/target.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
| 9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 10 #include "tools/gn/config_values_extractors.h" | 10 #include "tools/gn/config_values_extractors.h" |
| 11 #include "tools/gn/filesystem_utils.h" | 11 #include "tools/gn/filesystem_utils.h" |
| 12 #include "tools/gn/scheduler.h" | 12 #include "tools/gn/scheduler.h" |
| 13 #include "tools/gn/substitution_writer.h" | 13 #include "tools/gn/substitution_writer.h" |
| 14 | 14 |
| 15 namespace { | 15 namespace { |
| 16 | 16 |
| 17 typedef std::set<const Config*> ConfigSet; | 17 typedef std::set<const Config*> ConfigSet; |
| 18 | 18 |
| 19 // Merges the dependent configs from the given target to the given config list. | 19 // Merges the public configs from the given target to the given config list. |
| 20 void MergeDirectDependentConfigsFrom(const Target* from_target, | 20 void MergePublicConfigsFrom(const Target* from_target, |
| 21 UniqueVector<LabelConfigPair>* dest) { | 21 UniqueVector<LabelConfigPair>* dest) { |
| 22 const UniqueVector<LabelConfigPair>& direct = | 22 const UniqueVector<LabelConfigPair>& pub = from_target->public_configs(); |
| 23 from_target->direct_dependent_configs(); | 23 for (size_t i = 0; i < pub.size(); i++) |
| 24 for (size_t i = 0; i < direct.size(); i++) | 24 dest->push_back(pub[i]); |
| 25 dest->push_back(direct[i]); | |
| 26 } | 25 } |
| 27 | 26 |
| 28 // Like MergeDirectDependentConfigsFrom above except does the "all dependent" | 27 // Like MergePublicConfigsFrom above except does the "all dependent" ones. This |
| 29 // ones. This additionally adds all configs to the all_dependent_configs_ of | 28 // additionally adds all configs to the all_dependent_configs_ of the dest |
| 30 // the dest target given in *all_dest. | 29 // target given in *all_dest. |
| 31 void MergeAllDependentConfigsFrom(const Target* from_target, | 30 void MergeAllDependentConfigsFrom(const Target* from_target, |
| 32 UniqueVector<LabelConfigPair>* dest, | 31 UniqueVector<LabelConfigPair>* dest, |
| 33 UniqueVector<LabelConfigPair>* all_dest) { | 32 UniqueVector<LabelConfigPair>* all_dest) { |
| 34 const UniqueVector<LabelConfigPair>& all = | 33 const UniqueVector<LabelConfigPair>& all = |
| 35 from_target->all_dependent_configs(); | 34 from_target->all_dependent_configs(); |
| 36 for (size_t i = 0; i < all.size(); i++) { | 35 for (size_t i = 0; i < all.size(); i++) { |
| 37 all_dest->push_back(all[i]); | 36 all_dest->push_back(all[i]); |
| 38 dest->push_back(all[i]); | 37 dest->push_back(all[i]); |
| 39 } | 38 } |
| 40 } | 39 } |
| 41 | 40 |
| 42 Err MakeTestOnlyError(const Target* from, const Target* to) { | 41 Err MakeTestOnlyError(const Target* from, const Target* to) { |
| 43 return Err(from->defined_from(), "Test-only dependency not allowed.", | 42 return Err(from->defined_from(), "Test-only dependency not allowed.", |
| 44 from->label().GetUserVisibleName(false) + "\n" | 43 from->label().GetUserVisibleName(false) + "\n" |
| 45 "which is NOT marked testonly can't depend on\n" + | 44 "which is NOT marked testonly can't depend on\n" + |
| 46 to->label().GetUserVisibleName(false) + "\n" | 45 to->label().GetUserVisibleName(false) + "\n" |
| 47 "which is marked testonly. Only targets with \"testonly = true\"\n" | 46 "which is marked testonly. Only targets with \"testonly = true\"\n" |
| 48 "can depend on other test-only targets.\n" | 47 "can depend on other test-only targets.\n" |
| 49 "\n" | 48 "\n" |
| 50 "Either mark it test-only or don't do this dependency."); | 49 "Either mark it test-only or don't do this dependency."); |
| 51 } | 50 } |
| 52 | 51 |
| 53 // Inserts the given groups dependencies, starting at the given index of the | |
| 54 // given vector. Returns the number of items inserted. | |
| 55 size_t InsertGroupDeps(LabelTargetVector* vector, | |
| 56 size_t insert_at, | |
| 57 const Target* group) { | |
| 58 const LabelTargetVector& deps = group->deps(); | |
| 59 vector->insert(vector->begin() + insert_at, deps.begin(), deps.end()); | |
| 60 | |
| 61 // Clear the origin of each of the insertions. This marks these dependencies | |
| 62 // as internally generated. | |
| 63 for (size_t i = insert_at; i < deps.size() + insert_at; i++) | |
| 64 (*vector)[i].origin = NULL; | |
| 65 | |
| 66 return deps.size(); | |
| 67 } | |
| 68 | |
| 69 } // namespace | 52 } // namespace |
| 70 | 53 |
| 71 Target::Target(const Settings* settings, const Label& label) | 54 Target::Target(const Settings* settings, const Label& label) |
| 72 : Item(settings, label), | 55 : Item(settings, label), |
| 73 output_type_(UNKNOWN), | 56 output_type_(UNKNOWN), |
| 74 all_headers_public_(true), | 57 all_headers_public_(true), |
| 75 check_includes_(true), | 58 check_includes_(true), |
| 76 complete_static_lib_(false), | 59 complete_static_lib_(false), |
| 77 testonly_(false), | 60 testonly_(false), |
| 78 hard_dep_(false), | 61 hard_dep_(false), |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 } | 96 } |
| 114 | 97 |
| 115 const Target* Target::AsTarget() const { | 98 const Target* Target::AsTarget() const { |
| 116 return this; | 99 return this; |
| 117 } | 100 } |
| 118 | 101 |
| 119 bool Target::OnResolved(Err* err) { | 102 bool Target::OnResolved(Err* err) { |
| 120 DCHECK(output_type_ != UNKNOWN); | 103 DCHECK(output_type_ != UNKNOWN); |
| 121 DCHECK(toolchain_) << "Toolchain should have been set before resolving."; | 104 DCHECK(toolchain_) << "Toolchain should have been set before resolving."; |
| 122 | 105 |
| 123 ExpandGroups(); | |
| 124 | |
| 125 // Copy our own dependent configs to the list of configs applying to us. | 106 // Copy our own dependent configs to the list of configs applying to us. |
| 126 configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end()); | 107 configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end()); |
| 127 configs_.Append(direct_dependent_configs_.begin(), | 108 configs_.Append(public_configs_.begin(), public_configs_.end()); |
| 128 direct_dependent_configs_.end()); | |
| 129 | 109 |
| 130 // Copy our own libs and lib_dirs to the final set. This will be from our | 110 // Copy our own libs and lib_dirs to the final set. This will be from our |
| 131 // target and all of our configs. We do this specially since these must be | 111 // target and all of our configs. We do this specially since these must be |
| 132 // inherited through the dependency tree (other flags don't work this way). | 112 // inherited through the dependency tree (other flags don't work this way). |
| 133 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) { | 113 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) { |
| 134 const ConfigValues& cur = iter.cur(); | 114 const ConfigValues& cur = iter.cur(); |
| 135 all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end()); | 115 all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end()); |
| 136 all_libs_.append(cur.libs().begin(), cur.libs().end()); | 116 all_libs_.append(cur.libs().begin(), cur.libs().end()); |
| 137 } | 117 } |
| 138 | 118 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 "Alas, I can not continue.", | 186 "Alas, I can not continue.", |
| 207 label().GetUserVisibleName(false).c_str(), | 187 label().GetUserVisibleName(false).c_str(), |
| 208 GetStringForOutputType(output_type_), | 188 GetStringForOutputType(output_type_), |
| 209 label().GetToolchainLabel().GetUserVisibleName(false).c_str(), | 189 label().GetToolchainLabel().GetUserVisibleName(false).c_str(), |
| 210 Toolchain::ToolTypeToName( | 190 Toolchain::ToolTypeToName( |
| 211 toolchain->GetToolTypeForTargetFinalOutput(this)).c_str())); | 191 toolchain->GetToolTypeForTargetFinalOutput(this)).c_str())); |
| 212 } | 192 } |
| 213 return false; | 193 return false; |
| 214 } | 194 } |
| 215 | 195 |
| 216 void Target::ExpandGroups() { | |
| 217 // Convert any groups we depend on to just direct dependencies on that | |
| 218 // group's deps. We insert the new deps immediately after the group so that | |
| 219 // the ordering is preserved. We need to keep the original group so that any | |
| 220 // flags, etc. that it specifies itself are applied to us. | |
| 221 // TODO(brettw) bug 403488 this should also handle datadeps. | |
| 222 for (size_t i = 0; i < deps_.size(); i++) { | |
| 223 const Target* dep = deps_[i].ptr; | |
| 224 if (dep->output_type_ == GROUP) | |
| 225 i += InsertGroupDeps(&deps_, i + 1, dep); | |
| 226 } | |
| 227 } | |
| 228 | |
| 229 void Target::PullDependentTargetInfo() { | 196 void Target::PullDependentTargetInfo() { |
| 230 // Gather info from our dependents we need. | 197 // Gather info from our dependents we need. |
| 231 for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) { | 198 for (DepsIterator iter(this, DepsIterator::LINKED_ONLY); !iter.done(); |
| 232 const Target* dep = deps_[dep_i].ptr; | 199 iter.Advance()) { |
| 200 const Target* dep = iter.target(); |
| 233 MergeAllDependentConfigsFrom(dep, &configs_, &all_dependent_configs_); | 201 MergeAllDependentConfigsFrom(dep, &configs_, &all_dependent_configs_); |
| 234 MergeDirectDependentConfigsFrom(dep, &configs_); | 202 MergePublicConfigsFrom(dep, &configs_); |
| 235 | 203 |
| 236 // Direct dependent libraries. | 204 // Direct dependent libraries. |
| 237 if (dep->output_type() == STATIC_LIBRARY || | 205 if (dep->output_type() == STATIC_LIBRARY || |
| 238 dep->output_type() == SHARED_LIBRARY || | 206 dep->output_type() == SHARED_LIBRARY || |
| 239 dep->output_type() == SOURCE_SET) | 207 dep->output_type() == SOURCE_SET) |
| 240 inherited_libraries_.push_back(dep); | 208 inherited_libraries_.push_back(dep); |
| 241 | 209 |
| 242 // Inherited libraries and flags are inherited across static library | 210 // Inherited libraries and flags are inherited across static library |
| 243 // boundaries. | 211 // boundaries. |
| 244 if (!dep->IsFinal()) { | 212 if (!dep->IsFinal()) { |
| 245 inherited_libraries_.Append(dep->inherited_libraries().begin(), | 213 inherited_libraries_.Append(dep->inherited_libraries().begin(), |
| 246 dep->inherited_libraries().end()); | 214 dep->inherited_libraries().end()); |
| 247 | 215 |
| 248 // Inherited library settings. | 216 // Inherited library settings. |
| 249 all_lib_dirs_.append(dep->all_lib_dirs()); | 217 all_lib_dirs_.append(dep->all_lib_dirs()); |
| 250 all_libs_.append(dep->all_libs()); | 218 all_libs_.append(dep->all_libs()); |
| 251 } | 219 } |
| 252 } | 220 } |
| 253 } | 221 } |
| 254 | 222 |
| 255 void Target::PullForwardedDependentConfigs() { | 223 void Target::PullForwardedDependentConfigs() { |
| 256 // Groups implicitly forward all if its dependency's configs. | 224 // Pull public configs from each of our dependency's public deps. |
| 257 if (output_type() == GROUP) { | 225 for (size_t dep = 0; dep < public_deps_.size(); dep++) |
| 258 for (size_t i = 0; i < deps_.size(); i++) | 226 PullForwardedDependentConfigsFrom(public_deps_[dep].ptr); |
| 259 forward_dependent_configs_.push_back(deps_[i]); | |
| 260 } | |
| 261 | 227 |
| 262 // Forward direct dependent configs if requested. | 228 // Forward public configs if explicitly requested. |
| 263 for (size_t dep = 0; dep < forward_dependent_configs_.size(); dep++) { | 229 for (size_t dep = 0; dep < forward_dependent_configs_.size(); dep++) { |
| 264 const Target* from_target = forward_dependent_configs_[dep].ptr; | 230 const Target* from_target = forward_dependent_configs_[dep].ptr; |
| 265 | 231 |
| 266 // The forward_dependent_configs_ must be in the deps already, so we | 232 // The forward_dependent_configs_ must be in the deps (public or private) |
| 267 // don't need to bother copying to our configs, only forwarding. | 233 // already, so we don't need to bother copying to our configs, only |
| 268 DCHECK(std::find_if(deps_.begin(), deps_.end(), | 234 // forwarding. |
| 235 DCHECK(std::find_if(private_deps_.begin(), private_deps_.end(), |
| 269 LabelPtrPtrEquals<Target>(from_target)) != | 236 LabelPtrPtrEquals<Target>(from_target)) != |
| 270 deps_.end()); | 237 private_deps_.end() || |
| 271 direct_dependent_configs_.Append( | 238 std::find_if(public_deps_.begin(), public_deps_.end(), |
| 272 from_target->direct_dependent_configs().begin(), | 239 LabelPtrPtrEquals<Target>(from_target)) != |
| 273 from_target->direct_dependent_configs().end()); | 240 public_deps_.end()); |
| 241 |
| 242 PullForwardedDependentConfigsFrom(from_target); |
| 274 } | 243 } |
| 275 } | 244 } |
| 276 | 245 |
| 246 void Target::PullForwardedDependentConfigsFrom(const Target* from) { |
| 247 public_configs_.Append(from->public_configs().begin(), |
| 248 from->public_configs().end()); |
| 249 } |
| 250 |
| 277 void Target::PullRecursiveHardDeps() { | 251 void Target::PullRecursiveHardDeps() { |
| 278 for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) { | 252 for (DepsIterator iter(this, DepsIterator::LINKED_ONLY); !iter.done(); |
| 279 const Target* dep = deps_[dep_i].ptr; | 253 iter.Advance()) { |
| 280 if (dep->hard_dep()) | 254 if (iter.target()->hard_dep()) |
| 281 recursive_hard_deps_.insert(dep); | 255 recursive_hard_deps_.insert(iter.target()); |
| 282 | 256 |
| 283 // Android STL doesn't like insert(begin, end) so do it manually. | 257 // Android STL doesn't like insert(begin, end) so do it manually. |
| 284 // TODO(brettw) this can be changed to insert(dep->begin(), dep->end()) when | 258 // TODO(brettw) this can be changed to |
| 285 // Android uses a better STL. | 259 // insert(iter.target()->begin(), iter.target()->end()) |
| 260 // when Android uses a better STL. |
| 286 for (std::set<const Target*>::const_iterator cur = | 261 for (std::set<const Target*>::const_iterator cur = |
| 287 dep->recursive_hard_deps().begin(); | 262 iter.target()->recursive_hard_deps().begin(); |
| 288 cur != dep->recursive_hard_deps().end(); ++cur) | 263 cur != iter.target()->recursive_hard_deps().end(); ++cur) |
| 289 recursive_hard_deps_.insert(*cur); | 264 recursive_hard_deps_.insert(*cur); |
| 290 } | 265 } |
| 291 } | 266 } |
| 292 | 267 |
| 293 void Target::FillOutputFiles() { | 268 void Target::FillOutputFiles() { |
| 294 const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this); | 269 const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this); |
| 295 switch (output_type_) { | 270 switch (output_type_) { |
| 296 case GROUP: | 271 case GROUP: |
| 297 case SOURCE_SET: | 272 case SOURCE_SET: |
| 298 case COPY_FILES: | 273 case COPY_FILES: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 } | 318 } |
| 344 } | 319 } |
| 345 break; | 320 break; |
| 346 case UNKNOWN: | 321 case UNKNOWN: |
| 347 default: | 322 default: |
| 348 NOTREACHED(); | 323 NOTREACHED(); |
| 349 } | 324 } |
| 350 } | 325 } |
| 351 | 326 |
| 352 bool Target::CheckVisibility(Err* err) const { | 327 bool Target::CheckVisibility(Err* err) const { |
| 353 // Only check visibility when the origin of the dependency is non-null. These | 328 for (DepsIterator iter(this); !iter.done(); iter.Advance()) { |
| 354 // are dependencies added by the GN files. Internally added dependencies | 329 if (!Visibility::CheckItemVisibility(this, iter.target(), err)) |
| 355 // (expanded groups) will have a null origin. We don't want to check | |
| 356 // visibility for these, since the point of a group would often be to | |
| 357 // forward visibility. | |
| 358 for (size_t i = 0; i < deps_.size(); i++) { | |
| 359 if (deps_[i].origin && | |
| 360 !Visibility::CheckItemVisibility(this, deps_[i].ptr, err)) | |
| 361 return false; | 330 return false; |
| 362 } | 331 } |
| 363 | |
| 364 for (size_t i = 0; i < datadeps_.size(); i++) { | |
| 365 if (datadeps_[i].origin && | |
| 366 !Visibility::CheckItemVisibility(this, datadeps_[i].ptr, err)) | |
| 367 return false; | |
| 368 } | |
| 369 | |
| 370 return true; | 332 return true; |
| 371 } | 333 } |
| 372 | 334 |
| 373 bool Target::CheckTestonly(Err* err) const { | 335 bool Target::CheckTestonly(Err* err) const { |
| 374 // If there current target is marked testonly, it can include both testonly | 336 // If there current target is marked testonly, it can include both testonly |
| 375 // and non-testonly targets, so there's nothing to check. | 337 // and non-testonly targets, so there's nothing to check. |
| 376 if (testonly()) | 338 if (testonly()) |
| 377 return true; | 339 return true; |
| 378 | 340 |
| 379 // Verify no deps have "testonly" set. | 341 // Verify no deps have "testonly" set. |
| 380 for (size_t i = 0; i < deps_.size(); i++) { | 342 for (DepsIterator iter(this); !iter.done(); iter.Advance()) { |
| 381 if (deps_[i].ptr->testonly()) { | 343 if (iter.target()->testonly()) { |
| 382 *err = MakeTestOnlyError(this, deps_[i].ptr); | 344 *err = MakeTestOnlyError(this, iter.target()); |
| 383 return false; | |
| 384 } | |
| 385 } | |
| 386 | |
| 387 for (size_t i = 0; i < datadeps_.size(); i++) { | |
| 388 if (datadeps_[i].ptr->testonly()) { | |
| 389 *err = MakeTestOnlyError(this, datadeps_[i].ptr); | |
| 390 return false; | 345 return false; |
| 391 } | 346 } |
| 392 } | 347 } |
| 393 | 348 |
| 394 return true; | 349 return true; |
| 395 } | 350 } |
| 351 |
| 352 |
| 353 DepsIterator::DepsIterator(const Target* t) : current_index_(0) { |
| 354 vect_stack_[0] = &t->public_deps(); |
| 355 vect_stack_[1] = &t->private_deps(); |
| 356 vect_stack_[2] = &t->data_deps(); |
| 357 |
| 358 if (vect_stack_[0]->empty()) |
| 359 Advance(); |
| 360 } |
| 361 |
| 362 // Iterate over the public and private linked deps, but not the data deps. |
| 363 DepsIterator::DepsIterator(const Target* t, LinkedOnly) : current_index_(0) { |
| 364 vect_stack_[0] = &t->public_deps(); |
| 365 vect_stack_[1] = &t->private_deps(); |
| 366 vect_stack_[2] = NULL; |
| 367 |
| 368 if (vect_stack_[0]->empty()) |
| 369 Advance(); |
| 370 } |
| 371 |
| 372 // Advance to the next position. This assumes there are more vectors. |
| 373 // |
| 374 // For internal use, this function tolerates an initial index equal to the |
| 375 // length of the current vector. In this case, it will advance to the next |
| 376 // one. |
| 377 void DepsIterator::Advance() { |
| 378 DCHECK(vect_stack_[0]); |
| 379 |
| 380 current_index_++; |
| 381 if (current_index_ >= vect_stack_[0]->size()) { |
| 382 // Advance to next vect. Shift the elements left by one. |
| 383 vect_stack_[0] = vect_stack_[1]; |
| 384 vect_stack_[1] = vect_stack_[2]; |
| 385 vect_stack_[2] = NULL; |
| 386 |
| 387 current_index_ = 0; |
| 388 |
| 389 if (vect_stack_[0] && vect_stack_[0]->empty()) |
| 390 Advance(); |
| 391 } |
| 392 } |
| OLD | NEW |