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
16namespace {
17
18typedef std::set<const Config*> ConfigSet;
19
20// Merges the public configs from the given target to the given config list.
21void 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.
30void 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
41Err 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
52Err 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
67Target::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
78Target::~Target() {
79}
80
81// static
82const 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
107Target* Target::AsTarget() {
108  return this;
109}
110
111const Target* Target::AsTarget() const {
112  return this;
113}
114
115bool 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
148bool Target::IsLinkable() const {
149  return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY;
150}
151
152bool Target::IsFinal() const {
153  return output_type_ == EXECUTABLE || output_type_ == SHARED_LIBRARY ||
154         (output_type_ == STATIC_LIBRARY && complete_static_lib_);
155}
156
157std::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
177bool 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
204void 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
231void 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
254void Target::PullForwardedDependentConfigsFrom(const Target* from) {
255  public_configs_.Append(from->public_configs().begin(),
256                         from->public_configs().end());
257}
258
259void 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
276void 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
335bool 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
343bool 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
360bool 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}
383