Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / tools / gn / target_generator.cc
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 "tools/gn/target_generator.h"
6
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"
23
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) {
32 }
33
34 TargetGenerator::~TargetGenerator() {
35 }
36
37 void TargetGenerator::Run() {
38   // All target types use these.
39   if (!FillDependentConfigs())
40     return;
41
42   if (!FillData())
43     return;
44
45   if (!FillDependencies())
46     return;
47
48   if (!FillTestonly())
49     return;
50
51   if (!Visibility::FillItemVisibility(target_, scope_, err_))
52     return;
53
54   // Do type-specific generation.
55   DoRun();
56 }
57
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;
70   }
71
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());
77
78   if (g_scheduler->verbose_logging())
79     g_scheduler->Log("Defining target", label.GetUserVisibleName(true));
80
81   scoped_ptr<Target> target(new Target(scope->settings(), label));
82   target->set_defined_from(function_call);
83
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.");
118   }
119
120   if (err->has_error())
121     return;
122
123   // Save this target for the file.
124   Scope::ItemVector* collector = scope->GetItemCollector();
125   if (!collector) {
126     *err = Err(function_call, "Can't define a target in this context.");
127     return;
128   }
129   collector->push_back(target.release());
130 }
131
132 const BuildSettings* TargetGenerator::GetBuildSettings() const {
133   return scope_->settings()->build_settings();
134 }
135
136 bool TargetGenerator::FillSources() {
137   const Value* value = scope_->GetValue(variables::kSources, true);
138   if (!value)
139     return true;
140
141   Target::FileList dest_sources;
142   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
143                                   scope_->GetSourceDir(), &dest_sources, err_))
144     return false;
145   target_->sources().swap(dest_sources);
146   return true;
147 }
148
149 bool TargetGenerator::FillPublic() {
150   const Value* value = scope_->GetValue(variables::kPublic, true);
151   if (!value)
152     return true;
153
154   // If the public headers are defined, don't default to public.
155   target_->set_all_headers_public(false);
156
157   Target::FileList dest_public;
158   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
159                                   scope_->GetSourceDir(), &dest_public, err_))
160     return false;
161   target_->public_headers().swap(dest_public);
162   return true;
163 }
164
165 bool TargetGenerator::FillInputs() {
166   const Value* value = scope_->GetValue(variables::kInputs, true);
167  if (!value) {
168     // Older versions used "source_prereqs". Allow use of this variable until
169     // all callers are updated.
170     // TODO(brettw) remove this eventually.
171     value = scope_->GetValue("source_prereqs", true);
172     if (!value)
173       return true;
174   }
175
176   Target::FileList dest_inputs;
177   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
178                                   scope_->GetSourceDir(), &dest_inputs, err_))
179     return false;
180   target_->inputs().swap(dest_inputs);
181   return true;
182 }
183
184 bool TargetGenerator::FillConfigs() {
185   return FillGenericConfigs(variables::kConfigs, &target_->configs());
186 }
187
188 bool TargetGenerator::FillDependentConfigs() {
189   if (!FillGenericConfigs(variables::kAllDependentConfigs,
190                           &target_->all_dependent_configs()))
191     return false;
192   if (!FillGenericConfigs(variables::kPublicConfigs,
193                           &target_->public_configs()))
194     return false;
195
196   // "public_configs" was previously named "direct_dependent_configs", fall
197   // back to that if public_configs was undefined.
198   if (!scope_->GetValue(variables::kPublicConfigs, false)) {
199     if (!FillGenericConfigs("direct_dependent_configs",
200                             &target_->public_configs()))
201       return false;
202   }
203   return true;
204 }
205
206 bool TargetGenerator::FillData() {
207   const Value* value = scope_->GetValue(variables::kData, true);
208   if (!value)
209     return true;
210
211   Target::FileList dest_data;
212   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
213                                   scope_->GetSourceDir(), &dest_data, err_))
214     return false;
215   target_->data().swap(dest_data);
216   return true;
217 }
218
219 bool TargetGenerator::FillDependencies() {
220   if (!FillGenericDeps(variables::kDeps, &target_->private_deps()))
221     return false;
222   if (!FillGenericDeps(variables::kPublicDeps, &target_->public_deps()))
223     return false;
224   if (!FillGenericDeps(variables::kDataDeps, &target_->data_deps()))
225     return false;
226
227   // "data_deps" was previously named "datadeps". For backwards-compat, read
228   // the old one if no "data_deps" were specified.
229   if (!scope_->GetValue(variables::kDataDeps, false)) {
230     if (!FillGenericDeps("datadeps", &target_->data_deps()))
231       return false;
232   }
233
234   // This is a list of dependent targets to have their configs fowarded, so
235   // it goes here rather than in FillConfigs.
236   if (!FillForwardDependentConfigs())
237     return false;
238   return true;
239 }
240
241 bool TargetGenerator::FillTestonly() {
242   const Value* value = scope_->GetValue(variables::kTestonly, true);
243   if (value) {
244     if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
245       return false;
246     target_->set_testonly(value->boolean_value());
247   }
248   return true;
249 }
250
251 bool TargetGenerator::FillOutputs(bool allow_substitutions) {
252   const Value* value = scope_->GetValue(variables::kOutputs, true);
253   if (!value)
254     return true;
255
256   SubstitutionList& outputs = target_->action_values().outputs();
257   if (!outputs.Parse(*value, err_))
258     return false;
259
260   if (!allow_substitutions) {
261     // Verify no substitutions were actually used.
262     if (!outputs.required_types().empty()) {
263       *err_ = Err(*value, "Source expansions not allowed here.",
264           "The outputs of this target used source {{expansions}} but this "
265           "targe type\ndoesn't support them. Just express the outputs "
266           "literally.");
267       return false;
268     }
269   }
270
271   // Check the substitutions used are valid for this purpose.
272   if (!EnsureValidSourcesSubstitutions(outputs.required_types(),
273                                        value->origin(), err_))
274     return false;
275
276   // Validate that outputs are in the output dir.
277   CHECK(outputs.list().size() == value->list_value().size());
278   for (size_t i = 0; i < outputs.list().size(); i++) {
279     if (!EnsureSubstitutionIsInOutputDir(outputs.list()[i],
280                                          value->list_value()[i]))
281       return false;
282   }
283   return true;
284 }
285
286 bool TargetGenerator::EnsureSubstitutionIsInOutputDir(
287     const SubstitutionPattern& pattern,
288     const Value& original_value) {
289   if (pattern.ranges().empty()) {
290     // Pattern is empty, error out (this prevents weirdness below).
291     *err_ = Err(original_value, "This has an empty value in it.");
292     return false;
293   }
294
295   if (pattern.ranges()[0].type == SUBSTITUTION_LITERAL) {
296     // If the first thing is a literal, it must start with the output dir.
297     if (!EnsureStringIsInOutputDir(
298             GetBuildSettings()->build_dir(),
299             pattern.ranges()[0].literal, original_value.origin(), err_))
300       return false;
301   } else {
302     // Otherwise, the first subrange must be a pattern that expands to
303     // something in the output directory.
304     if (!SubstitutionIsInOutputDir(pattern.ranges()[0].type)) {
305       *err_ = Err(original_value,
306           "File is not inside output directory.",
307           "The given file should be in the output directory. Normally you\n"
308           "would specify\n\"$target_out_dir/foo\" or "
309           "\"{{source_gen_dir}}/foo\".");
310       return false;
311     }
312   }
313
314   return true;
315 }
316
317 bool TargetGenerator::FillGenericConfigs(const char* var_name,
318                                          UniqueVector<LabelConfigPair>* dest) {
319   const Value* value = scope_->GetValue(var_name, true);
320   if (value) {
321     ExtractListOfUniqueLabels(*value, scope_->GetSourceDir(),
322                               ToolchainLabelForScope(scope_), dest, err_);
323   }
324   return !err_->has_error();
325 }
326
327 bool TargetGenerator::FillGenericDeps(const char* var_name,
328                                       LabelTargetVector* dest) {
329   const Value* value = scope_->GetValue(var_name, true);
330   if (value) {
331     ExtractListOfLabels(*value, scope_->GetSourceDir(),
332                         ToolchainLabelForScope(scope_), dest, err_);
333   }
334   return !err_->has_error();
335 }
336
337 bool TargetGenerator::FillForwardDependentConfigs() {
338   const Value* value = scope_->GetValue(
339       variables::kForwardDependentConfigsFrom, true);
340   if (value) {
341     ExtractListOfUniqueLabels(*value, scope_->GetSourceDir(),
342                               ToolchainLabelForScope(scope_),
343                               &target_->forward_dependent_configs(), err_);
344   }
345   return !err_->has_error();
346 }