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/binary_target_generator.h"
8 #include "tools/gn/build_settings.h"
9 #include "tools/gn/config.h"
10 #include "tools/gn/copy_target_generator.h"
11 #include "tools/gn/err.h"
12 #include "tools/gn/filesystem_utils.h"
13 #include "tools/gn/functions.h"
14 #include "tools/gn/group_target_generator.h"
15 #include "tools/gn/parse_tree.h"
16 #include "tools/gn/scheduler.h"
17 #include "tools/gn/scope.h"
18 #include "tools/gn/script_target_generator.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();
44 // Do type-specific generation.
49 void TargetGenerator::GenerateTarget(Scope
* scope
,
50 const FunctionCallNode
* function_call
,
51 const std::vector
<Value
>& args
,
52 const std::string
& output_type
,
54 // Name is the argument to the function.
55 if (args
.size() != 1u || args
[0].type() != Value::STRING
) {
56 *err
= Err(function_call
,
57 "Target generator requires one string argument.",
58 "Otherwise I'm not sure what to call this target.");
62 // The location of the target is the directory name with no slash at the end.
63 // FIXME(brettw) validate name.
64 const Label
& toolchain_label
= ToolchainLabelForScope(scope
);
65 Label
label(scope
->GetSourceDir(), args
[0].string_value(),
66 toolchain_label
.dir(), toolchain_label
.name());
68 if (g_scheduler
->verbose_logging())
69 g_scheduler
->Log("Defining target", label
.GetUserVisibleName(true));
71 scoped_ptr
<Target
> target(new Target(scope
->settings(), label
));
72 target
->set_defined_from(function_call
);
74 // Create and call out to the proper generator.
75 if (output_type
== functions::kCopy
) {
76 CopyTargetGenerator
generator(target
.get(), scope
, function_call
, err
);
78 } else if (output_type
== functions::kCustom
) {
79 ScriptTargetGenerator
generator(target
.get(), scope
, function_call
, err
);
81 } else if (output_type
== functions::kExecutable
) {
82 BinaryTargetGenerator
generator(target
.get(), scope
, function_call
,
83 Target::EXECUTABLE
, err
);
85 } else if (output_type
== functions::kGroup
) {
86 GroupTargetGenerator
generator(target
.get(), scope
, function_call
, err
);
88 } else if (output_type
== functions::kSharedLibrary
) {
89 BinaryTargetGenerator
generator(target
.get(), scope
, function_call
,
90 Target::SHARED_LIBRARY
, err
);
92 } else if (output_type
== functions::kSourceSet
) {
93 BinaryTargetGenerator
generator(target
.get(), scope
, function_call
,
94 Target::SOURCE_SET
, err
);
96 } else if (output_type
== functions::kStaticLibrary
) {
97 BinaryTargetGenerator
generator(target
.get(), scope
, function_call
,
98 Target::STATIC_LIBRARY
, err
);
101 *err
= Err(function_call
, "Not a known output type",
102 "I am very confused.");
105 if (!err
->has_error())
106 scope
->settings()->build_settings()->ItemDefined(target
.PassAs
<Item
>());
109 const BuildSettings
* TargetGenerator::GetBuildSettings() const {
110 return scope_
->settings()->build_settings();
113 void TargetGenerator::FillSources() {
114 const Value
* value
= scope_
->GetValue(variables::kSources
, true);
118 Target::FileList dest_sources
;
119 if (!ExtractListOfRelativeFiles(scope_
->settings()->build_settings(), *value
,
120 scope_
->GetSourceDir(), &dest_sources
, err_
))
122 target_
->sources().swap(dest_sources
);
125 void TargetGenerator::FillSourcePrereqs() {
126 const Value
* value
= scope_
->GetValue(variables::kSourcePrereqs
, true);
130 Target::FileList dest_reqs
;
131 if (!ExtractListOfRelativeFiles(scope_
->settings()->build_settings(), *value
,
132 scope_
->GetSourceDir(), &dest_reqs
, err_
))
134 target_
->source_prereqs().swap(dest_reqs
);
137 void TargetGenerator::FillConfigs() {
138 FillGenericConfigs(variables::kConfigs
, &target_
->configs());
141 void TargetGenerator::FillDependentConfigs() {
142 FillGenericConfigs(variables::kAllDependentConfigs
,
143 &target_
->all_dependent_configs());
144 FillGenericConfigs(variables::kDirectDependentConfigs
,
145 &target_
->direct_dependent_configs());
148 void TargetGenerator::FillData() {
149 const Value
* value
= scope_
->GetValue(variables::kData
, true);
153 Target::FileList dest_data
;
154 if (!ExtractListOfRelativeFiles(scope_
->settings()->build_settings(), *value
,
155 scope_
->GetSourceDir(), &dest_data
, err_
))
157 target_
->data().swap(dest_data
);
160 void TargetGenerator::FillDependencies() {
161 FillGenericDeps(variables::kDeps
, &target_
->deps());
162 FillGenericDeps(variables::kDatadeps
, &target_
->datadeps());
164 // This is a list of dependent targets to have their configs fowarded, so
165 // it goes here rather than in FillConfigs.
166 FillForwardDependentConfigs();
171 void TargetGenerator::FillGypFile() {
172 const Value
* gyp_file_value
= scope_
->GetValue(variables::kGypFile
, true);
175 if (!gyp_file_value
->VerifyTypeIs(Value::STRING
, err_
))
178 target_
->set_gyp_file(scope_
->GetSourceDir().ResolveRelativeFile(
179 gyp_file_value
->string_value()));
182 void TargetGenerator::FillHardDep() {
183 const Value
* hard_dep_value
= scope_
->GetValue(variables::kHardDep
, true);
186 if (!hard_dep_value
->VerifyTypeIs(Value::BOOLEAN
, err_
))
188 target_
->set_hard_dep(hard_dep_value
->boolean_value());
191 void TargetGenerator::FillExternal() {
192 const Value
* value
= scope_
->GetValue(variables::kExternal
, true);
195 if (!value
->VerifyTypeIs(Value::BOOLEAN
, err_
))
197 target_
->set_external(value
->boolean_value());
200 void TargetGenerator::FillOutputs() {
201 const Value
* value
= scope_
->GetValue(variables::kOutputs
, true);
205 Target::FileList outputs
;
206 if (!ExtractListOfRelativeFiles(scope_
->settings()->build_settings(), *value
,
207 scope_
->GetSourceDir(), &outputs
, err_
))
210 // Validate that outputs are in the output dir.
211 CHECK(outputs
.size() == value
->list_value().size());
212 for (size_t i
= 0; i
< outputs
.size(); i
++) {
213 if (!EnsureStringIsInOutputDir(
214 GetBuildSettings()->build_dir(),
215 outputs
[i
].value(), value
->list_value()[i
], err_
))
218 target_
->script_values().outputs().swap(outputs
);
221 void TargetGenerator::FillGenericConfigs(const char* var_name
,
222 LabelConfigVector
* dest
) {
223 const Value
* value
= scope_
->GetValue(var_name
, true);
225 ExtractListOfLabels(*value
, scope_
->GetSourceDir(),
226 ToolchainLabelForScope(scope_
), dest
, err_
);
230 void TargetGenerator::FillGenericDeps(const char* var_name
,
231 LabelTargetVector
* dest
) {
232 const Value
* value
= scope_
->GetValue(var_name
, true);
234 ExtractListOfLabels(*value
, scope_
->GetSourceDir(),
235 ToolchainLabelForScope(scope_
), dest
, err_
);
239 void TargetGenerator::FillForwardDependentConfigs() {
240 const Value
* value
= scope_
->GetValue(
241 variables::kForwardDependentConfigsFrom
, true);
243 ExtractListOfLabels(*value
, scope_
->GetSourceDir(),
244 ToolchainLabelForScope(scope_
),
245 &target_
->forward_dependent_configs(), err_
);