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 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 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 132 const BuildSettings* TargetGenerator::GetBuildSettings() const { 133 return scope_->settings()->build_settings(); 134 } 135 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 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 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 182 void TargetGenerator::FillConfigs() { 183 FillGenericConfigs(variables::kConfigs, &target_->configs()); 184 } 185 186 void TargetGenerator::FillDependentConfigs() { 187 FillGenericConfigs(variables::kAllDependentConfigs, 188 &target_->all_dependent_configs()); 189 FillGenericConfigs(variables::kDirectDependentConfigs, 190 &target_->direct_dependent_configs()); 191 } 192 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 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 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 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 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 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