• 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/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"
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   FillData();
41   FillDependencies();
42   FillGypFile();
43 
44   // Do type-specific generation.
45   DoRun();
46 }
47 
48 // static
GenerateTarget(Scope * scope,const FunctionCallNode * function_call,const std::vector<Value> & args,const std::string & output_type,Err * err)49 void TargetGenerator::GenerateTarget(Scope* scope,
50                                      const FunctionCallNode* function_call,
51                                      const std::vector<Value>& args,
52                                      const std::string& output_type,
53                                      Err* err) {
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.");
59     return;
60   }
61 
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());
67 
68   if (g_scheduler->verbose_logging())
69     g_scheduler->Log("Defining target", label.GetUserVisibleName(true));
70 
71   scoped_ptr<Target> target(new Target(scope->settings(), label));
72   target->set_defined_from(function_call);
73 
74   // Create and call out to the proper generator.
75   if (output_type == functions::kCopy) {
76     CopyTargetGenerator generator(target.get(), scope, function_call, err);
77     generator.Run();
78   } else if (output_type == functions::kCustom) {
79     ScriptTargetGenerator generator(target.get(), scope, function_call, err);
80     generator.Run();
81   } else if (output_type == functions::kExecutable) {
82     BinaryTargetGenerator generator(target.get(), scope, function_call,
83                                     Target::EXECUTABLE, err);
84     generator.Run();
85   } else if (output_type == functions::kGroup) {
86     GroupTargetGenerator generator(target.get(), scope, function_call, err);
87     generator.Run();
88   } else if (output_type == functions::kSharedLibrary) {
89     BinaryTargetGenerator generator(target.get(), scope, function_call,
90                                     Target::SHARED_LIBRARY, err);
91     generator.Run();
92   } else if (output_type == functions::kSourceSet) {
93     BinaryTargetGenerator generator(target.get(), scope, function_call,
94                                     Target::SOURCE_SET, err);
95     generator.Run();
96   } else if (output_type == functions::kStaticLibrary) {
97     BinaryTargetGenerator generator(target.get(), scope, function_call,
98                                     Target::STATIC_LIBRARY, err);
99     generator.Run();
100   } else {
101     *err = Err(function_call, "Not a known output type",
102                "I am very confused.");
103   }
104 
105   if (!err->has_error())
106     scope->settings()->build_settings()->ItemDefined(target.PassAs<Item>());
107 }
108 
GetBuildSettings() const109 const BuildSettings* TargetGenerator::GetBuildSettings() const {
110   return scope_->settings()->build_settings();
111 }
112 
FillSources()113 void TargetGenerator::FillSources() {
114   const Value* value = scope_->GetValue(variables::kSources, true);
115   if (!value)
116     return;
117 
118   Target::FileList dest_sources;
119   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
120                                   scope_->GetSourceDir(), &dest_sources, err_))
121     return;
122   target_->sources().swap(dest_sources);
123 }
124 
FillSourcePrereqs()125 void TargetGenerator::FillSourcePrereqs() {
126   const Value* value = scope_->GetValue(variables::kSourcePrereqs, true);
127   if (!value)
128     return;
129 
130   Target::FileList dest_reqs;
131   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
132                                   scope_->GetSourceDir(), &dest_reqs, err_))
133     return;
134   target_->source_prereqs().swap(dest_reqs);
135 }
136 
FillConfigs()137 void TargetGenerator::FillConfigs() {
138   FillGenericConfigs(variables::kConfigs, &target_->configs());
139 }
140 
FillDependentConfigs()141 void TargetGenerator::FillDependentConfigs() {
142   FillGenericConfigs(variables::kAllDependentConfigs,
143                      &target_->all_dependent_configs());
144   FillGenericConfigs(variables::kDirectDependentConfigs,
145                      &target_->direct_dependent_configs());
146 }
147 
FillData()148 void TargetGenerator::FillData() {
149   const Value* value = scope_->GetValue(variables::kData, true);
150   if (!value)
151     return;
152 
153   Target::FileList dest_data;
154   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
155                                   scope_->GetSourceDir(), &dest_data, err_))
156     return;
157   target_->data().swap(dest_data);
158 }
159 
FillDependencies()160 void TargetGenerator::FillDependencies() {
161   FillGenericDeps(variables::kDeps, &target_->deps());
162   FillGenericDeps(variables::kDatadeps, &target_->datadeps());
163 
164   // This is a list of dependent targets to have their configs fowarded, so
165   // it goes here rather than in FillConfigs.
166   FillForwardDependentConfigs();
167 
168   FillHardDep();
169 }
170 
FillGypFile()171 void TargetGenerator::FillGypFile() {
172   const Value* gyp_file_value = scope_->GetValue(variables::kGypFile, true);
173   if (!gyp_file_value)
174     return;
175   if (!gyp_file_value->VerifyTypeIs(Value::STRING, err_))
176     return;
177 
178   target_->set_gyp_file(scope_->GetSourceDir().ResolveRelativeFile(
179       gyp_file_value->string_value()));
180 }
181 
FillHardDep()182 void TargetGenerator::FillHardDep() {
183   const Value* hard_dep_value = scope_->GetValue(variables::kHardDep, true);
184   if (!hard_dep_value)
185     return;
186   if (!hard_dep_value->VerifyTypeIs(Value::BOOLEAN, err_))
187     return;
188   target_->set_hard_dep(hard_dep_value->boolean_value());
189 }
190 
FillExternal()191 void TargetGenerator::FillExternal() {
192   const Value* value = scope_->GetValue(variables::kExternal, true);
193   if (!value)
194     return;
195   if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
196     return;
197   target_->set_external(value->boolean_value());
198 }
199 
FillOutputs()200 void TargetGenerator::FillOutputs() {
201   const Value* value = scope_->GetValue(variables::kOutputs, true);
202   if (!value)
203     return;
204 
205   Target::FileList outputs;
206   if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
207                                   scope_->GetSourceDir(), &outputs, err_))
208     return;
209 
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_))
216       return;
217   }
218   target_->script_values().outputs().swap(outputs);
219 }
220 
FillGenericConfigs(const char * var_name,LabelConfigVector * dest)221 void TargetGenerator::FillGenericConfigs(const char* var_name,
222                                          LabelConfigVector* dest) {
223   const Value* value = scope_->GetValue(var_name, true);
224   if (value) {
225     ExtractListOfLabels(*value, scope_->GetSourceDir(),
226                         ToolchainLabelForScope(scope_), dest, err_);
227   }
228 }
229 
FillGenericDeps(const char * var_name,LabelTargetVector * dest)230 void TargetGenerator::FillGenericDeps(const char* var_name,
231                                       LabelTargetVector* dest) {
232   const Value* value = scope_->GetValue(var_name, true);
233   if (value) {
234     ExtractListOfLabels(*value, scope_->GetSourceDir(),
235                         ToolchainLabelForScope(scope_), dest, err_);
236   }
237 }
238 
FillForwardDependentConfigs()239 void TargetGenerator::FillForwardDependentConfigs() {
240   const Value* value = scope_->GetValue(
241       variables::kForwardDependentConfigsFrom, true);
242   if (value) {
243     ExtractListOfLabels(*value, scope_->GetSourceDir(),
244                         ToolchainLabelForScope(scope_),
245                         &target_->forward_dependent_configs(), err_);
246   }
247 }
248