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