Upstream version 10.39.225.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   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]);
38   }
39 }
40
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.");
50 }
51
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.");
63 }
64
65 }  // namespace
66
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) {
76 }
77
78 Target::~Target() {
79 }
80
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 "";
104   }
105 }
106
107 Target* Target::AsTarget() {
108   return this;
109 }
110
111 const Target* Target::AsTarget() const {
112   return this;
113 }
114
115 bool Target::OnResolved(Err* err) {
116   DCHECK(output_type_ != UNKNOWN);
117   DCHECK(toolchain_) << "Toolchain should have been set before resolving.";
118
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_);
122
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());
130   }
131
132   PullDependentTargetInfo();
133   PullForwardedDependentConfigs();
134   PullRecursiveHardDeps();
135
136   FillOutputFiles();
137
138   if (!CheckVisibility(err))
139     return false;
140   if (!CheckTestonly(err))
141     return false;
142   if (!CheckNoNestedStaticLibs(err))
143     return false;
144
145   return true;
146 }
147
148 bool Target::IsLinkable() const {
149   return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY;
150 }
151
152 bool Target::IsFinal() const {
153   return output_type_ == EXECUTABLE || output_type_ == SHARED_LIBRARY ||
154          (output_type_ == STATIC_LIBRARY && complete_static_lib_);
155 }
156
157 std::string Target::GetComputedOutputName(bool include_prefix) const {
158   DCHECK(toolchain_)
159       << "Toolchain must be specified before getting the computed output name.";
160
161   const std::string& name = output_name_.empty() ? label().name()
162                                                  : output_name_;
163
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;
171   }
172
173   result.append(name);
174   return result;
175 }
176
177 bool Target::SetToolchain(const Toolchain* toolchain, Err* err) {
178   DCHECK(!toolchain_);
179   DCHECK_NE(UNKNOWN, output_type_);
180   toolchain_ = toolchain;
181
182   const Tool* tool = toolchain->GetToolForTargetFinalOutput(this);
183   if (tool)
184     return true;
185
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()));
200   }
201   return false;
202 }
203
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_);
211
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);
217
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());
223
224       // Inherited library settings.
225       all_lib_dirs_.append(dep->all_lib_dirs());
226       all_libs_.append(dep->all_libs());
227     }
228   }
229 }
230
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);
235
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;
239
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());
249
250     PullForwardedDependentConfigsFrom(from_target);
251   }
252 }
253
254 void Target::PullForwardedDependentConfigsFrom(const Target* from) {
255   public_configs_.Append(from->public_configs().begin(),
256                          from->public_configs().end());
257 }
258
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());
264
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);
273   }
274 }
275
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;
291     }
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());
321         }
322         if (!tool->depend_output().empty()) {
323           dependency_output_file_ =
324               SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
325                   this, tool, tool->depend_output());
326         }
327       }
328       break;
329     case UNKNOWN:
330     default:
331       NOTREACHED();
332   }
333 }
334
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;
339   }
340   return true;
341 }
342
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;
348
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;
354     }
355   }
356
357   return true;
358 }
359
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;
365
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;
371     }
372   }
373
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;
379     }
380   }
381   return true;
382 }