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 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 FillData(); 41 FillDependencies(); 42 FillGypFile(); 43 44 // Do type-specific generation. 45 DoRun(); 46 } 47 48 // static 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 109 const BuildSettings* TargetGenerator::GetBuildSettings() const { 110 return scope_->settings()->build_settings(); 111 } 112 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 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 137 void TargetGenerator::FillConfigs() { 138 FillGenericConfigs(variables::kConfigs, &target_->configs()); 139 } 140 141 void TargetGenerator::FillDependentConfigs() { 142 FillGenericConfigs(variables::kAllDependentConfigs, 143 &target_->all_dependent_configs()); 144 FillGenericConfigs(variables::kDirectDependentConfigs, 145 &target_->direct_dependent_configs()); 146 } 147 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 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 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 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 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 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 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 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 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