Add ctrl+mousewheel plumbing to MimeHandlerView.
[chromium-blink-merge.git] / tools / gn / target.cc
blob9368749856f2bc7ed154e06244a6bc1181b8244c
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.
5 #include "tools/gn/target.h"
7 #include "base/bind.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "tools/gn/config_values_extractors.h"
11 #include "tools/gn/deps_iterator.h"
12 #include "tools/gn/filesystem_utils.h"
13 #include "tools/gn/scheduler.h"
14 #include "tools/gn/substitution_writer.h"
16 namespace {
18 typedef std::set<const Config*> ConfigSet;
20 // Merges the public configs from the given target to the given config list.
21 void MergePublicConfigsFrom(const Target* from_target,
22 UniqueVector<LabelConfigPair>* dest) {
23 const UniqueVector<LabelConfigPair>& pub = from_target->public_configs();
24 dest->Append(pub.begin(), pub.end());
27 // Like MergePublicConfigsFrom above except does the "all dependent" ones. This
28 // additionally adds all configs to the all_dependent_configs_ of the dest
29 // target given in *all_dest.
30 void MergeAllDependentConfigsFrom(const Target* from_target,
31 UniqueVector<LabelConfigPair>* dest,
32 UniqueVector<LabelConfigPair>* all_dest) {
33 const UniqueVector<LabelConfigPair>& all =
34 from_target->all_dependent_configs();
35 for (size_t i = 0; i < all.size(); i++) {
36 all_dest->push_back(all[i]);
37 dest->push_back(all[i]);
41 Err MakeTestOnlyError(const Target* from, const Target* to) {
42 return Err(from->defined_from(), "Test-only dependency not allowed.",
43 from->label().GetUserVisibleName(false) + "\n"
44 "which is NOT marked testonly can't depend on\n" +
45 to->label().GetUserVisibleName(false) + "\n"
46 "which is marked testonly. Only targets with \"testonly = true\"\n"
47 "can depend on other test-only targets.\n"
48 "\n"
49 "Either mark it test-only or don't do this dependency.");
52 Err MakeStaticLibDepsError(const Target* from, const Target* to) {
53 return Err(from->defined_from(),
54 "Complete static libraries can't depend on static libraries.",
55 from->label().GetUserVisibleName(false) +
56 "\n"
57 "which is a complete static library can't depend on\n" +
58 to->label().GetUserVisibleName(false) +
59 "\n"
60 "which is a static library.\n"
61 "\n"
62 "Use source sets for intermediate targets instead.");
65 } // namespace
67 Target::Target(const Settings* settings, const Label& label)
68 : Item(settings, label),
69 output_type_(UNKNOWN),
70 all_headers_public_(true),
71 check_includes_(true),
72 complete_static_lib_(false),
73 testonly_(false),
74 hard_dep_(false),
75 toolchain_(NULL) {
78 Target::~Target() {
81 // static
82 const char* Target::GetStringForOutputType(OutputType type) {
83 switch (type) {
84 case UNKNOWN:
85 return "Unknown";
86 case GROUP:
87 return "Group";
88 case EXECUTABLE:
89 return "Executable";
90 case SHARED_LIBRARY:
91 return "Shared library";
92 case STATIC_LIBRARY:
93 return "Static library";
94 case SOURCE_SET:
95 return "Source set";
96 case COPY_FILES:
97 return "Copy";
98 case ACTION:
99 return "Action";
100 case ACTION_FOREACH:
101 return "ActionForEach";
102 default:
103 return "";
107 Target* Target::AsTarget() {
108 return this;
111 const Target* Target::AsTarget() const {
112 return this;
115 bool Target::OnResolved(Err* err) {
116 DCHECK(output_type_ != UNKNOWN);
117 DCHECK(toolchain_) << "Toolchain should have been set before resolving.";
119 // Copy our own dependent configs to the list of configs applying to us.
120 configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end());
121 MergePublicConfigsFrom(this, &configs_);
123 // Copy our own libs and lib_dirs to the final set. This will be from our
124 // target and all of our configs. We do this specially since these must be
125 // inherited through the dependency tree (other flags don't work this way).
126 for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
127 const ConfigValues& cur = iter.cur();
128 all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end());
129 all_libs_.append(cur.libs().begin(), cur.libs().end());
132 PullDependentTargetInfo();
133 PullForwardedDependentConfigs();
134 PullRecursiveHardDeps();
136 FillOutputFiles();
138 if (!CheckVisibility(err))
139 return false;
140 if (!CheckTestonly(err))
141 return false;
142 if (!CheckNoNestedStaticLibs(err))
143 return false;
145 return true;
148 bool Target::IsLinkable() const {
149 return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY;
152 bool Target::IsFinal() const {
153 return output_type_ == EXECUTABLE || output_type_ == SHARED_LIBRARY ||
154 (output_type_ == STATIC_LIBRARY && complete_static_lib_);
157 std::string Target::GetComputedOutputName(bool include_prefix) const {
158 DCHECK(toolchain_)
159 << "Toolchain must be specified before getting the computed output name.";
161 const std::string& name = output_name_.empty() ? label().name()
162 : output_name_;
164 std::string result;
165 if (include_prefix) {
166 const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
167 const std::string& prefix = tool->output_prefix();
168 // Only add the prefix if the name doesn't already have it.
169 if (!StartsWithASCII(name, prefix, true))
170 result = prefix;
173 result.append(name);
174 return result;
177 bool Target::SetToolchain(const Toolchain* toolchain, Err* err) {
178 DCHECK(!toolchain_);
179 DCHECK_NE(UNKNOWN, output_type_);
180 toolchain_ = toolchain;
182 const Tool* tool = toolchain->GetToolForTargetFinalOutput(this);
183 if (tool)
184 return true;
186 // Tool not specified for this target type.
187 if (err) {
188 *err = Err(defined_from(), "This target uses an undefined tool.",
189 base::StringPrintf(
190 "The target %s\n"
191 "of type \"%s\"\n"
192 "uses toolchain %s\n"
193 "which doesn't have the tool \"%s\" defined.\n\n"
194 "Alas, I can not continue.",
195 label().GetUserVisibleName(false).c_str(),
196 GetStringForOutputType(output_type_),
197 label().GetToolchainLabel().GetUserVisibleName(false).c_str(),
198 Toolchain::ToolTypeToName(
199 toolchain->GetToolTypeForTargetFinalOutput(this)).c_str()));
201 return false;
204 void Target::PullDependentTargetInfo() {
205 // Gather info from our dependents we need.
206 for (DepsIterator iter(this, DepsIterator::LINKED_ONLY); !iter.done();
207 iter.Advance()) {
208 const Target* dep = iter.target();
209 MergeAllDependentConfigsFrom(dep, &configs_, &all_dependent_configs_);
210 MergePublicConfigsFrom(dep, &configs_);
212 // Direct dependent libraries.
213 if (dep->output_type() == STATIC_LIBRARY ||
214 dep->output_type() == SHARED_LIBRARY ||
215 dep->output_type() == SOURCE_SET)
216 inherited_libraries_.push_back(dep);
218 // Inherited libraries and flags are inherited across static library
219 // boundaries.
220 if (!dep->IsFinal()) {
221 inherited_libraries_.Append(dep->inherited_libraries().begin(),
222 dep->inherited_libraries().end());
224 // Inherited library settings.
225 all_lib_dirs_.append(dep->all_lib_dirs());
226 all_libs_.append(dep->all_libs());
231 void Target::PullForwardedDependentConfigs() {
232 // Pull public configs from each of our dependency's public deps.
233 for (size_t dep = 0; dep < public_deps_.size(); dep++)
234 PullForwardedDependentConfigsFrom(public_deps_[dep].ptr);
236 // Forward public configs if explicitly requested.
237 for (size_t dep = 0; dep < forward_dependent_configs_.size(); dep++) {
238 const Target* from_target = forward_dependent_configs_[dep].ptr;
240 // The forward_dependent_configs_ must be in the deps (public or private)
241 // already, so we don't need to bother copying to our configs, only
242 // forwarding.
243 DCHECK(std::find_if(private_deps_.begin(), private_deps_.end(),
244 LabelPtrPtrEquals<Target>(from_target)) !=
245 private_deps_.end() ||
246 std::find_if(public_deps_.begin(), public_deps_.end(),
247 LabelPtrPtrEquals<Target>(from_target)) !=
248 public_deps_.end());
250 PullForwardedDependentConfigsFrom(from_target);
254 void Target::PullForwardedDependentConfigsFrom(const Target* from) {
255 public_configs_.Append(from->public_configs().begin(),
256 from->public_configs().end());
259 void Target::PullRecursiveHardDeps() {
260 for (DepsIterator iter(this, DepsIterator::LINKED_ONLY); !iter.done();
261 iter.Advance()) {
262 if (iter.target()->hard_dep())
263 recursive_hard_deps_.insert(iter.target());
265 // Android STL doesn't like insert(begin, end) so do it manually.
266 // TODO(brettw) this can be changed to
267 // insert(iter.target()->begin(), iter.target()->end())
268 // when Android uses a better STL.
269 for (std::set<const Target*>::const_iterator cur =
270 iter.target()->recursive_hard_deps().begin();
271 cur != iter.target()->recursive_hard_deps().end(); ++cur)
272 recursive_hard_deps_.insert(*cur);
276 void Target::FillOutputFiles() {
277 const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
278 switch (output_type_) {
279 case GROUP:
280 case SOURCE_SET:
281 case COPY_FILES:
282 case ACTION:
283 case ACTION_FOREACH: {
284 // These don't get linked to and use stamps which should be the first
285 // entry in the outputs. These stamps are named
286 // "<target_out_dir>/<targetname>.stamp".
287 dependency_output_file_ = GetTargetOutputDirAsOutputFile(this);
288 dependency_output_file_.value().append(GetComputedOutputName(true));
289 dependency_output_file_.value().append(".stamp");
290 break;
292 case EXECUTABLE:
293 // Executables don't get linked to, but the first output is used for
294 // dependency management.
295 CHECK_GE(tool->outputs().list().size(), 1u);
296 dependency_output_file_ =
297 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
298 this, tool, tool->outputs().list()[0]);
299 break;
300 case STATIC_LIBRARY:
301 // Static libraries both have dependencies and linking going off of the
302 // first output.
303 CHECK(tool->outputs().list().size() >= 1);
304 link_output_file_ = dependency_output_file_ =
305 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
306 this, tool, tool->outputs().list()[0]);
307 break;
308 case SHARED_LIBRARY:
309 CHECK(tool->outputs().list().size() >= 1);
310 if (tool->link_output().empty() && tool->depend_output().empty()) {
311 // Default behavior, use the first output file for both.
312 link_output_file_ = dependency_output_file_ =
313 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
314 this, tool, tool->outputs().list()[0]);
315 } else {
316 // Use the tool-specified ones.
317 if (!tool->link_output().empty()) {
318 link_output_file_ =
319 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
320 this, tool, tool->link_output());
322 if (!tool->depend_output().empty()) {
323 dependency_output_file_ =
324 SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
325 this, tool, tool->depend_output());
328 break;
329 case UNKNOWN:
330 default:
331 NOTREACHED();
335 bool Target::CheckVisibility(Err* err) const {
336 for (DepsIterator iter(this); !iter.done(); iter.Advance()) {
337 if (!Visibility::CheckItemVisibility(this, iter.target(), err))
338 return false;
340 return true;
343 bool Target::CheckTestonly(Err* err) const {
344 // If the current target is marked testonly, it can include both testonly
345 // and non-testonly targets, so there's nothing to check.
346 if (testonly())
347 return true;
349 // Verify no deps have "testonly" set.
350 for (DepsIterator iter(this); !iter.done(); iter.Advance()) {
351 if (iter.target()->testonly()) {
352 *err = MakeTestOnlyError(this, iter.target());
353 return false;
357 return true;
360 bool Target::CheckNoNestedStaticLibs(Err* err) const {
361 // If the current target is not a complete static library, it can depend on
362 // static library targets with no problem.
363 if (!(output_type() == Target::STATIC_LIBRARY && complete_static_lib()))
364 return true;
366 // Verify no deps are static libraries.
367 for (DepsIterator iter(this); !iter.done(); iter.Advance()) {
368 if (iter.target()->output_type() == Target::STATIC_LIBRARY) {
369 *err = MakeStaticLibDepsError(this, iter.target());
370 return false;
374 // Verify no inherited libraries are static libraries.
375 for (size_t i = 0; i < inherited_libraries().size(); ++i) {
376 if (inherited_libraries()[i]->output_type() == Target::STATIC_LIBRARY) {
377 *err = MakeStaticLibDepsError(this, inherited_libraries()[i]);
378 return false;
381 return true;