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 24TargetGenerator::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 34TargetGenerator::~TargetGenerator() { 35} 36 37void 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 49void 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 109const BuildSettings* TargetGenerator::GetBuildSettings() const { 110 return scope_->settings()->build_settings(); 111} 112 113void 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 125void 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 137void TargetGenerator::FillConfigs() { 138 FillGenericConfigs(variables::kConfigs, &target_->configs()); 139} 140 141void TargetGenerator::FillDependentConfigs() { 142 FillGenericConfigs(variables::kAllDependentConfigs, 143 &target_->all_dependent_configs()); 144 FillGenericConfigs(variables::kDirectDependentConfigs, 145 &target_->direct_dependent_configs()); 146} 147 148void 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 160void 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 171void 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 182void 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 191void 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 200void 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 221void 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 230void 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 239void 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