Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / tools / gn / target.cc
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 "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"
15
16 namespace {
17
18 typedef std::set<const Config*> ConfigSet;
19
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());
25 }
26
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   for (const auto& pair : from_target->all_dependent_configs()) {
34     all_dest->push_back(pair);
35     dest->push_back(pair);
36   }
37 }
38
39 Err MakeTestOnlyError(const Target* from, const Target* to) {
40   return Err(from->defined_from(), "Test-only dependency not allowed.",
41       from->label().GetUserVisibleName(false) + "\n"
42       "which is NOT marked testonly can't depend on\n" +
43       to->label().GetUserVisibleName(false) + "\n"
44       "which is marked testonly. Only targets with \"testonly = true\"\n"
45       "can depend on other test-only targets.\n"
46       "\n"
47       "Either mark it test-only or don't do this dependency.");
48 }
49
50 Err MakeStaticLibDepsError(const Target* from, const Target* to) {
51   return Err(from->defined_from(),
52              "Complete static libraries can't depend on static libraries.",
53              from->label().GetUserVisibleName(false) +
54                  "\n"
55                  "which is a complete static library can't depend on\n" +
56                  to->label().GetUserVisibleName(false) +
57                  "\n"
58                  "which is a static library.\n"
59                  "\n"
60                  "Use source sets for intermediate targets instead.");
61 }
62
63 }  // namespace
64
65 Target::Target(const Settings* settings, const Label& label)
66     : Item(settings, label),
67       output_type_(UNKNOWN),
68       all_headers_public_(true),
69       check_includes_(true),
70       complete_static_lib_(false),
71       testonly_(false),
72       hard_dep_(false),
73       toolchain_(NULL) {
74 }
75
76 Target::~Target() {
77 }
78
79 // static
80 const char* Target::GetStringForOutputType(OutputType type) {
81   switch (type) {
82     case UNKNOWN:
83       return "Unknown";
84     case GROUP:
85       return "Group";
86     case EXECUTABLE:
87       return "Executable";
88     case SHARED_LIBRARY:
89       return "Shared library";
90     case STATIC_LIBRARY:
91       return "Static library";
92     case SOURCE_SET:
93       return "Source set";
94     case COPY_FILES:
95       return "Copy";
96     case ACTION:
97       return "Action";
98     case ACTION_FOREACH:
99       return "ActionForEach";
100     default:
101       return "";
102   }
103 }
104
105 Target* Target::AsTarget() {
106   return this;
107 }
108
109 const Target* Target::AsTarget() const {
110   return this;
111 }
112
113 bool Target::OnResolved(Err* err) {
114   DCHECK(output_type_ != UNKNOWN);
115   DCHECK(toolchain_) << "Toolchain should have been set before resolving.";
116
117   // Copy our own dependent configs to the list of configs applying to us.
118   configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end());
119   MergePublicConfigsFrom(this, &configs_);
120
121   // Copy our own libs and lib_dirs to the final set. This will be from our
122   // target and all of our configs. We do this specially since these must be
123   // inherited through the dependency tree (other flags don't work this way).
124   for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
125     const ConfigValues& cur = iter.cur();
126     all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end());
127     all_libs_.append(cur.libs().begin(), cur.libs().end());
128   }
129
130   PullDependentTargetInfo();
131   PullForwardedDependentConfigs();
132   PullRecursiveHardDeps();
133
134   FillOutputFiles();
135
136   if (!CheckVisibility(err))
137     return false;
138   if (!CheckTestonly(err))
139     return false;
140   if (!CheckNoNestedStaticLibs(err))
141     return false;
142
143   return true;
144 }
145
146 bool Target::IsLinkable() const {
147   return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY;
148 }
149
150 bool Target::IsFinal() const {
151   return output_type_ == EXECUTABLE || output_type_ == SHARED_LIBRARY ||
152          (output_type_ == STATIC_LIBRARY && complete_static_lib_);
153 }
154
155 DepsIteratorRange Target::GetDeps(DepsIterationType type) const {
156   if (type == DEPS_LINKED) {
157     return DepsIteratorRange(DepsIterator(
158         &public_deps_, &private_deps_, nullptr));
159   }
160   // All deps.
161   return DepsIteratorRange(DepsIterator(
162       &public_deps_, &private_deps_, &data_deps_));
163 }
164
165 std::string Target::GetComputedOutputName(bool include_prefix) const {
166   DCHECK(toolchain_)
167       << "Toolchain must be specified before getting the computed output name.";
168
169   const std::string& name = output_name_.empty() ? label().name()
170                                                  : output_name_;
171
172   std::string result;
173   if (include_prefix) {
174     const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
175     const std::string& prefix = tool->output_prefix();
176     // Only add the prefix if the name doesn't already have it.
177     if (!StartsWithASCII(name, prefix, true))
178       result = prefix;
179   }
180
181   result.append(name);
182   return result;
183 }
184
185 bool Target::SetToolchain(const Toolchain* toolchain, Err* err) {
186   DCHECK(!toolchain_);
187   DCHECK_NE(UNKNOWN, output_type_);
188   toolchain_ = toolchain;
189
190   const Tool* tool = toolchain->GetToolForTargetFinalOutput(this);
191   if (tool)
192     return true;
193
194   // Tool not specified for this target type.
195   if (err) {
196     *err = Err(defined_from(), "This target uses an undefined tool.",
197         base::StringPrintf(
198             "The target %s\n"
199             "of type \"%s\"\n"
200             "uses toolchain %s\n"
201             "which doesn't have the tool \"%s\" defined.\n\n"
202             "Alas, I can not continue.",
203             label().GetUserVisibleName(false).c_str(),
204             GetStringForOutputType(output_type_),
205             label().GetToolchainLabel().GetUserVisibleName(false).c_str(),
206             Toolchain::ToolTypeToName(
207                 toolchain->GetToolTypeForTargetFinalOutput(this)).c_str()));
208   }
209   return false;
210 }
211
212 void Target::PullDependentTargetInfo() {
213   // Gather info from our dependents we need.
214   for (const auto& pair : GetDeps(DEPS_LINKED)) {
215     const Target* dep = pair.ptr;
216     MergeAllDependentConfigsFrom(dep, &configs_, &all_dependent_configs_);
217     MergePublicConfigsFrom(dep, &configs_);
218
219     // Direct dependent libraries.
220     if (dep->output_type() == STATIC_LIBRARY ||
221         dep->output_type() == SHARED_LIBRARY ||
222         dep->output_type() == SOURCE_SET)
223       inherited_libraries_.push_back(dep);
224
225     // Inherited libraries and flags are inherited across static library
226     // boundaries.
227     if (!dep->IsFinal()) {
228       inherited_libraries_.Append(dep->inherited_libraries().begin(),
229                                   dep->inherited_libraries().end());
230
231       // Inherited library settings.
232       all_lib_dirs_.append(dep->all_lib_dirs());
233       all_libs_.append(dep->all_libs());
234     }
235   }
236 }
237
238 void Target::PullForwardedDependentConfigs() {
239   // Pull public configs from each of our dependency's public deps.
240   for (const auto& dep : public_deps_)
241     PullForwardedDependentConfigsFrom(dep.ptr);
242
243   // Forward public configs if explicitly requested.
244   for (const auto& dep : forward_dependent_configs_) {
245     const Target* from_target = dep.ptr;
246
247     // The forward_dependent_configs_ must be in the deps (public or private)
248     // already, so we don't need to bother copying to our configs, only
249     // forwarding.
250     DCHECK(std::find_if(private_deps_.begin(), private_deps_.end(),
251                         LabelPtrPtrEquals<Target>(from_target)) !=
252                private_deps_.end() ||
253            std::find_if(public_deps_.begin(), public_deps_.end(),
254                         LabelPtrPtrEquals<Target>(from_target)) !=
255                public_deps_.end());
256
257     PullForwardedDependentConfigsFrom(from_target);
258   }
259 }
260
261 void Target::PullForwardedDependentConfigsFrom(const Target* from) {
262   public_configs_.Append(from->public_configs().begin(),
263                          from->public_configs().end());
264 }
265
266 void Target::PullRecursiveHardDeps() {
267   for (const auto& pair : GetDeps(DEPS_LINKED)) {
268     if (pair.ptr->hard_dep())
269       recursive_hard_deps_.insert(pair.ptr);
270
271     // Android STL doesn't like insert(begin, end) so do it manually.
272     // TODO(brettw) this can be changed to
273     // insert(iter.target()->begin(), iter.target()->end())
274     // when Android uses a better STL.
275     for (std::set<const Target*>::const_iterator cur =
276              pair.ptr->recursive_hard_deps().begin();
277          cur != pair.ptr->recursive_hard_deps().end(); ++cur)
278       recursive_hard_deps_.insert(*cur);
279   }
280 }
281
282 void Target::FillOutputFiles() {
283   const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
284   switch (output_type_) {
285     case GROUP:
286     case SOURCE_SET:
287     case COPY_FILES:
288     case ACTION:
289     case ACTION_FOREACH: {
290       // These don't get linked to and use stamps which should be the first
291       // entry in the outputs. These stamps are named
292       // "<target_out_dir>/<targetname>.stamp".
293       dependency_output_file_ = GetTargetOutputDirAsOutputFile(this);
294       dependency_output_file_.value().append(GetComputedOutputName(true));
295       dependency_output_file_.value().append(".stamp");
296       break;
297     }
298     case EXECUTABLE:
299       // Executables don't get linked to, but the first output is used for
300       // dependency management.
301       CHECK_GE(tool->outputs().list().size(), 1u);
302       dependency_output_file_ =
303           SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
304               this, tool, tool->outputs().list()[0]);
305       break;
306     case STATIC_LIBRARY:
307       // Static libraries both have dependencies and linking going off of the
308       // first output.
309       CHECK(tool->outputs().list().size() >= 1);
310       link_output_file_ = dependency_output_file_ =
311           SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
312               this, tool, tool->outputs().list()[0]);
313       break;
314     case SHARED_LIBRARY:
315       CHECK(tool->outputs().list().size() >= 1);
316       if (tool->link_output().empty() && tool->depend_output().empty()) {
317         // Default behavior, use the first output file for both.
318         link_output_file_ = dependency_output_file_ =
319             SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
320                 this, tool, tool->outputs().list()[0]);
321       } else {
322         // Use the tool-specified ones.
323         if (!tool->link_output().empty()) {
324           link_output_file_ =
325               SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
326                   this, tool, tool->link_output());
327         }
328         if (!tool->depend_output().empty()) {
329           dependency_output_file_ =
330               SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
331                   this, tool, tool->depend_output());
332         }
333       }
334       break;
335     case UNKNOWN:
336     default:
337       NOTREACHED();
338   }
339 }
340
341 bool Target::CheckVisibility(Err* err) const {
342   for (const auto& pair : GetDeps(DEPS_ALL)) {
343     if (!Visibility::CheckItemVisibility(this, pair.ptr, err))
344       return false;
345   }
346   return true;
347 }
348
349 bool Target::CheckTestonly(Err* err) const {
350   // If the current target is marked testonly, it can include both testonly
351   // and non-testonly targets, so there's nothing to check.
352   if (testonly())
353     return true;
354
355   // Verify no deps have "testonly" set.
356   for (const auto& pair : GetDeps(DEPS_ALL)) {
357     if (pair.ptr->testonly()) {
358       *err = MakeTestOnlyError(this, pair.ptr);
359       return false;
360     }
361   }
362
363   return true;
364 }
365
366 bool Target::CheckNoNestedStaticLibs(Err* err) const {
367   // If the current target is not a complete static library, it can depend on
368   // static library targets with no problem.
369   if (!(output_type() == Target::STATIC_LIBRARY && complete_static_lib()))
370     return true;
371
372   // Verify no deps are static libraries.
373   for (const auto& pair : GetDeps(DEPS_ALL)) {
374     if (pair.ptr->output_type() == Target::STATIC_LIBRARY) {
375       *err = MakeStaticLibDepsError(this, pair.ptr);
376       return false;
377     }
378   }
379
380   // Verify no inherited libraries are static libraries.
381   for (const auto& lib : inherited_libraries()) {
382     if (lib->output_type() == Target::STATIC_LIBRARY) {
383       *err = MakeStaticLibDepsError(this, lib);
384       return false;
385     }
386   }
387   return true;
388 }