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 if (!FillDependentConfigs())
45 if (!FillDependencies())
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 target type",
117 "I am very confused by the target type \"" + output_type
+ "\"");
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(target
.release());
132 const BuildSettings
* TargetGenerator::GetBuildSettings() const {
133 return scope_
->settings()->build_settings();
136 bool 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
);
149 bool TargetGenerator::FillPublic() {
150 const Value
* value
= scope_
->GetValue(variables::kPublic
, true);
154 // If the public headers are defined, don't default to public.
155 target_
->set_all_headers_public(false);
157 Target::FileList dest_public
;
158 if (!ExtractListOfRelativeFiles(scope_
->settings()->build_settings(), *value
,
159 scope_
->GetSourceDir(), &dest_public
, err_
))
161 target_
->public_headers().swap(dest_public
);
165 bool TargetGenerator::FillInputs() {
166 const Value
* value
= scope_
->GetValue(variables::kInputs
, true);
170 Target::FileList dest_inputs
;
171 if (!ExtractListOfRelativeFiles(scope_
->settings()->build_settings(), *value
,
172 scope_
->GetSourceDir(), &dest_inputs
, err_
))
174 target_
->inputs().swap(dest_inputs
);
178 bool TargetGenerator::FillConfigs() {
179 return FillGenericConfigs(variables::kConfigs
, &target_
->configs());
182 bool TargetGenerator::FillDependentConfigs() {
183 if (!FillGenericConfigs(variables::kAllDependentConfigs
,
184 &target_
->all_dependent_configs()))
186 if (!FillGenericConfigs(variables::kPublicConfigs
,
187 &target_
->public_configs()))
190 // "public_configs" was previously named "direct_dependent_configs", fall
191 // back to that if public_configs was undefined.
192 if (!scope_
->GetValue(variables::kPublicConfigs
, false)) {
193 if (!FillGenericConfigs("direct_dependent_configs",
194 &target_
->public_configs()))
200 bool TargetGenerator::FillData() {
201 const Value
* value
= scope_
->GetValue(variables::kData
, true);
204 if (!value
->VerifyTypeIs(Value::LIST
, err_
))
207 const std::vector
<Value
>& input_list
= value
->list_value();
208 std::vector
<std::string
>& output_list
= target_
->data();
209 output_list
.reserve(input_list
.size());
211 const SourceDir
& dir
= scope_
->GetSourceDir();
212 const std::string
& root_path
=
213 scope_
->settings()->build_settings()->root_path_utf8();
215 for (size_t i
= 0; i
< input_list
.size(); i
++) {
216 const Value
& input
= input_list
[i
];
217 if (!input
.VerifyTypeIs(Value::STRING
, err_
))
219 const std::string
& input_str
= input
.string_value();
221 // Treat each input as either a file or a directory, depending on the
223 if (!input_str
.empty() && input_str
[input_str
.size() - 1] == '/') {
224 // Resolve as directory.
226 dir
.ResolveRelativeDir(input
, input_str
, err_
, root_path
);
227 if (err_
->has_error())
229 output_list
.push_back(resolved
.value());
232 SourceFile resolved
= dir
.ResolveRelativeFile(input
, err_
, root_path
);
233 if (err_
->has_error())
235 output_list
.push_back(resolved
.value());
241 bool TargetGenerator::FillDependencies() {
242 if (!FillGenericDeps(variables::kDeps
, &target_
->private_deps()))
244 if (!FillGenericDeps(variables::kPublicDeps
, &target_
->public_deps()))
246 if (!FillGenericDeps(variables::kDataDeps
, &target_
->data_deps()))
249 // "data_deps" was previously named "datadeps". For backwards-compat, read
250 // the old one if no "data_deps" were specified.
251 if (!scope_
->GetValue(variables::kDataDeps
, false)) {
252 if (!FillGenericDeps("datadeps", &target_
->data_deps()))
256 // This is a list of dependent targets to have their configs fowarded, so
257 // it goes here rather than in FillConfigs.
258 if (!FillForwardDependentConfigs())
263 bool TargetGenerator::FillTestonly() {
264 const Value
* value
= scope_
->GetValue(variables::kTestonly
, true);
266 if (!value
->VerifyTypeIs(Value::BOOLEAN
, err_
))
268 target_
->set_testonly(value
->boolean_value());
273 bool TargetGenerator::FillOutputs(bool allow_substitutions
) {
274 const Value
* value
= scope_
->GetValue(variables::kOutputs
, true);
278 SubstitutionList
& outputs
= target_
->action_values().outputs();
279 if (!outputs
.Parse(*value
, err_
))
282 if (!allow_substitutions
) {
283 // Verify no substitutions were actually used.
284 if (!outputs
.required_types().empty()) {
285 *err_
= Err(*value
, "Source expansions not allowed here.",
286 "The outputs of this target used source {{expansions}} but this "
287 "targe type\ndoesn't support them. Just express the outputs "
293 // Check the substitutions used are valid for this purpose.
294 if (!EnsureValidSourcesSubstitutions(outputs
.required_types(),
295 value
->origin(), err_
))
298 // Validate that outputs are in the output dir.
299 CHECK(outputs
.list().size() == value
->list_value().size());
300 for (size_t i
= 0; i
< outputs
.list().size(); i
++) {
301 if (!EnsureSubstitutionIsInOutputDir(outputs
.list()[i
],
302 value
->list_value()[i
]))
308 bool TargetGenerator::FillCheckIncludes() {
309 const Value
* value
= scope_
->GetValue(variables::kCheckIncludes
, true);
312 if (!value
->VerifyTypeIs(Value::BOOLEAN
, err_
))
314 target_
->set_check_includes(value
->boolean_value());
318 bool TargetGenerator::EnsureSubstitutionIsInOutputDir(
319 const SubstitutionPattern
& pattern
,
320 const Value
& original_value
) {
321 if (pattern
.ranges().empty()) {
322 // Pattern is empty, error out (this prevents weirdness below).
323 *err_
= Err(original_value
, "This has an empty value in it.");
327 if (pattern
.ranges()[0].type
== SUBSTITUTION_LITERAL
) {
328 // If the first thing is a literal, it must start with the output dir.
329 if (!EnsureStringIsInOutputDir(
330 GetBuildSettings()->build_dir(),
331 pattern
.ranges()[0].literal
, original_value
.origin(), err_
))
334 // Otherwise, the first subrange must be a pattern that expands to
335 // something in the output directory.
336 if (!SubstitutionIsInOutputDir(pattern
.ranges()[0].type
)) {
337 *err_
= Err(original_value
,
338 "File is not inside output directory.",
339 "The given file should be in the output directory. Normally you\n"
340 "would specify\n\"$target_out_dir/foo\" or "
341 "\"{{source_gen_dir}}/foo\".");
349 bool TargetGenerator::FillGenericConfigs(const char* var_name
,
350 UniqueVector
<LabelConfigPair
>* dest
) {
351 const Value
* value
= scope_
->GetValue(var_name
, true);
353 ExtractListOfUniqueLabels(*value
, scope_
->GetSourceDir(),
354 ToolchainLabelForScope(scope_
), dest
, err_
);
356 return !err_
->has_error();
359 bool TargetGenerator::FillGenericDeps(const char* var_name
,
360 LabelTargetVector
* dest
) {
361 const Value
* value
= scope_
->GetValue(var_name
, true);
363 ExtractListOfLabels(*value
, scope_
->GetSourceDir(),
364 ToolchainLabelForScope(scope_
), dest
, err_
);
366 return !err_
->has_error();
369 bool TargetGenerator::FillForwardDependentConfigs() {
370 const Value
* value
= scope_
->GetValue(
371 variables::kForwardDependentConfigsFrom
, true);
373 ExtractListOfUniqueLabels(*value
, scope_
->GetSourceDir(),
374 ToolchainLabelForScope(scope_
),
375 &target_
->forward_dependent_configs(), err_
);
377 return !err_
->has_error();