• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gn/binary_target_generator.h"
6 
7 #include "gn/config_values_generator.h"
8 #include "gn/deps_iterator.h"
9 #include "gn/err.h"
10 #include "gn/filesystem_utils.h"
11 #include "gn/functions.h"
12 #include "gn/parse_tree.h"
13 #include "gn/rust_values_generator.h"
14 #include "gn/rust_variables.h"
15 #include "gn/scope.h"
16 #include "gn/settings.h"
17 #include "gn/value_extractors.h"
18 #include "gn/variables.h"
19 
BinaryTargetGenerator(Target * target,Scope * scope,const FunctionCallNode * function_call,Target::OutputType type,Err * err)20 BinaryTargetGenerator::BinaryTargetGenerator(
21     Target* target,
22     Scope* scope,
23     const FunctionCallNode* function_call,
24     Target::OutputType type,
25     Err* err)
26     : TargetGenerator(target, scope, function_call, err), output_type_(type) {}
27 
28 BinaryTargetGenerator::~BinaryTargetGenerator() = default;
29 
DoRun()30 void BinaryTargetGenerator::DoRun() {
31   target_->set_output_type(output_type_);
32 
33   if (!FillOutputName())
34     return;
35 
36   if (!FillOutputPrefixOverride())
37     return;
38 
39   if (!FillOutputDir())
40     return;
41 
42   if (!FillOutputExtension())
43     return;
44 
45   if (!FillSources())
46     return;
47 
48   if (!FillPublic())
49     return;
50 
51   if (!FillFriends())
52     return;
53 
54   if (!FillCheckIncludes())
55     return;
56 
57   if (!FillConfigs())
58     return;
59 
60   if (!FillAllowCircularIncludesFrom())
61     return;
62 
63   if (!FillCompleteStaticLib())
64     return;
65 
66   if (!ValidateSources())
67     return;
68 
69   if (target_->source_types_used().RustSourceUsed()) {
70     RustTargetGenerator rustgen(target_, scope_, function_call_, err_);
71     rustgen.Run();
72     if (err_->has_error())
73       return;
74   }
75 
76   // Config values (compiler flags, etc.) set directly on this target.
77   ConfigValuesGenerator gen(&target_->config_values(), scope_,
78                             scope_->GetSourceDir(), err_);
79   gen.Run();
80   if (err_->has_error())
81     return;
82 }
83 
FillSources()84 bool BinaryTargetGenerator::FillSources() {
85   bool ret = TargetGenerator::FillSources();
86   for (std::size_t i = 0; i < target_->sources().size(); ++i) {
87     const auto& source = target_->sources()[i];
88     switch (source.type()) {
89       case SourceFile::SOURCE_CPP:
90       case SourceFile::SOURCE_H:
91       case SourceFile::SOURCE_C:
92       case SourceFile::SOURCE_M:
93       case SourceFile::SOURCE_MM:
94       case SourceFile::SOURCE_S:
95       case SourceFile::SOURCE_ASM:
96       case SourceFile::SOURCE_O:
97       case SourceFile::SOURCE_DEF:
98       case SourceFile::SOURCE_GO:
99       case SourceFile::SOURCE_RS:
100       case SourceFile::SOURCE_RC:
101         // These are allowed.
102         break;
103       case SourceFile::SOURCE_UNKNOWN:
104       case SourceFile::SOURCE_NUMTYPES:
105         *err_ =
106             Err(scope_->GetValue(variables::kSources, true)->list_value()[i],
107                 std::string("Only source, header, and object files belong in "
108                             "the sources of a ") +
109                     Target::GetStringForOutputType(target_->output_type()) +
110                     ". " + source.value() + " is not one of the valid types.");
111     }
112 
113     target_->source_types_used().Set(source.type());
114   }
115   return ret;
116 }
117 
FillCompleteStaticLib()118 bool BinaryTargetGenerator::FillCompleteStaticLib() {
119   if (target_->output_type() == Target::STATIC_LIBRARY) {
120     const Value* value = scope_->GetValue(variables::kCompleteStaticLib, true);
121     if (!value)
122       return true;
123     if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
124       return false;
125     target_->set_complete_static_lib(value->boolean_value());
126   }
127   return true;
128 }
129 
FillFriends()130 bool BinaryTargetGenerator::FillFriends() {
131   const Value* value = scope_->GetValue(variables::kFriend, true);
132   if (value) {
133     return ExtractListOfLabelPatterns(scope_->settings()->build_settings(),
134                                       *value, scope_->GetSourceDir(),
135                                       &target_->friends(), err_);
136   }
137   return true;
138 }
139 
FillOutputName()140 bool BinaryTargetGenerator::FillOutputName() {
141   const Value* value = scope_->GetValue(variables::kOutputName, true);
142   if (!value)
143     return true;
144   if (!value->VerifyTypeIs(Value::STRING, err_))
145     return false;
146   target_->set_output_name(value->string_value());
147   return true;
148 }
149 
FillOutputPrefixOverride()150 bool BinaryTargetGenerator::FillOutputPrefixOverride() {
151   const Value* value = scope_->GetValue(variables::kOutputPrefixOverride, true);
152   if (!value)
153     return true;
154   if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
155     return false;
156   target_->set_output_prefix_override(value->boolean_value());
157   return true;
158 }
159 
FillOutputDir()160 bool BinaryTargetGenerator::FillOutputDir() {
161   const Value* value = scope_->GetValue(variables::kOutputDir, true);
162   if (!value)
163     return true;
164   if (!value->VerifyTypeIs(Value::STRING, err_))
165     return false;
166 
167   if (value->string_value().empty())
168     return true;  // Treat empty string as the default and do nothing.
169 
170   const BuildSettings* build_settings = scope_->settings()->build_settings();
171   SourceDir dir = scope_->GetSourceDir().ResolveRelativeDir(
172       *value, err_, build_settings->root_path_utf8());
173   if (err_->has_error())
174     return false;
175 
176   if (!EnsureStringIsInOutputDir(build_settings->build_dir(), dir.value(),
177                                  value->origin(), err_))
178     return false;
179   target_->set_output_dir(dir);
180   return true;
181 }
182 
FillAllowCircularIncludesFrom()183 bool BinaryTargetGenerator::FillAllowCircularIncludesFrom() {
184   const Value* value =
185       scope_->GetValue(variables::kAllowCircularIncludesFrom, true);
186   if (!value)
187     return true;
188 
189   UniqueVector<Label> circular;
190   ExtractListOfUniqueLabels(scope_->settings()->build_settings(), *value,
191                             scope_->GetSourceDir(),
192                             ToolchainLabelForScope(scope_), &circular, err_);
193   if (err_->has_error())
194     return false;
195 
196   // Validate that all circular includes entries are in the deps.
197   for (const auto& cur : circular) {
198     bool found_dep = false;
199     for (const auto& dep_pair : target_->GetDeps(Target::DEPS_LINKED)) {
200       if (dep_pair.label == cur) {
201         found_dep = true;
202         break;
203       }
204     }
205     if (!found_dep) {
206       *err_ = Err(*value, "Label not in deps.",
207                   "The label \"" + cur.GetUserVisibleName(false) +
208                       "\"\nwas not in the deps of this target. "
209                       "allow_circular_includes_from only allows\ntargets "
210                       "present in the "
211                       "deps.");
212       return false;
213     }
214   }
215 
216   // Add to the set.
217   for (const auto& cur : circular)
218     target_->allow_circular_includes_from().insert(cur);
219   return true;
220 }
221 
ValidateSources()222 bool BinaryTargetGenerator::ValidateSources() {
223   // For Rust targets, if the only source file is the root `sources` can be
224   // omitted/empty.
225   if (scope_->GetValue(variables::kRustCrateRoot, false)) {
226     target_->source_types_used().Set(SourceFile::SOURCE_RS);
227   }
228 
229   if (target_->source_types_used().MixedSourceUsed()) {
230     *err_ =
231         Err(function_call_, "More than one language used in target sources.",
232             "Mixed sources are not allowed, unless they are "
233             "compilation-compatible (e.g. Objective C and C++).");
234     return false;
235   }
236   return true;
237 }
238