• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TargetGenerator(Target * target,Scope * scope,const FunctionCallNode * function_call,Err * err)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 
~TargetGenerator()34 TargetGenerator::~TargetGenerator() {
35 }
36 
Run()37 void TargetGenerator::Run() {
38   // All target types use these.
39   FillDependentConfigs();
40   if (err_->has_error())
41     return;
42 
43   FillData();
44   if (err_->has_error())
45     return;
46 
47   FillDependencies();
48   if (err_->has_error())
49     return;
50 
51   if (!Visibility::FillItemVisibility(target_, scope_, err_))
52     return;
53 
54   // Do type-specific generation.
55   DoRun();
56 }
57 
58 // static
GenerateTarget(Scope * scope,const FunctionCallNode * function_call,const std::vector<Value> & args,const std::string & output_type,Err * err)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(new scoped_ptr<Item>(target.PassAs<Item>()));
130 }
131 
GetBuildSettings() const132 const BuildSettings* TargetGenerator::GetBuildSettings() const {
133   return scope_->settings()->build_settings();
134 }
135 
FillSources()136 void TargetGenerator::FillSources() {
137   const Value* value = scope_->GetValue(variables::kSources, true);
138   if (!value)
139     return;
140 
141   Target::FileList dest_sources;
142   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
143                                   scope_->GetSourceDir(), &dest_sources, err_))
144     return;
145   target_->sources().swap(dest_sources);
146 }
147 
FillPublic()148 void TargetGenerator::FillPublic() {
149   const Value* value = scope_->GetValue(variables::kPublic, true);
150   if (!value)
151     return;
152 
153   // If the public headers are defined, don't default to public.
154   target_->set_all_headers_public(false);
155 
156   Target::FileList dest_public;
157   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
158                                   scope_->GetSourceDir(), &dest_public, err_))
159     return;
160   target_->public_headers().swap(dest_public);
161 }
162 
FillInputs()163 void TargetGenerator::FillInputs() {
164   const Value* value = scope_->GetValue(variables::kInputs, true);
165   if (!value) {
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);
170 
171     if (!value)
172       return;
173   }
174 
175   Target::FileList dest_inputs;
176   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
177                                   scope_->GetSourceDir(), &dest_inputs, err_))
178     return;
179   target_->inputs().swap(dest_inputs);
180 }
181 
FillConfigs()182 void TargetGenerator::FillConfigs() {
183   FillGenericConfigs(variables::kConfigs, &target_->configs());
184 }
185 
FillDependentConfigs()186 void TargetGenerator::FillDependentConfigs() {
187   FillGenericConfigs(variables::kAllDependentConfigs,
188                      &target_->all_dependent_configs());
189   FillGenericConfigs(variables::kDirectDependentConfigs,
190                      &target_->direct_dependent_configs());
191 }
192 
FillData()193 void TargetGenerator::FillData() {
194   const Value* value = scope_->GetValue(variables::kData, true);
195   if (!value)
196     return;
197 
198   Target::FileList dest_data;
199   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
200                                   scope_->GetSourceDir(), &dest_data, err_))
201     return;
202   target_->data().swap(dest_data);
203 }
204 
FillDependencies()205 void TargetGenerator::FillDependencies() {
206   FillGenericDeps(variables::kDeps, &target_->deps());
207   if (err_->has_error())
208     return;
209   FillGenericDeps(variables::kDatadeps, &target_->datadeps());
210   if (err_->has_error())
211     return;
212 
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())
217     return;
218 }
219 
FillOutputs()220 void TargetGenerator::FillOutputs() {
221   const Value* value = scope_->GetValue(variables::kOutputs, true);
222   if (!value)
223     return;
224 
225   Target::FileList outputs;
226   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
227                                   scope_->GetSourceDir(), &outputs, err_))
228     return;
229 
230   // Validate that outputs are in the output dir.
231   CHECK(outputs.size() == value->list_value().size());
232   for (size_t i = 0; i < outputs.size(); i++) {
233     if (!EnsureStringIsInOutputDir(
234             GetBuildSettings()->build_dir(),
235             outputs[i].value(), value->list_value()[i], err_))
236       return;
237   }
238   target_->action_values().outputs().swap(outputs);
239 }
240 
FillGenericConfigs(const char * var_name,LabelConfigVector * dest)241 void TargetGenerator::FillGenericConfigs(const char* var_name,
242                                          LabelConfigVector* dest) {
243   const Value* value = scope_->GetValue(var_name, true);
244   if (value) {
245     ExtractListOfLabels(*value, scope_->GetSourceDir(),
246                         ToolchainLabelForScope(scope_), dest, err_);
247   }
248 }
249 
FillGenericDeps(const char * var_name,LabelTargetVector * dest)250 void TargetGenerator::FillGenericDeps(const char* var_name,
251                                       LabelTargetVector* dest) {
252   const Value* value = scope_->GetValue(var_name, true);
253   if (value) {
254     ExtractListOfLabels(*value, scope_->GetSourceDir(),
255                         ToolchainLabelForScope(scope_), dest, err_);
256   }
257 }
258 
FillForwardDependentConfigs()259 void TargetGenerator::FillForwardDependentConfigs() {
260   const Value* value = scope_->GetValue(
261       variables::kForwardDependentConfigsFrom, true);
262   if (value) {
263     ExtractListOfLabels(*value, scope_->GetSourceDir(),
264                         ToolchainLabelForScope(scope_),
265                         &target_->forward_dependent_configs(), err_);
266   }
267 }
268