Release the Settings API.
[chromium-blink-merge.git] / tools / gn / target_generator.cc
blob570e1f89441b9f5f0939a32a750c9735f1e56079
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,
25 Scope* scope,
26 const FunctionCallNode* function_call,
27 Err* err)
28 : target_(target),
29 scope_(scope),
30 function_call_(function_call),
31 err_(err) {
34 TargetGenerator::~TargetGenerator() {
37 void TargetGenerator::Run() {
38 // All target types use these.
39 FillDependentConfigs();
40 if (err_->has_error())
41 return;
43 FillData();
44 if (err_->has_error())
45 return;
47 FillDependencies();
48 if (err_->has_error())
49 return;
51 if (!Visibility::FillItemVisibility(target_, scope_, err_))
52 return;
54 // Do type-specific generation.
55 DoRun();
58 // static
59 void TargetGenerator::GenerateTarget(Scope* scope,
60 const FunctionCallNode* function_call,
61 const std::vector<Value>& args,
62 const std::string& output_type,
63 Err* err) {
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.");
69 return;
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);
87 generator.Run();
88 } else if (output_type == functions::kAction) {
89 ActionTargetGenerator generator(target.get(), scope, function_call,
90 Target::ACTION, err);
91 generator.Run();
92 } else if (output_type == functions::kActionForEach) {
93 ActionTargetGenerator generator(target.get(), scope, function_call,
94 Target::ACTION_FOREACH, err);
95 generator.Run();
96 } else if (output_type == functions::kExecutable) {
97 BinaryTargetGenerator generator(target.get(), scope, function_call,
98 Target::EXECUTABLE, err);
99 generator.Run();
100 } else if (output_type == functions::kGroup) {
101 GroupTargetGenerator generator(target.get(), scope, function_call, err);
102 generator.Run();
103 } else if (output_type == functions::kSharedLibrary) {
104 BinaryTargetGenerator generator(target.get(), scope, function_call,
105 Target::SHARED_LIBRARY, err);
106 generator.Run();
107 } else if (output_type == functions::kSourceSet) {
108 BinaryTargetGenerator generator(target.get(), scope, function_call,
109 Target::SOURCE_SET, err);
110 generator.Run();
111 } else if (output_type == functions::kStaticLibrary) {
112 BinaryTargetGenerator generator(target.get(), scope, function_call,
113 Target::STATIC_LIBRARY, err);
114 generator.Run();
115 } else {
116 *err = Err(function_call, "Not a known output type",
117 "I am very confused.");
120 if (!err->has_error())
121 scope->settings()->build_settings()->ItemDefined(target.PassAs<Item>());
124 const BuildSettings* TargetGenerator::GetBuildSettings() const {
125 return scope_->settings()->build_settings();
128 void TargetGenerator::FillSources() {
129 const Value* value = scope_->GetValue(variables::kSources, true);
130 if (!value)
131 return;
133 Target::FileList dest_sources;
134 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
135 scope_->GetSourceDir(), &dest_sources, err_))
136 return;
137 target_->sources().swap(dest_sources);
140 void TargetGenerator::FillPublic() {
141 const Value* value = scope_->GetValue(variables::kPublic, true);
142 if (!value)
143 return;
145 // If the public headers are defined, don't default to public.
146 target_->set_all_headers_public(false);
148 Target::FileList dest_public;
149 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
150 scope_->GetSourceDir(), &dest_public, err_))
151 return;
152 target_->public_headers().swap(dest_public);
155 void TargetGenerator::FillSourcePrereqs() {
156 const Value* value = scope_->GetValue(variables::kSourcePrereqs, true);
157 if (!value)
158 return;
160 Target::FileList dest_reqs;
161 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
162 scope_->GetSourceDir(), &dest_reqs, err_))
163 return;
164 target_->source_prereqs().swap(dest_reqs);
167 void TargetGenerator::FillConfigs() {
168 FillGenericConfigs(variables::kConfigs, &target_->configs());
171 void TargetGenerator::FillDependentConfigs() {
172 FillGenericConfigs(variables::kAllDependentConfigs,
173 &target_->all_dependent_configs());
174 FillGenericConfigs(variables::kDirectDependentConfigs,
175 &target_->direct_dependent_configs());
178 void TargetGenerator::FillData() {
179 const Value* value = scope_->GetValue(variables::kData, true);
180 if (!value)
181 return;
183 Target::FileList dest_data;
184 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
185 scope_->GetSourceDir(), &dest_data, err_))
186 return;
187 target_->data().swap(dest_data);
190 void TargetGenerator::FillDependencies() {
191 FillGenericDeps(variables::kDeps, &target_->deps());
192 if (err_->has_error())
193 return;
194 FillGenericDeps(variables::kDatadeps, &target_->datadeps());
195 if (err_->has_error())
196 return;
198 // This is a list of dependent targets to have their configs fowarded, so
199 // it goes here rather than in FillConfigs.
200 FillForwardDependentConfigs();
201 if (err_->has_error())
202 return;
204 FillHardDep();
207 void TargetGenerator::FillHardDep() {
208 const Value* hard_dep_value = scope_->GetValue(variables::kHardDep, true);
209 if (!hard_dep_value)
210 return;
211 if (!hard_dep_value->VerifyTypeIs(Value::BOOLEAN, err_))
212 return;
213 target_->set_hard_dep(hard_dep_value->boolean_value());
216 void TargetGenerator::FillOutputs() {
217 const Value* value = scope_->GetValue(variables::kOutputs, true);
218 if (!value)
219 return;
221 Target::FileList outputs;
222 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
223 scope_->GetSourceDir(), &outputs, err_))
224 return;
226 // Validate that outputs are in the output dir.
227 CHECK(outputs.size() == value->list_value().size());
228 for (size_t i = 0; i < outputs.size(); i++) {
229 if (!EnsureStringIsInOutputDir(
230 GetBuildSettings()->build_dir(),
231 outputs[i].value(), value->list_value()[i], err_))
232 return;
234 target_->action_values().outputs().swap(outputs);
237 void TargetGenerator::FillGenericConfigs(const char* var_name,
238 LabelConfigVector* dest) {
239 const Value* value = scope_->GetValue(var_name, true);
240 if (value) {
241 ExtractListOfLabels(*value, scope_->GetSourceDir(),
242 ToolchainLabelForScope(scope_), dest, err_);
246 void TargetGenerator::FillGenericDeps(const char* var_name,
247 LabelTargetVector* dest) {
248 const Value* value = scope_->GetValue(var_name, true);
249 if (value) {
250 ExtractListOfLabels(*value, scope_->GetSourceDir(),
251 ToolchainLabelForScope(scope_), dest, err_);
255 void TargetGenerator::FillForwardDependentConfigs() {
256 const Value* value = scope_->GetValue(
257 variables::kForwardDependentConfigsFrom, true);
258 if (value) {
259 ExtractListOfLabels(*value, scope_->GetSourceDir(),
260 ToolchainLabelForScope(scope_),
261 &target_->forward_dependent_configs(), err_);