| 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" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 UniqueVector<LabelConfigPair>* dest, | 32 UniqueVector<LabelConfigPair>* dest, |
| 33 UniqueVector<LabelConfigPair>* all_dest) { | 33 UniqueVector<LabelConfigPair>* all_dest) { |
| 34 const UniqueVector<LabelConfigPair>& all = | 34 const UniqueVector<LabelConfigPair>& all = |
| 35 from_target->all_dependent_configs(); | 35 from_target->all_dependent_configs(); |
| 36 for (size_t i = 0; i < all.size(); i++) { | 36 for (size_t i = 0; i < all.size(); i++) { |
| 37 all_dest->push_back(all[i]); | 37 all_dest->push_back(all[i]); |
| 38 dest->push_back(all[i]); | 38 dest->push_back(all[i]); |
| 39 } | 39 } |
| 40 } | 40 } |
| 41 | 41 |
| 42 Err MakeTestOnlyError(const Target* from, const Target* to) { |
| 43 return Err(from->defined_from(), "Test-only dependency not allowed.", |
| 44 from->label().GetUserVisibleName(false) + "\n" |
| 45 "which is NOT marked testonly can't depend on\n" + |
| 46 to->label().GetUserVisibleName(false) + "\n" |
| 47 "which is marked testonly. Only targets with \"testonly = true\"\n" |
| 48 "can depend on other test-only targets.\n" |
| 49 "\n" |
| 50 "Either mark it test-only or don't do this dependency."); |
| 51 } |
| 52 |
| 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 |
| 42 } // namespace | 69 } // namespace |
| 43 | 70 |
| 44 Target::Target(const Settings* settings, const Label& label) | 71 Target::Target(const Settings* settings, const Label& label) |
| 45 : Item(settings, label), | 72 : Item(settings, label), |
| 46 output_type_(UNKNOWN), | 73 output_type_(UNKNOWN), |
| 47 all_headers_public_(true), | 74 all_headers_public_(true), |
| 75 testonly_(false), |
| 48 hard_dep_(false), | 76 hard_dep_(false), |
| 49 toolchain_(NULL) { | 77 toolchain_(NULL) { |
| 50 } | 78 } |
| 51 | 79 |
| 52 Target::~Target() { | 80 Target::~Target() { |
| 53 } | 81 } |
| 54 | 82 |
| 55 // static | 83 // static |
| 56 const char* Target::GetStringForOutputType(OutputType type) { | 84 const char* Target::GetStringForOutputType(OutputType type) { |
| 57 switch (type) { | 85 switch (type) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 79 } | 107 } |
| 80 | 108 |
| 81 Target* Target::AsTarget() { | 109 Target* Target::AsTarget() { |
| 82 return this; | 110 return this; |
| 83 } | 111 } |
| 84 | 112 |
| 85 const Target* Target::AsTarget() const { | 113 const Target* Target::AsTarget() const { |
| 86 return this; | 114 return this; |
| 87 } | 115 } |
| 88 | 116 |
| 89 void Target::OnResolved() { | 117 bool Target::OnResolved(Err* err) { |
| 90 DCHECK(output_type_ != UNKNOWN); | 118 DCHECK(output_type_ != UNKNOWN); |
| 91 DCHECK(toolchain_) << "Toolchain should have been set before resolving."; | 119 DCHECK(toolchain_) << "Toolchain should have been set before resolving."; |
| 92 | 120 |
| 93 // Convert any groups we depend on to just direct dependencies on that | 121 ExpandGroups(); |
| 94 // group's deps. We insert the new deps immediately after the group so that | |
| 95 // the ordering is preserved. We need to keep the original group so that any | |
| 96 // flags, etc. that it specifies itself are applied to us. | |
| 97 for (size_t i = 0; i < deps_.size(); i++) { | |
| 98 const Target* dep = deps_[i].ptr; | |
| 99 if (dep->output_type_ == GROUP) { | |
| 100 // TODO(brettw) bug 403488 this should also handle datadeps. | |
| 101 deps_.insert(deps_.begin() + i + 1, dep->deps_.begin(), dep->deps_.end()); | |
| 102 i += dep->deps_.size(); | |
| 103 } | |
| 104 } | |
| 105 | 122 |
| 106 // Copy our own dependent configs to the list of configs applying to us. | 123 // Copy our own dependent configs to the list of configs applying to us. |
| 107 configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end()); | 124 configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end()); |
| 108 configs_.Append(direct_dependent_configs_.begin(), | 125 configs_.Append(direct_dependent_configs_.begin(), |
| 109 direct_dependent_configs_.end()); | 126 direct_dependent_configs_.end()); |
| 110 | 127 |
| 111 // Copy our own libs and lib_dirs to the final set. This will be from our | 128 // Copy our own libs and lib_dirs to the final set. This will be from our |
| 112 // target and all of our configs. We do this specially since these must be | 129 // target and all of our configs. We do this specially since these must be |
| 113 // inherited through the dependency tree (other flags don't work this way). | 130 // inherited through the dependency tree (other flags don't work this way). |
| 114 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) { | 131 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) { |
| 115 const ConfigValues& cur = iter.cur(); | 132 const ConfigValues& cur = iter.cur(); |
| 116 all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end()); | 133 all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end()); |
| 117 all_libs_.append(cur.libs().begin(), cur.libs().end()); | 134 all_libs_.append(cur.libs().begin(), cur.libs().end()); |
| 118 } | 135 } |
| 119 | 136 |
| 120 if (output_type_ != GROUP) { | 137 if (output_type_ != GROUP) { |
| 121 // Don't pull target info like libraries and configs from dependencies into | 138 // Don't pull target info like libraries and configs from dependencies into |
| 122 // a group target. When A depends on a group G, the G's dependents will | 139 // a group target. When A depends on a group G, the G's dependents will |
| 123 // be treated as direct dependencies of A, so this is unnecessary and will | 140 // be treated as direct dependencies of A, so this is unnecessary and will |
| 124 // actually result in duplicated settings (since settings will also be | 141 // actually result in duplicated settings (since settings will also be |
| 125 // pulled from G to A in case G has configs directly on it). | 142 // pulled from G to A in case G has configs directly on it). |
| 126 PullDependentTargetInfo(); | 143 PullDependentTargetInfo(); |
| 127 } | 144 } |
| 128 PullForwardedDependentConfigs(); | 145 PullForwardedDependentConfigs(); |
| 129 PullRecursiveHardDeps(); | 146 PullRecursiveHardDeps(); |
| 130 | 147 |
| 131 FillOutputFiles(); | 148 FillOutputFiles(); |
| 149 |
| 150 if (!CheckVisibility(err)) |
| 151 return false; |
| 152 if (!CheckTestonly(err)) |
| 153 return false; |
| 154 |
| 155 return true; |
| 132 } | 156 } |
| 133 | 157 |
| 134 bool Target::IsLinkable() const { | 158 bool Target::IsLinkable() const { |
| 135 return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY; | 159 return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY; |
| 136 } | 160 } |
| 137 | 161 |
| 138 std::string Target::GetComputedOutputName(bool include_prefix) const { | 162 std::string Target::GetComputedOutputName(bool include_prefix) const { |
| 139 DCHECK(toolchain_) | 163 DCHECK(toolchain_) |
| 140 << "Toolchain must be specified before getting the computed output name."; | 164 << "Toolchain must be specified before getting the computed output name."; |
| 141 | 165 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 "Alas, I can not continue.", | 199 "Alas, I can not continue.", |
| 176 label().GetUserVisibleName(false).c_str(), | 200 label().GetUserVisibleName(false).c_str(), |
| 177 GetStringForOutputType(output_type_), | 201 GetStringForOutputType(output_type_), |
| 178 label().GetToolchainLabel().GetUserVisibleName(false).c_str(), | 202 label().GetToolchainLabel().GetUserVisibleName(false).c_str(), |
| 179 Toolchain::ToolTypeToName( | 203 Toolchain::ToolTypeToName( |
| 180 toolchain->GetToolTypeForTargetFinalOutput(this)).c_str())); | 204 toolchain->GetToolTypeForTargetFinalOutput(this)).c_str())); |
| 181 } | 205 } |
| 182 return false; | 206 return false; |
| 183 } | 207 } |
| 184 | 208 |
| 209 void Target::ExpandGroups() { |
| 210 // Convert any groups we depend on to just direct dependencies on that |
| 211 // group's deps. We insert the new deps immediately after the group so that |
| 212 // the ordering is preserved. We need to keep the original group so that any |
| 213 // flags, etc. that it specifies itself are applied to us. |
| 214 // TODO(brettw) bug 403488 this should also handle datadeps. |
| 215 for (size_t i = 0; i < deps_.size(); i++) { |
| 216 const Target* dep = deps_[i].ptr; |
| 217 if (dep->output_type_ == GROUP) |
| 218 i += InsertGroupDeps(&deps_, i + 1, dep); |
| 219 } |
| 220 } |
| 221 |
| 185 void Target::PullDependentTargetInfo() { | 222 void Target::PullDependentTargetInfo() { |
| 186 // Gather info from our dependents we need. | 223 // Gather info from our dependents we need. |
| 187 for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) { | 224 for (size_t dep_i = 0; dep_i < deps_.size(); dep_i++) { |
| 188 const Target* dep = deps_[dep_i].ptr; | 225 const Target* dep = deps_[dep_i].ptr; |
| 189 MergeAllDependentConfigsFrom(dep, &configs_, &all_dependent_configs_); | 226 MergeAllDependentConfigsFrom(dep, &configs_, &all_dependent_configs_); |
| 190 MergeDirectDependentConfigsFrom(dep, &configs_); | 227 MergeDirectDependentConfigsFrom(dep, &configs_); |
| 191 | 228 |
| 192 // Direct dependent libraries. | 229 // Direct dependent libraries. |
| 193 if (dep->output_type() == STATIC_LIBRARY || | 230 if (dep->output_type() == STATIC_LIBRARY || |
| 194 dep->output_type() == SHARED_LIBRARY || | 231 dep->output_type() == SHARED_LIBRARY || |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile( | 335 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile( |
| 299 this, tool, tool->link_output()); | 336 this, tool, tool->link_output()); |
| 300 } | 337 } |
| 301 } | 338 } |
| 302 break; | 339 break; |
| 303 case UNKNOWN: | 340 case UNKNOWN: |
| 304 default: | 341 default: |
| 305 NOTREACHED(); | 342 NOTREACHED(); |
| 306 } | 343 } |
| 307 } | 344 } |
| 345 |
| 346 bool Target::CheckVisibility(Err* err) const { |
| 347 // Only check visibility when the origin of the dependency is non-null. These |
| 348 // are dependencies added by the GN files. Internally added dependencies |
| 349 // (expanded groups) will have a null origin. We don't want to check |
| 350 // visibility for these, since the point of a group would often be to |
| 351 // forward visibility. |
| 352 for (size_t i = 0; i < deps_.size(); i++) { |
| 353 if (deps_[i].origin && |
| 354 !Visibility::CheckItemVisibility(this, deps_[i].ptr, err)) |
| 355 return false; |
| 356 } |
| 357 |
| 358 for (size_t i = 0; i < datadeps_.size(); i++) { |
| 359 if (deps_[i].origin && |
| 360 !Visibility::CheckItemVisibility(this, datadeps_[i].ptr, err)) |
| 361 return false; |
| 362 } |
| 363 |
| 364 return true; |
| 365 } |
| 366 |
| 367 bool Target::CheckTestonly(Err* err) const { |
| 368 // If there current target is marked testonly, it can include both testonly |
| 369 // and non-testonly targets, so there's nothing to check. |
| 370 if (testonly()) |
| 371 return true; |
| 372 |
| 373 // Verify no deps have "testonly" set. |
| 374 for (size_t i = 0; i < deps_.size(); i++) { |
| 375 if (deps_[i].ptr->testonly()) { |
| 376 *err = MakeTestOnlyError(this, deps_[i].ptr); |
| 377 return false; |
| 378 } |
| 379 } |
| 380 |
| 381 for (size_t i = 0; i < datadeps_.size(); i++) { |
| 382 if (datadeps_[i].ptr->testonly()) { |
| 383 *err = MakeTestOnlyError(this, datadeps_[i].ptr); |
| 384 return false; |
| 385 } |
| 386 } |
| 387 |
| 388 return true; |
| 389 } |
| OLD | NEW |