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/functions.h" 6 7 #include <iostream> 8 9 #include "base/strings/string_util.h" 10 #include "tools/gn/config.h" 11 #include "tools/gn/config_values_generator.h" 12 #include "tools/gn/err.h" 13 #include "tools/gn/input_file.h" 14 #include "tools/gn/item_tree.h" 15 #include "tools/gn/parse_tree.h" 16 #include "tools/gn/scheduler.h" 17 #include "tools/gn/scope.h" 18 #include "tools/gn/settings.h" 19 #include "tools/gn/target_manager.h" 20 #include "tools/gn/token.h" 21 #include "tools/gn/value.h" 22 23 namespace { 24 25 void FillNeedsBlockError(const FunctionCallNode* function, Err* err) { 26 *err = Err(function->function(), "This function call requires a block.", 27 "The block's \"{\" must be on the same line as the function " 28 "call's \")\"."); 29 } 30 31 // This is called when a template is invoked. When we see a template 32 // declaration, that funciton is RunTemplate. 33 Value RunTemplateInvocation(Scope* scope, 34 const FunctionCallNode* invocation, 35 const std::vector<Value>& args, 36 BlockNode* block, 37 const FunctionCallNode* rule, 38 Err* err) { 39 if (!EnsureNotProcessingImport(invocation, scope, err)) 40 return Value(); 41 Scope block_scope(scope); 42 if (!FillTargetBlockScope(scope, invocation, 43 invocation->function().value().data(), 44 block, args, &block_scope, err)) 45 return Value(); 46 47 // Run the block for the rule invocation. 48 block->ExecuteBlockInScope(&block_scope, err); 49 if (err->has_error()) 50 return Value(); 51 52 // Now run the rule itself with that block as the current scope. 53 rule->block()->ExecuteBlockInScope(&block_scope, err); 54 if (err->has_error()) 55 return Value(); 56 57 return Value(); 58 } 59 60 } // namespace 61 62 // ---------------------------------------------------------------------------- 63 64 bool EnsureNotProcessingImport(const ParseNode* node, 65 const Scope* scope, 66 Err* err) { 67 if (scope->IsProcessingImport()) { 68 *err = Err(node, "Not valid from an import.", 69 "We need to talk about this thing you are doing here. Doing this\n" 70 "kind of thing from an imported file makes me feel like you are\n" 71 "abusing me. Imports are for defining defaults, variables, and rules.\n" 72 "The appropriate place for this kind of thing is really in a normal\n" 73 "BUILD file."); 74 return false; 75 } 76 return true; 77 } 78 79 bool EnsureNotProcessingBuildConfig(const ParseNode* node, 80 const Scope* scope, 81 Err* err) { 82 if (scope->IsProcessingBuildConfig()) { 83 *err = Err(node, "Not valid from the build config.", 84 "You can't do this kind of thing from the build config script, " 85 "silly!\nPut it in a regular BUILD file."); 86 return false; 87 } 88 return true; 89 } 90 91 bool FillTargetBlockScope(const Scope* scope, 92 const FunctionCallNode* function, 93 const char* target_type, 94 const BlockNode* block, 95 const std::vector<Value>& args, 96 Scope* block_scope, 97 Err* err) { 98 if (!block) { 99 FillNeedsBlockError(function, err); 100 return false; 101 } 102 103 // Copy the target defaults, if any, into the scope we're going to execute 104 // the block in. 105 const Scope* default_scope = scope->GetTargetDefaults(target_type); 106 if (default_scope) { 107 if (!default_scope->NonRecursiveMergeTo(block_scope, function, 108 "target defaults", err)) 109 return false; 110 } 111 112 // The name is the single argument to the target function. 113 if (!EnsureSingleStringArg(function, args, err)) 114 return false; 115 116 // Set the target name variable to the current target, and mark it used 117 // because we don't want to issue an error if the script ignores it. 118 const base::StringPiece target_name("target_name"); 119 block_scope->SetValue(target_name, Value(function, args[0].string_value()), 120 function); 121 block_scope->MarkUsed(target_name); 122 return true; 123 } 124 125 bool EnsureSingleStringArg(const FunctionCallNode* function, 126 const std::vector<Value>& args, 127 Err* err) { 128 if (args.size() != 1) { 129 *err = Err(function->function(), "Incorrect arguments.", 130 "This function requires a single string argument."); 131 return false; 132 } 133 return args[0].VerifyTypeIs(Value::STRING, err); 134 } 135 136 const SourceDir& SourceDirForFunctionCall(const FunctionCallNode* function) { 137 return function->function().location().file()->dir(); 138 } 139 140 const Label& ToolchainLabelForScope(const Scope* scope) { 141 return scope->settings()->toolchain()->label(); 142 } 143 144 Label MakeLabelForScope(const Scope* scope, 145 const FunctionCallNode* function, 146 const std::string& name) { 147 const SourceDir& input_dir = SourceDirForFunctionCall(function); 148 const Label& toolchain_label = ToolchainLabelForScope(scope); 149 return Label(input_dir, name, toolchain_label.dir(), toolchain_label.name()); 150 } 151 152 namespace functions { 153 154 // assert ---------------------------------------------------------------------- 155 156 const char kAssert[] = "assert"; 157 const char kAssert_Help[] = 158 "TODO(brettw) WRITE ME"; 159 160 Value RunAssert(Scope* scope, 161 const FunctionCallNode* function, 162 const std::vector<Value>& args, 163 Err* err) { 164 if (args.size() != 1) { 165 *err = Err(function->function(), "Wrong number of arguments.", 166 "assert() takes one argument, " 167 "were you expecting somethig else?"); 168 } else if (args[0].InterpretAsInt() == 0) { 169 *err = Err(function->function(), "Assertion failed."); 170 if (args[0].origin()) { 171 // If you do "assert(foo)" we'd ideally like to show you where foo was 172 // set, and in this case the origin of the args will tell us that. 173 // However, if you do "assert(foo && bar)" the source of the value will 174 // be the assert like, which isn't so helpful. 175 // 176 // So we try to see if the args are from the same line or not. This will 177 // break if you do "assert(\nfoo && bar)" and we may show the second line 178 // as the source, oh well. The way around this is to check to see if the 179 // origin node is inside our function call block. 180 Location origin_location = args[0].origin()->GetRange().begin(); 181 if (origin_location.file() != function->function().location().file() || 182 origin_location.line_number() != 183 function->function().location().line_number()) { 184 err->AppendSubErr(Err(args[0].origin()->GetRange(), "", 185 "This is where it was set.")); 186 } 187 } 188 } 189 return Value(); 190 } 191 192 // config ---------------------------------------------------------------------- 193 194 const char kConfig[] = "config"; 195 const char kConfig_Help[] = 196 "TODO(brettw) write this."; 197 198 Value RunConfig(const FunctionCallNode* function, 199 const std::vector<Value>& args, 200 Scope* scope, 201 Err* err) { 202 if (!EnsureSingleStringArg(function, args, err) || 203 !EnsureNotProcessingImport(function, scope, err)) 204 return Value(); 205 206 Label label(MakeLabelForScope(scope, function, args[0].string_value())); 207 208 if (g_scheduler->verbose_logging()) 209 g_scheduler->Log("Generating config", label.GetUserVisibleName(true)); 210 211 // Create the empty config object. 212 ItemTree* tree = &scope->settings()->build_settings()->item_tree(); 213 Config* config = Config::GetConfig(scope->settings(), function->GetRange(), 214 label, NULL, err); 215 if (err->has_error()) 216 return Value(); 217 218 // Fill it. 219 const SourceDir input_dir = SourceDirForFunctionCall(function); 220 ConfigValuesGenerator gen(&config->config_values(), scope, 221 function->function(), input_dir, err); 222 gen.Run(); 223 if (err->has_error()) 224 return Value(); 225 226 // Mark as complete. 227 { 228 base::AutoLock lock(tree->lock()); 229 tree->MarkItemDefinedLocked(scope->settings()->build_settings(), label, 230 err); 231 } 232 return Value(); 233 } 234 235 // declare_args ---------------------------------------------------------------- 236 237 const char kDeclareArgs[] = "declare_args"; 238 const char kDeclareArgs_Help[] = 239 "TODO(brettw) write this."; 240 241 Value RunDeclareArgs(const FunctionCallNode* function, 242 const std::vector<Value>& args, 243 Scope* scope, 244 Err* err) { 245 // Only allow this to be called once. We use a variable in the current scope 246 // with a name the parser will reject if the user tried to type it. 247 const char did_declare_args_var[] = "@@declared_args"; 248 if (scope->GetValue(did_declare_args_var)) { 249 *err = Err(function->function(), "Duplicate call to declared_args."); 250 err->AppendSubErr( 251 Err(scope->GetValue(did_declare_args_var)->origin()->GetRange(), 252 "See the original call.")); 253 return Value(); 254 } 255 256 // Find the root scope where the values will be set. 257 Scope* root = scope->mutable_containing(); 258 if (!root || root->containing() || !scope->IsProcessingBuildConfig()) { 259 *err = Err(function->function(), "declare_args called incorrectly." 260 "It must be called only from the build config script and in the " 261 "root scope."); 262 return Value(); 263 } 264 265 // Take all variables set in the current scope as default values and put 266 // them in the parent scope. The values in the current scope are the defaults, 267 // then we apply the external args to this list. 268 Scope::KeyValueVector values; 269 scope->GetCurrentScopeValues(&values); 270 for (size_t i = 0; i < values.size(); i++) { 271 // TODO(brettw) actually import the arguments from the command line rather 272 // than only using the defaults. 273 root->SetValue(values[i].first, values[i].second, 274 values[i].second.origin()); 275 } 276 277 scope->SetValue(did_declare_args_var, Value(function, 1), NULL); 278 return Value(); 279 } 280 281 // import ---------------------------------------------------------------------- 282 283 const char kImport[] = "import"; 284 const char kImport_Help[] = 285 "import: Import a file into the current scope.\n" 286 "\n" 287 " The import command loads the rules and variables resulting from\n" 288 " executing the given file into the current scope.\n" 289 "\n" 290 " By convention, imported files are named with a .gni extension.\n" 291 "\n" 292 " It does not do an \"include\". The imported file is executed in a\n" 293 " standalone environment from the caller of the import command. The\n" 294 " results of this execution are cached for other files that import the\n" 295 " same .gni file.\n" 296 "\n" 297 " Note that you can not import a BUILD.gn file that's otherwise used\n" 298 " in the build. Files must either be imported or implicitly loaded as\n" 299 " a result of deps rules, but not both.\n" 300 "\n" 301 " The imported file's scope will be merged with the scope at the point\n" 302 " import was called. If there is a conflict (both the current scope and\n" 303 " the imported file define some variable or rule with the same name)\n" 304 " a runtime error will be thrown. Therefore, it's good practice to\n" 305 " minimize the stuff that an imported file defines.\n" 306 "\n" 307 "Examples:\n" 308 "\n" 309 " import(\"//build/rules/idl_compilation_rule.gni\")\n" 310 "\n" 311 " # Looks in the current directory.\n" 312 " import(\"my_vars.gni\")\n"; 313 314 Value RunImport(Scope* scope, 315 const FunctionCallNode* function, 316 const std::vector<Value>& args, 317 Err* err) { 318 if (!EnsureSingleStringArg(function, args, err) || 319 !EnsureNotProcessingImport(function, scope, err)) 320 return Value(); 321 322 const SourceDir input_dir = SourceDirForFunctionCall(function); 323 SourceFile import_file = 324 input_dir.ResolveRelativeFile(args[0].string_value()); 325 scope->settings()->import_manager().DoImport(import_file, function, 326 scope, err); 327 return Value(); 328 } 329 330 // set_defaults ---------------------------------------------------------------- 331 332 const char kSetDefaults[] = "set_defaults"; 333 const char kSetDefaults_Help[] = 334 "TODO(brettw) write this."; 335 336 Value RunSetDefaults(Scope* scope, 337 const FunctionCallNode* function, 338 const std::vector<Value>& args, 339 BlockNode* block, 340 Err* err) { 341 if (!EnsureSingleStringArg(function, args, err)) 342 return Value(); 343 const std::string& target_type(args[0].string_value()); 344 345 // Ensure there aren't defaults already set. 346 if (scope->GetTargetDefaults(target_type)) { 347 *err = Err(function->function(), 348 "This target type defaults were already set."); 349 return Value(); 350 } 351 352 // Execute the block in a new scope that has a parent of the containing 353 // scope. 354 Scope block_scope(scope); 355 if (!FillTargetBlockScope(scope, function, 356 function->function().value().data(), 357 block, args, &block_scope, err)) 358 return Value(); 359 360 // Run the block for the rule invocation. 361 block->ExecuteBlockInScope(&block_scope, err); 362 if (err->has_error()) 363 return Value(); 364 365 // Now copy the values set on the scope we made into the free-floating one 366 // (with no containing scope) used to hold the target defaults. 367 Scope* dest = scope->MakeTargetDefaults(target_type); 368 block_scope.NonRecursiveMergeTo(dest, function, "<SHOULD NOT FAIL>", err); 369 return Value(); 370 } 371 372 // set_sources_assignment_filter ----------------------------------------------- 373 374 const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter"; 375 const char kSetSourcesAssignmentFilter_Help[] = 376 "TODO(brettw) write this."; 377 378 Value RunSetSourcesAssignmentFilter(Scope* scope, 379 const FunctionCallNode* function, 380 const std::vector<Value>& args, 381 Err* err) { 382 if (args.size() != 1) { 383 *err = Err(function, "set_sources_assignment_filter takes one argument."); 384 } else { 385 scoped_ptr<PatternList> f(new PatternList); 386 f->SetFromValue(args[0], err); 387 if (!err->has_error()) 388 scope->set_sources_assignment_filter(f.Pass()); 389 } 390 return Value(); 391 } 392 393 // print ----------------------------------------------------------------------- 394 395 const char kPrint[] = "print"; 396 const char kPrint_Help[] = 397 "print(...)\n" 398 " Prints all arguments to the console separated by spaces. A newline is\n" 399 " automatically appended to the end.\n" 400 "\n" 401 " This function is intended for debugging. Note that build files are run\n" 402 " in parallel so you may get interleaved prints. A buildfile may also\n" 403 " be executed more than once in parallel in the context of different\n" 404 " toolchains so the prints from one file may be duplicated or\n" 405 " interleaved with itself.\n" 406 "\n" 407 "Examples:\n" 408 " print(\"Hello world\")\n" 409 "\n" 410 " print(sources, deps)\n"; 411 412 Value RunPrint(Scope* scope, 413 const FunctionCallNode* function, 414 const std::vector<Value>& args, 415 Err* err) { 416 for (size_t i = 0; i < args.size(); i++) { 417 if (i != 0) 418 std::cout << " "; 419 std::cout << args[i].ToString(); 420 } 421 std::cout << std::endl; 422 return Value(); 423 } 424 425 // ----------------------------------------------------------------------------- 426 427 FunctionInfo::FunctionInfo() 428 : generic_block_runner(NULL), 429 executed_block_runner(NULL), 430 no_block_runner(NULL), 431 help(NULL) { 432 } 433 434 FunctionInfo::FunctionInfo(GenericBlockFunction gbf, const char* in_help) 435 : generic_block_runner(gbf), 436 executed_block_runner(NULL), 437 no_block_runner(NULL), 438 help(in_help) { 439 } 440 441 FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf, const char* in_help) 442 : generic_block_runner(NULL), 443 executed_block_runner(ebf), 444 no_block_runner(NULL), 445 help(in_help) { 446 } 447 448 FunctionInfo::FunctionInfo(NoBlockFunction nbf, const char* in_help) 449 : generic_block_runner(NULL), 450 executed_block_runner(NULL), 451 no_block_runner(nbf), 452 help(in_help) { 453 } 454 455 // Setup the function map via a static initializer. We use this because it 456 // avoids race conditions without having to do some global setup function or 457 // locking-heavy singleton checks at runtime. In practice, we always need this 458 // before we can do anything interesting, so it's OK to wait for the 459 // initializer. 460 struct FunctionInfoInitializer { 461 FunctionInfoMap map; 462 463 FunctionInfoInitializer() { 464 #define INSERT_FUNCTION(command) \ 465 map[k##command] = FunctionInfo(&Run##command, k##command##_Help); 466 467 INSERT_FUNCTION(Assert) 468 INSERT_FUNCTION(Component) 469 INSERT_FUNCTION(Config) 470 INSERT_FUNCTION(Copy) 471 INSERT_FUNCTION(Custom) 472 INSERT_FUNCTION(DeclareArgs) 473 INSERT_FUNCTION(ExecScript) 474 INSERT_FUNCTION(Executable) 475 INSERT_FUNCTION(Group) 476 INSERT_FUNCTION(Import) 477 INSERT_FUNCTION(Print) 478 INSERT_FUNCTION(ProcessFileTemplate) 479 INSERT_FUNCTION(ReadFile) 480 INSERT_FUNCTION(SetDefaults) 481 INSERT_FUNCTION(SetDefaultToolchain) 482 INSERT_FUNCTION(SetSourcesAssignmentFilter) 483 INSERT_FUNCTION(SharedLibrary) 484 INSERT_FUNCTION(StaticLibrary) 485 INSERT_FUNCTION(Template) 486 INSERT_FUNCTION(Test) 487 INSERT_FUNCTION(Tool) 488 INSERT_FUNCTION(Toolchain) 489 INSERT_FUNCTION(WriteFile) 490 491 #undef INSERT_FUNCTION 492 } 493 }; 494 const FunctionInfoInitializer function_info; 495 496 const FunctionInfoMap& GetFunctions() { 497 return function_info.map; 498 } 499 500 Value RunFunction(Scope* scope, 501 const FunctionCallNode* function, 502 const std::vector<Value>& args, 503 BlockNode* block, 504 Err* err) { 505 const Token& name = function->function(); 506 507 const FunctionInfoMap& function_map = GetFunctions(); 508 FunctionInfoMap::const_iterator found_function = 509 function_map.find(name.value()); 510 if (found_function == function_map.end()) { 511 // No build-in function matching this, check for a template. 512 const FunctionCallNode* rule = 513 scope->GetTemplate(function->function().value().as_string()); 514 if (rule) 515 return RunTemplateInvocation(scope, function, args, block, rule, err); 516 517 *err = Err(name, "Unknown function."); 518 return Value(); 519 } 520 521 if (found_function->second.generic_block_runner) { 522 if (!block) { 523 FillNeedsBlockError(function, err); 524 return Value(); 525 } 526 return found_function->second.generic_block_runner( 527 scope, function, args, block, err); 528 } 529 530 if (found_function->second.executed_block_runner) { 531 if (!block) { 532 FillNeedsBlockError(function, err); 533 return Value(); 534 } 535 536 Scope block_scope(scope); 537 block->ExecuteBlockInScope(&block_scope, err); 538 if (err->has_error()) 539 return Value(); 540 return found_function->second.executed_block_runner( 541 function, args, &block_scope, err); 542 } 543 544 // Otherwise it's a no-block function. 545 return found_function->second.no_block_runner(scope, function, args, err); 546 } 547 548 } // namespace functions 549