Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Side by Side Diff: tools/gn/target.cc

Issue 524623005: Add testonly flag to GN (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/target.h ('k') | tools/gn/target_generator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « tools/gn/target.h ('k') | tools/gn/target_generator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698