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.
5 #include "tools/gn/target_generator.h"
7 #include "tools/gn/action_target_generator.h"
8 #include "tools/gn/binary_target_generator.h"
9 #include "tools/gn/build_settings.h"
10 #include "tools/gn/config.h"
11 #include "tools/gn/copy_target_generator.h"
12 #include "tools/gn/err.h"
13 #include "tools/gn/filesystem_utils.h"
14 #include "tools/gn/functions.h"
15 #include "tools/gn/group_target_generator.h"
16 #include "tools/gn/parse_tree.h"
17 #include "tools/gn/scheduler.h"
18 #include "tools/gn/scope.h"
19 #include "tools/gn/token.h"
20 #include "tools/gn/value.h"
21 #include "tools/gn/value_extractors.h"
22 #include "tools/gn/variables.h"
24 TargetGenerator::TargetGenerator(Target* target,
26 const FunctionCallNode* function_call,
30 function_call_(function_call),
34 TargetGenerator::~TargetGenerator() {
37 void TargetGenerator::Run() {
38 // All target types use these.
39 FillDependentConfigs();
40 if (err_->has_error())
44 if (err_->has_error())
48 if (err_->has_error())
51 if (!Visibility::FillItemVisibility(target_, scope_, err_))
54 // Do type-specific generation.
59 void TargetGenerator::GenerateTarget(Scope* scope,
60 const FunctionCallNode* function_call,
61 const std::vector<Value>& args,
62 const std::string& output_type,
64 // Name is the argument to the function.
65 if (args.size() != 1u || args[0].type() != Value::STRING) {
66 *err = Err(function_call,
67 "Target generator requires one string argument.",
68 "Otherwise I'm not sure what to call this target.");
72 // The location of the target is the directory name with no slash at the end.
73 // FIXME(brettw) validate name.
74 const Label& toolchain_label = ToolchainLabelForScope(scope);
75 Label label(scope->GetSourceDir(), args[0].string_value(),
76 toolchain_label.dir(), toolchain_label.name());
78 if (g_scheduler->verbose_logging())
79 g_scheduler->Log("Defining target", label.GetUserVisibleName(true));
81 scoped_ptr<Target> target(new Target(scope->settings(), label));
82 target->set_defined_from(function_call);
84 // Create and call out to the proper generator.
85 if (output_type == functions::kCopy) {
86 CopyTargetGenerator generator(target.get(), scope, function_call, err);
88 } else if (output_type == functions::kAction) {
89 ActionTargetGenerator generator(target.get(), scope, function_call,
92 } else if (output_type == functions::kActionForEach) {
93 ActionTargetGenerator generator(target.get(), scope, function_call,
94 Target::ACTION_FOREACH, err);
96 } else if (output_type == functions::kExecutable) {
97 BinaryTargetGenerator generator(target.get(), scope, function_call,
98 Target::EXECUTABLE, err);
100 } else if (output_type == functions::kGroup) {
101 GroupTargetGenerator generator(target.get(), scope, function_call, err);
103 } else if (output_type == functions::kSharedLibrary) {
104 BinaryTargetGenerator generator(target.get(), scope, function_call,
105 Target::SHARED_LIBRARY, err);
107 } else if (output_type == functions::kSourceSet) {
108 BinaryTargetGenerator generator(target.get(), scope, function_call,
109 Target::SOURCE_SET, err);
111 } else if (output_type == functions::kStaticLibrary) {
112 BinaryTargetGenerator generator(target.get(), scope, function_call,
113 Target::STATIC_LIBRARY, err);
116 *err = Err(function_call, "Not a known output type",
117 "I am very confused.");
120 if (err->has_error())
123 // Save this target for the file.
124 Scope::ItemVector* collector = scope->GetItemCollector();
126 *err = Err(function_call, "Can't define a target in this context.");
129 collector->push_back(new scoped_ptr<Item>(target.PassAs<Item>()));
132 const BuildSettings* TargetGenerator::GetBuildSettings() const {
133 return scope_->settings()->build_settings();
136 void TargetGenerator::FillSources() {
137 const Value* value = scope_->GetValue(variables::kSources, true);
141 Target::FileList dest_sources;
142 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
143 scope_->GetSourceDir(), &dest_sources, err_))
145 target_->sources().swap(dest_sources);
148 void TargetGenerator::FillPublic() {
149 const Value* value = scope_->GetValue(variables::kPublic, true);
153 // If the public headers are defined, don't default to public.
154 target_->set_all_headers_public(false);
156 Target::FileList dest_public;
157 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
158 scope_->GetSourceDir(), &dest_public, err_))
160 target_->public_headers().swap(dest_public);
163 void TargetGenerator::FillInputs() {
164 const Value* value = scope_->GetValue(variables::kInputs, true);
166 // Older versions used "source_prereqs". Allow use of this variable until
167 // all callers are updated.
168 // TODO(brettw) remove this eventually.
169 value = scope_->GetValue("source_prereqs", true);
175 Target::FileList dest_inputs;
176 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
177 scope_->GetSourceDir(), &dest_inputs, err_))
179 target_->inputs().swap(dest_inputs);
182 void TargetGenerator::FillConfigs() {
183 FillGenericConfigs(variables::kConfigs, &target_->configs());
186 void TargetGenerator::FillDependentConfigs() {
187 FillGenericConfigs(variables::kAllDependentConfigs,
188 &target_->all_dependent_configs());
189 FillGenericConfigs(variables::kDirectDependentConfigs,
190 &target_->direct_dependent_configs());
193 void TargetGenerator::FillData() {
194 const Value* value = scope_->GetValue(variables::kData, true);
198 Target::FileList dest_data;
199 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
200 scope_->GetSourceDir(), &dest_data, err_))
202 target_->data().swap(dest_data);
205 void TargetGenerator::FillDependencies() {
206 FillGenericDeps(variables::kDeps, &target_->deps());
207 if (err_->has_error())
209 FillGenericDeps(variables::kDatadeps, &target_->datadeps());
210 if (err_->has_error())
213 // This is a list of dependent targets to have their configs fowarded, so
214 // it goes here rather than in FillConfigs.
215 FillForwardDependentConfigs();
216 if (err_->has_error())
220 void TargetGenerator::FillOutputs(bool allow_substitutions) {
221 const Value* value = scope_->GetValue(variables::kOutputs, true);
225 SubstitutionList& outputs = target_->action_values().outputs();
226 if (!outputs.Parse(*value, err_))
229 if (!allow_substitutions) {
230 // Verify no substitutions were actually used.
231 if (!outputs.required_types().empty()) {
232 *err_ = Err(*value, "Source expansions not allowed here.",
233 "The outputs of this target used source {{expansions}} but this "
234 "targe type\ndoesn't support them. Just express the outputs "
240 // Check the substitutions used are valid for this purpose.
241 if (!EnsureValidSourcesSubstitutions(outputs.required_types(),
242 value->origin(), err_))
245 // Validate that outputs are in the output dir.
246 CHECK(outputs.list().size() == value->list_value().size());
247 for (size_t i = 0; i < outputs.list().size(); i++) {
248 if (!EnsureSubstitutionIsInOutputDir(outputs.list()[i],
249 value->list_value()[i]))
254 bool TargetGenerator::EnsureSubstitutionIsInOutputDir(
255 const SubstitutionPattern& pattern,
256 const Value& original_value) {
257 if (pattern.ranges().empty()) {
258 // Pattern is empty, error out (this prevents weirdness below).
259 *err_ = Err(original_value, "This has an empty value in it.");
263 if (pattern.ranges()[0].type == SUBSTITUTION_LITERAL) {
264 // If the first thing is a literal, it must start with the output dir.
265 if (!EnsureStringIsInOutputDir(
266 GetBuildSettings()->build_dir(),
267 pattern.ranges()[0].literal, original_value, err_))
270 // Otherwise, the first subrange must be a pattern that expands to
271 // something in the output directory.
272 if (!SubstitutionIsInOutputDir(pattern.ranges()[0].type)) {
273 *err_ = Err(original_value,
274 "File is not inside output directory.",
275 "The given file should be in the output directory. Normally you\n"
276 "would specify\n\"$target_out_dir/foo\" or "
277 "\"{{source_gen_dir}}/foo\".");
285 void TargetGenerator::FillGenericConfigs(const char* var_name,
286 UniqueVector<LabelConfigPair>* dest) {
287 const Value* value = scope_->GetValue(var_name, true);
289 ExtractListOfUniqueLabels(*value, scope_->GetSourceDir(),
290 ToolchainLabelForScope(scope_), dest, err_);
294 void TargetGenerator::FillGenericDeps(const char* var_name,
295 LabelTargetVector* dest) {
296 const Value* value = scope_->GetValue(var_name, true);
298 ExtractListOfLabels(*value, scope_->GetSourceDir(),
299 ToolchainLabelForScope(scope_), dest, err_);
303 void TargetGenerator::FillForwardDependentConfigs() {
304 const Value* value = scope_->GetValue(
305 variables::kForwardDependentConfigsFrom, true);
307 ExtractListOfUniqueLabels(*value, scope_->GetSourceDir(),
308 ToolchainLabelForScope(scope_),
309 &target_->forward_dependent_configs(), err_);