OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "tools/gn/target_generator.h" | 5 #include "tools/gn/target_generator.h" |
6 | 6 |
7 #include "tools/gn/binary_target_generator.h" | 7 #include "tools/gn/binary_target_generator.h" |
8 #include "tools/gn/build_settings.h" | 8 #include "tools/gn/build_settings.h" |
9 #include "tools/gn/config.h" | 9 #include "tools/gn/config.h" |
10 #include "tools/gn/copy_target_generator.h" | 10 #include "tools/gn/copy_target_generator.h" |
11 #include "tools/gn/err.h" | 11 #include "tools/gn/err.h" |
12 #include "tools/gn/filesystem_utils.h" | 12 #include "tools/gn/filesystem_utils.h" |
13 #include "tools/gn/functions.h" | 13 #include "tools/gn/functions.h" |
14 #include "tools/gn/group_target_generator.h" | 14 #include "tools/gn/group_target_generator.h" |
15 #include "tools/gn/item_node.h" | |
16 #include "tools/gn/parse_tree.h" | 15 #include "tools/gn/parse_tree.h" |
17 #include "tools/gn/scheduler.h" | 16 #include "tools/gn/scheduler.h" |
18 #include "tools/gn/scope.h" | 17 #include "tools/gn/scope.h" |
19 #include "tools/gn/script_target_generator.h" | 18 #include "tools/gn/script_target_generator.h" |
20 #include "tools/gn/target_manager.h" | |
21 #include "tools/gn/token.h" | 19 #include "tools/gn/token.h" |
22 #include "tools/gn/value.h" | 20 #include "tools/gn/value.h" |
23 #include "tools/gn/value_extractors.h" | 21 #include "tools/gn/value_extractors.h" |
24 #include "tools/gn/variables.h" | 22 #include "tools/gn/variables.h" |
25 | 23 |
26 TargetGenerator::TargetGenerator(Target* target, | 24 TargetGenerator::TargetGenerator(Target* target, |
27 Scope* scope, | 25 Scope* scope, |
28 const Token& function_token, | 26 const FunctionCallNode* function_call, |
29 Err* err) | 27 Err* err) |
30 : target_(target), | 28 : target_(target), |
31 scope_(scope), | 29 scope_(scope), |
32 function_token_(function_token), | 30 function_call_(function_call), |
33 err_(err) { | 31 err_(err) { |
34 } | 32 } |
35 | 33 |
36 TargetGenerator::~TargetGenerator() { | 34 TargetGenerator::~TargetGenerator() { |
37 } | 35 } |
38 | 36 |
39 void TargetGenerator::Run() { | 37 void TargetGenerator::Run() { |
40 // All target types use these. | 38 // All target types use these. |
41 FillDependentConfigs(); | 39 FillDependentConfigs(); |
42 FillData(); | 40 FillData(); |
43 FillDependencies(); | 41 FillDependencies(); |
44 FillGypFile(); | 42 FillGypFile(); |
45 | 43 |
46 // To type-specific generation. | 44 // Do type-specific generation. |
47 DoRun(); | 45 DoRun(); |
48 | |
49 // Mark the target as complete. | |
50 if (!err_->has_error()) { | |
51 target_->SetGenerated(&function_token_); | |
52 GetBuildSettings()->target_manager().TargetGenerationComplete( | |
53 target_->label(), err_); | |
54 } | |
55 } | 46 } |
56 | 47 |
57 // static | 48 // static |
58 void TargetGenerator::GenerateTarget(Scope* scope, | 49 void TargetGenerator::GenerateTarget(Scope* scope, |
59 const Token& function_token, | 50 const FunctionCallNode* function_call, |
60 const std::vector<Value>& args, | 51 const std::vector<Value>& args, |
61 const std::string& output_type, | 52 const std::string& output_type, |
62 Err* err) { | 53 Err* err) { |
63 // Name is the argument to the function. | 54 // Name is the argument to the function. |
64 if (args.size() != 1u || args[0].type() != Value::STRING) { | 55 if (args.size() != 1u || args[0].type() != Value::STRING) { |
65 *err = Err(function_token, | 56 *err = Err(function_call, |
66 "Target generator requires one string argument.", | 57 "Target generator requires one string argument.", |
67 "Otherwise I'm not sure what to call this target."); | 58 "Otherwise I'm not sure what to call this target."); |
68 return; | 59 return; |
69 } | 60 } |
70 | 61 |
71 // The location of the target is the directory name with no slash at the end. | 62 // The location of the target is the directory name with no slash at the end. |
72 // FIXME(brettw) validate name. | 63 // FIXME(brettw) validate name. |
73 const Label& toolchain_label = ToolchainLabelForScope(scope); | 64 const Label& toolchain_label = ToolchainLabelForScope(scope); |
74 Label label(scope->GetSourceDir(), args[0].string_value(), | 65 Label label(scope->GetSourceDir(), args[0].string_value(), |
75 toolchain_label.dir(), toolchain_label.name()); | 66 toolchain_label.dir(), toolchain_label.name()); |
76 | 67 |
77 if (g_scheduler->verbose_logging()) | 68 if (g_scheduler->verbose_logging()) |
78 g_scheduler->Log("Generating target", label.GetUserVisibleName(true)); | 69 g_scheduler->Log("Defining target", label.GetUserVisibleName(true)); |
79 | 70 |
80 Target* target = | 71 scoped_ptr<Target> target(new Target(scope->settings(), label)); |
81 scope->settings()->build_settings()->target_manager().GetTarget( | 72 target->set_defined_from(function_call); |
82 label, function_token.range(), NULL, err); | |
83 if (err->has_error()) | |
84 return; | |
85 | 73 |
86 // Create and call out to the proper generator. | 74 // Create and call out to the proper generator. |
87 if (output_type == functions::kCopy) { | 75 if (output_type == functions::kCopy) { |
88 CopyTargetGenerator generator(target, scope, function_token, err); | 76 CopyTargetGenerator generator(target.get(), scope, function_call, err); |
89 generator.Run(); | 77 generator.Run(); |
90 } else if (output_type == functions::kCustom) { | 78 } else if (output_type == functions::kCustom) { |
91 ScriptTargetGenerator generator(target, scope, function_token, err); | 79 ScriptTargetGenerator generator(target.get(), scope, function_call, err); |
92 generator.Run(); | 80 generator.Run(); |
93 } else if (output_type == functions::kExecutable) { | 81 } else if (output_type == functions::kExecutable) { |
94 BinaryTargetGenerator generator(target, scope, function_token, | 82 BinaryTargetGenerator generator(target.get(), scope, function_call, |
95 Target::EXECUTABLE, err); | 83 Target::EXECUTABLE, err); |
96 generator.Run(); | 84 generator.Run(); |
97 } else if (output_type == functions::kGroup) { | 85 } else if (output_type == functions::kGroup) { |
98 GroupTargetGenerator generator(target, scope, function_token, err); | 86 GroupTargetGenerator generator(target.get(), scope, function_call, err); |
99 generator.Run(); | 87 generator.Run(); |
100 } else if (output_type == functions::kSharedLibrary) { | 88 } else if (output_type == functions::kSharedLibrary) { |
101 BinaryTargetGenerator generator(target, scope, function_token, | 89 BinaryTargetGenerator generator(target.get(), scope, function_call, |
102 Target::SHARED_LIBRARY, err); | 90 Target::SHARED_LIBRARY, err); |
103 generator.Run(); | 91 generator.Run(); |
104 } else if (output_type == functions::kSourceSet) { | 92 } else if (output_type == functions::kSourceSet) { |
105 BinaryTargetGenerator generator(target, scope, function_token, | 93 BinaryTargetGenerator generator(target.get(), scope, function_call, |
106 Target::SOURCE_SET, err); | 94 Target::SOURCE_SET, err); |
107 generator.Run(); | 95 generator.Run(); |
108 } else if (output_type == functions::kStaticLibrary) { | 96 } else if (output_type == functions::kStaticLibrary) { |
109 BinaryTargetGenerator generator(target, scope, function_token, | 97 BinaryTargetGenerator generator(target.get(), scope, function_call, |
110 Target::STATIC_LIBRARY, err); | 98 Target::STATIC_LIBRARY, err); |
111 generator.Run(); | 99 generator.Run(); |
112 } else { | 100 } else { |
113 *err = Err(function_token, "Not a known output type", | 101 *err = Err(function_call, "Not a known output type", |
114 "I am very confused."); | 102 "I am very confused."); |
115 } | 103 } |
| 104 |
| 105 if (!err->has_error()) |
| 106 scope->settings()->build_settings()->ItemDefined(target.PassAs<Item>()); |
116 } | 107 } |
117 | 108 |
118 const BuildSettings* TargetGenerator::GetBuildSettings() const { | 109 const BuildSettings* TargetGenerator::GetBuildSettings() const { |
119 return scope_->settings()->build_settings(); | 110 return scope_->settings()->build_settings(); |
120 } | 111 } |
121 | 112 |
122 void TargetGenerator::FillSources() { | 113 void TargetGenerator::FillSources() { |
123 const Value* value = scope_->GetValue(variables::kSources, true); | 114 const Value* value = scope_->GetValue(variables::kSources, true); |
124 if (!value) | 115 if (!value) |
125 return; | 116 return; |
(...skipping 22 matching lines...) Expand all Loading... |
148 } | 139 } |
149 | 140 |
150 void TargetGenerator::FillDependentConfigs() { | 141 void TargetGenerator::FillDependentConfigs() { |
151 FillGenericConfigs(variables::kAllDependentConfigs, | 142 FillGenericConfigs(variables::kAllDependentConfigs, |
152 &target_->all_dependent_configs()); | 143 &target_->all_dependent_configs()); |
153 FillGenericConfigs(variables::kDirectDependentConfigs, | 144 FillGenericConfigs(variables::kDirectDependentConfigs, |
154 &target_->direct_dependent_configs()); | 145 &target_->direct_dependent_configs()); |
155 } | 146 } |
156 | 147 |
157 void TargetGenerator::FillData() { | 148 void TargetGenerator::FillData() { |
158 // TODO(brettW) hook this up to the constant when we have cleaned up | |
159 // how data files are used. | |
160 const Value* value = scope_->GetValue(variables::kData, true); | 149 const Value* value = scope_->GetValue(variables::kData, true); |
161 if (!value) | 150 if (!value) |
162 return; | 151 return; |
163 | 152 |
164 Target::FileList dest_data; | 153 Target::FileList dest_data; |
165 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value, | 154 if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value, |
166 scope_->GetSourceDir(), &dest_data, err_)) | 155 scope_->GetSourceDir(), &dest_data, err_)) |
167 return; | 156 return; |
168 target_->data().swap(dest_data); | 157 target_->data().swap(dest_data); |
169 } | 158 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 CHECK(outputs.size() == value->list_value().size()); | 211 CHECK(outputs.size() == value->list_value().size()); |
223 for (size_t i = 0; i < outputs.size(); i++) { | 212 for (size_t i = 0; i < outputs.size(); i++) { |
224 if (!EnsureStringIsInOutputDir( | 213 if (!EnsureStringIsInOutputDir( |
225 GetBuildSettings()->build_dir(), | 214 GetBuildSettings()->build_dir(), |
226 outputs[i].value(), value->list_value()[i], err_)) | 215 outputs[i].value(), value->list_value()[i], err_)) |
227 return; | 216 return; |
228 } | 217 } |
229 target_->script_values().outputs().swap(outputs); | 218 target_->script_values().outputs().swap(outputs); |
230 } | 219 } |
231 | 220 |
232 void TargetGenerator::SetToolchainDependency() { | |
233 // TODO(brettw) currently we lock separately for each config, dep, and | |
234 // toolchain we add which is bad! Do this in one lock. | |
235 ItemTree* tree = &GetBuildSettings()->item_tree(); | |
236 base::AutoLock lock(tree->lock()); | |
237 ItemNode* tc_node = | |
238 tree->GetExistingNodeLocked(ToolchainLabelForScope(scope_)); | |
239 target_->item_node()->AddDependency( | |
240 GetBuildSettings(), function_token_.range(), tc_node, err_); | |
241 } | |
242 | |
243 void TargetGenerator::FillGenericConfigs(const char* var_name, | 221 void TargetGenerator::FillGenericConfigs(const char* var_name, |
244 LabelConfigVector* dest) { | 222 LabelConfigVector* dest) { |
245 const Value* value = scope_->GetValue(var_name, true); | 223 const Value* value = scope_->GetValue(var_name, true); |
246 if (!value) | 224 if (value) { |
247 return; | 225 ExtractListOfLabels(*value, scope_->GetSourceDir(), |
248 if (!ExtractListOfLabels(*value, scope_->GetSourceDir(), | 226 ToolchainLabelForScope(scope_), dest, err_); |
249 ToolchainLabelForScope(scope_), dest, err_)) | |
250 return; | |
251 | |
252 for (size_t i = 0; i < dest->size(); i++) { | |
253 LabelConfigPair& cur = (*dest)[i]; | |
254 cur.ptr = Config::GetConfig(scope_->settings(), | |
255 value->list_value()[i].origin()->GetRange(), | |
256 cur.label, target_, err_); | |
257 if (err_->has_error()) | |
258 return; | |
259 } | 227 } |
260 } | 228 } |
261 | 229 |
262 void TargetGenerator::FillGenericDeps(const char* var_name, | 230 void TargetGenerator::FillGenericDeps(const char* var_name, |
263 LabelTargetVector* dest) { | 231 LabelTargetVector* dest) { |
264 const Value* value = scope_->GetValue(var_name, true); | 232 const Value* value = scope_->GetValue(var_name, true); |
265 if (!value) | 233 if (value) { |
266 return; | 234 ExtractListOfLabels(*value, scope_->GetSourceDir(), |
267 if (!ExtractListOfLabels(*value, scope_->GetSourceDir(), | 235 ToolchainLabelForScope(scope_), dest, err_); |
268 ToolchainLabelForScope(scope_), dest, err_)) | |
269 return; | |
270 | |
271 for (size_t i = 0; i < dest->size(); i++) { | |
272 LabelTargetPair& cur = (*dest)[i]; | |
273 cur.ptr = GetBuildSettings()->target_manager().GetTarget( | |
274 cur.label, value->list_value()[i].origin()->GetRange(), target_, err_); | |
275 if (err_->has_error()) | |
276 return; | |
277 } | 236 } |
278 } | 237 } |
279 | 238 |
280 void TargetGenerator::FillForwardDependentConfigs() { | 239 void TargetGenerator::FillForwardDependentConfigs() { |
281 const Value* value = scope_->GetValue( | 240 const Value* value = scope_->GetValue( |
282 variables::kForwardDependentConfigsFrom, true); | 241 variables::kForwardDependentConfigsFrom, true); |
283 if (!value) | 242 if (value) { |
284 return; | 243 ExtractListOfLabels(*value, scope_->GetSourceDir(), |
285 | 244 ToolchainLabelForScope(scope_), |
286 LabelTargetVector& dest = target_->forward_dependent_configs(); | 245 &target_->forward_dependent_configs(), err_); |
287 if (!ExtractListOfLabels(*value, scope_->GetSourceDir(), | |
288 ToolchainLabelForScope(scope_), &dest, err_)) | |
289 return; | |
290 | |
291 // We currently assume that the list is very small and do a brute-force | |
292 // search in the deps for the labeled target. This could be optimized. | |
293 const LabelTargetVector& deps = target_->deps(); | |
294 std::vector<const Target*> forward_from_list; | |
295 for (size_t dest_index = 0; dest_index < dest.size(); dest_index++) { | |
296 LabelTargetPair& cur_dest = dest[dest_index]; | |
297 for (size_t dep_index = 0; dep_index < deps.size(); dep_index++) { | |
298 if (deps[dep_index].label == cur_dest.label) { | |
299 cur_dest.ptr = deps[dep_index].ptr; | |
300 break; | |
301 } | |
302 } | |
303 if (!cur_dest.ptr) { | |
304 *err_ = Err(cur_dest.origin, | |
305 "Can't forward from this target.", | |
306 "forward_dependent_configs_from must contain a list of labels that\n" | |
307 "must all appear in the deps of the same target."); | |
308 return; | |
309 } | |
310 } | 246 } |
311 } | 247 } |
312 | |
313 | |
314 | |
315 | |
316 | |
OLD | NEW |