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/binary_target_generator.h"
6
7#include "tools/gn/config_values_generator.h"
8#include "tools/gn/deps_iterator.h"
9#include "tools/gn/err.h"
10#include "tools/gn/functions.h"
11#include "tools/gn/scope.h"
12#include "tools/gn/value_extractors.h"
13#include "tools/gn/variables.h"
14
15BinaryTargetGenerator::BinaryTargetGenerator(
16    Target* target,
17    Scope* scope,
18    const FunctionCallNode* function_call,
19    Target::OutputType type,
20    Err* err)
21    : TargetGenerator(target, scope, function_call, err),
22      output_type_(type) {
23}
24
25BinaryTargetGenerator::~BinaryTargetGenerator() {
26}
27
28void BinaryTargetGenerator::DoRun() {
29  target_->set_output_type(output_type_);
30
31  if (!FillOutputName())
32    return;
33
34  if (!FillOutputExtension())
35    return;
36
37  if (!FillSources())
38    return;
39
40  if (!FillPublic())
41    return;
42
43  if (!FillCheckIncludes())
44    return;
45
46  if (!FillInputs())
47    return;
48
49  if (!FillConfigs())
50    return;
51
52  if (!FillAllowCircularIncludesFrom())
53    return;
54
55  if (!FillCompleteStaticLib())
56    return;
57
58  // Config values (compiler flags, etc.) set directly on this target.
59  ConfigValuesGenerator gen(&target_->config_values(), scope_,
60                            scope_->GetSourceDir(), err_);
61  gen.Run();
62  if (err_->has_error())
63    return;
64}
65
66bool BinaryTargetGenerator::FillCheckIncludes() {
67  const Value* value = scope_->GetValue(variables::kCheckIncludes, true);
68  if (!value)
69    return true;
70  if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
71    return false;
72  target_->set_check_includes(value->boolean_value());
73  return true;
74}
75
76bool BinaryTargetGenerator::FillCompleteStaticLib() {
77  if (target_->output_type() == Target::STATIC_LIBRARY) {
78    const Value* value = scope_->GetValue(variables::kCompleteStaticLib, true);
79    if (!value)
80      return true;
81    if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
82      return false;
83    target_->set_complete_static_lib(value->boolean_value());
84  }
85  return true;
86}
87
88bool BinaryTargetGenerator::FillOutputName() {
89  const Value* value = scope_->GetValue(variables::kOutputName, true);
90  if (!value)
91    return true;
92  if (!value->VerifyTypeIs(Value::STRING, err_))
93    return false;
94  target_->set_output_name(value->string_value());
95  return true;
96}
97
98bool BinaryTargetGenerator::FillOutputExtension() {
99  const Value* value = scope_->GetValue(variables::kOutputExtension, true);
100  if (!value)
101    return true;
102  if (!value->VerifyTypeIs(Value::STRING, err_))
103    return false;
104  target_->set_output_extension(value->string_value());
105  return true;
106}
107
108bool BinaryTargetGenerator::FillAllowCircularIncludesFrom() {
109  const Value* value = scope_->GetValue(
110      variables::kAllowCircularIncludesFrom, true);
111  if (!value)
112    return true;
113
114  UniqueVector<Label> circular;
115  ExtractListOfUniqueLabels(*value, scope_->GetSourceDir(),
116                            ToolchainLabelForScope(scope_), &circular, err_);
117  if (err_->has_error())
118    return false;
119
120  // Validate that all circular includes entries are in the deps.
121  for (size_t circular_i = 0; circular_i < circular.size(); circular_i++) {
122    bool found_dep = false;
123    for (DepsIterator iter(target_, DepsIterator::LINKED_ONLY);
124         !iter.done(); iter.Advance()) {
125      if (iter.label() == circular[circular_i]) {
126        found_dep = true;
127        break;
128      }
129    }
130    if (!found_dep) {
131      *err_ = Err(*value, "Label not in deps.",
132          "The label \"" + circular[circular_i].GetUserVisibleName(false) +
133          "\"\nwas not in the deps of this target. "
134          "allow_circular_includes_from only allows\ntargets present in the "
135          "deps.");
136      return false;
137    }
138  }
139
140  // Add to the set.
141  for (size_t i = 0; i < circular.size(); i++)
142    target_->allow_circular_includes_from().insert(circular[i]);
143  return true;
144}
145