functions.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// found in the LICENSE file. 4d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 5d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/functions.h" 6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include <iostream> 8d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/string_util.h" 10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/config.h" 11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/config_values_generator.h" 12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/err.h" 13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/input_file.h" 14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/item_tree.h" 15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/parse_tree.h" 16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h" 17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scope.h" 18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/settings.h" 19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/target_manager.h" 20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/token.h" 21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/value.h" 22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace { 24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// This is called when a template is invoked. When we see a template 26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// declaration, that funciton is RunTemplate. 27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunTemplateInvocation(Scope* scope, 28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const FunctionCallNode* invocation, 29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::vector<Value>& args, 30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) BlockNode* block, 31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const FunctionCallNode* rule, 32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!EnsureNotProcessingImport(invocation, scope, err)) 34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return Value(); 353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Scope block_scope(scope); 37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!FillTargetBlockScope(scope, invocation, 383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) invocation->function().value().as_string(), 39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) block, args, &block_scope, err)) 40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return Value(); 41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Run the block for the rule invocation. 43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) block->ExecuteBlockInScope(&block_scope, err); 44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (err->has_error()) 45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return Value(); 46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Now run the rule itself with that block as the current scope. 48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) rule->block()->ExecuteBlockInScope(&block_scope, err); 49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (err->has_error()) 50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return Value(); 51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return Value(); 53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} // namespace 56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// ---------------------------------------------------------------------------- 58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureNotProcessingImport(const ParseNode* node, 60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const Scope* scope, 61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (scope->IsProcessingImport()) { 63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *err = Err(node, "Not valid from an import.", 64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) "Imports are for defining defaults, variables, and rules. The\n" 65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) "appropriate place for this kind of thing is really in a normal\n" 66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "BUILD file."); 67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureNotProcessingBuildConfig(const ParseNode* node, 73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const Scope* scope, 74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (scope->IsProcessingBuildConfig()) { 76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *err = Err(node, "Not valid from the build config.", 77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "You can't do this kind of thing from the build config script, " 78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "silly!\nPut it in a regular BUILD file."); 79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool FillTargetBlockScope(const Scope* scope, 85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const FunctionCallNode* function, 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& target_type, 87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const BlockNode* block, 88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::vector<Value>& args, 89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Scope* block_scope, 90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!block) { 92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FillNeedsBlockError(function, err); 93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Copy the target defaults, if any, into the scope we're going to execute 97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // the block in. 98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const Scope* default_scope = scope->GetTargetDefaults(target_type); 99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (default_scope) { 100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!default_scope->NonRecursiveMergeTo(block_scope, function, 101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "target defaults", err)) 102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // The name is the single argument to the target function. 106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!EnsureSingleStringArg(function, args, err)) 107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Set the target name variable to the current target, and mark it used 110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // because we don't want to issue an error if the script ignores it. 111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const base::StringPiece target_name("target_name"); 112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) block_scope->SetValue(target_name, Value(function, args[0].string_value()), 113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) function); 114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) block_scope->MarkUsed(target_name); 115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void FillNeedsBlockError(const FunctionCallNode* function, Err* err) { 1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err = Err(function->function(), "This function call requires a block.", 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "The block's \"{\" must be on the same line as the function " 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "call's \")\"."); 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureSingleStringArg(const FunctionCallNode* function, 125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::vector<Value>& args, 126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (args.size() != 1) { 128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *err = Err(function->function(), "Incorrect arguments.", 129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "This function requires a single string argument."); 130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return args[0].VerifyTypeIs(Value::STRING, err); 133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const Label& ToolchainLabelForScope(const Scope* scope) { 136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return scope->settings()->toolchain()->label(); 137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Label MakeLabelForScope(const Scope* scope, 140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const FunctionCallNode* function, 141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::string& name) { 142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const Label& toolchain_label = ToolchainLabelForScope(scope); 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Label(scope->GetSourceDir(), name, toolchain_label.dir(), 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) toolchain_label.name()); 145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace functions { 148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// assert ---------------------------------------------------------------------- 150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kAssert[] = "assert"; 152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kAssert_Help[] = 1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "assert: Assert an expression is true at generation time.\n" 1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " assert(<condition> [, <error string>])\n" 1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " If the condition is false, the build will fail with an error. If the\n" 1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " optional second argument is provided, that string will be printed\n" 1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " with the error message.\n" 1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "Examples:\n" 1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " assert(is_win)\n" 1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " assert(defined(sources), \"Sources must be defined\")\n"; 164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunAssert(Scope* scope, 166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const FunctionCallNode* function, 167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::vector<Value>& args, 168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (args.size() != 1 && args.size() != 2) { 170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err = Err(function->function(), "Wrong number of arguments.", 1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "assert() takes one or two argument, " 172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "were you expecting somethig else?"); 1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (args[0].type() != Value::BOOLEAN) { 1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err = Err(function->function(), "Assertion value not a bool."); 1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (!args[0].boolean_value()) { 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (args.size() == 2) { 1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Optional string message. 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (args[1].type() != Value::STRING) { 1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err = Err(function->function(), "Assertion failed.", 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "<<<ERROR MESSAGE IS NOT A STRING>>>"); 1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err = Err(function->function(), "Assertion failed.", 1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) args[1].string_value()); 1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err = Err(function->function(), "Assertion failed."); 1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (args[0].origin()) { 190d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // If you do "assert(foo)" we'd ideally like to show you where foo was 191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // set, and in this case the origin of the args will tell us that. 192d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // However, if you do "assert(foo && bar)" the source of the value will 193d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // be the assert like, which isn't so helpful. 194d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // 195d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // So we try to see if the args are from the same line or not. This will 196d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // break if you do "assert(\nfoo && bar)" and we may show the second line 197d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // as the source, oh well. The way around this is to check to see if the 198d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // origin node is inside our function call block. 199d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Location origin_location = args[0].origin()->GetRange().begin(); 200d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (origin_location.file() != function->function().location().file() || 201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch origin_location.line_number() != 202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch function->function().location().line_number()) { 203d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch err->AppendSubErr(Err(args[0].origin()->GetRange(), "", 204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "This is where it was set.")); 205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// config ---------------------------------------------------------------------- 212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kConfig[] = "config"; 214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kConfig_Help[] = 215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "TODO(brettw) write this."; 216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunConfig(const FunctionCallNode* function, 218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::vector<Value>& args, 219a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Scope* scope, 220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!EnsureSingleStringArg(function, args, err) || 222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch !EnsureNotProcessingImport(function, scope, err)) 223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 225d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Label label(MakeLabelForScope(scope, function, args[0].string_value())); 226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (g_scheduler->verbose_logging()) 228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch g_scheduler->Log("Generating config", label.GetUserVisibleName(true)); 229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Create the empty config object. 231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ItemTree* tree = &scope->settings()->build_settings()->item_tree(); 232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Config* config = Config::GetConfig(scope->settings(), function->GetRange(), 233d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch label, NULL, err); 234d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (err->has_error()) 235d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 236d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 237d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Fill it. 2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const SourceDir& input_dir = scope->GetSourceDir(); 239d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ConfigValuesGenerator gen(&config->config_values(), scope, 240d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch function->function(), input_dir, err); 241d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch gen.Run(); 242d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (err->has_error()) 243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Mark as complete. 246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch { 247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch base::AutoLock lock(tree->lock()); 248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) tree->MarkItemDefinedLocked(scope->settings()->build_settings(), label, 249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) err); 250d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 251d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 253d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// declare_args ---------------------------------------------------------------- 255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kDeclareArgs[] = "declare_args"; 257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kDeclareArgs_Help[] = 2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "declare_args: Declare build arguments used by this file.\n" 2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " Introduces the given arguments into the current scope. If they are\n" 2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " not specified on the command line or in a toolchain's arguments,\n" 2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " the default values given in the declare_args block will be used.\n" 2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " However, these defaults will not override command-line values.\n" 2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " See also \"gn help buildargs\" for an overview.\n" 2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "Example:\n" 2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " declare_args() {\n" 2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " enable_teleporter = true\n" 2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " enable_doom_melon = false\n" 2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " }\n" 2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " If you want to override the (default disabled) Doom Melon:\n" 2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " gn --args=\"enable_doom_melon=true enable_teleporter=false\"\n" 2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " This also sets the teleporter, but it's already defaulted to on so\n" 2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " it will have no effect.\n"; 277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Value RunDeclareArgs(Scope* scope, 2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const FunctionCallNode* function, 280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::vector<Value>& args, 2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BlockNode* block, 282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Scope block_scope(scope); 2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) block->ExecuteBlockInScope(&block_scope, err); 2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (err->has_error()) 286d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 287d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Pass the values from our scope into the Args object for adding to the 2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // scope with the proper values (taking into account the defaults given in 2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // the block_scope, and arguments passed into the build). 2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Scope::KeyValueMap values; 2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) block_scope.GetCurrentScopeValues(&values); 2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scope->settings()->build_settings()->build_args().DeclareArgs( 2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) values, scope, err); 2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Value(); 2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// defined --------------------------------------------------------------------- 299d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kDefined[] = "defined"; 3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kDefined_Help[] = 3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "defined: Returns whether an identifier is defined.\n" 3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " Returns true if the given argument is defined. This is most useful in\n" 3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " templates to assert that the caller set things up properly.\n" 3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "Example:\n" 3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " template(\"mytemplate\") {\n" 3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " # To help users call this template properly...\n" 3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " assert(defined(sources), \"Sources must be defined\")\n" 3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "\n" 3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " # If we want to accept an optional \"values\" argument, we don't\n" 3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " # want to dereference something that may not be defined.\n" 3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " if (!defined(outputs)) {\n" 3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " outputs = []\n" 3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " }\n" 3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) " }\n"; 3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Value RunDefined(Scope* scope, 3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const FunctionCallNode* function, 3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const ListNode* args_list, 3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Err* err) { 3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::vector<const ParseNode*>& args_vector = args_list->contents(); 3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const IdentifierNode* identifier = NULL; 3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (args_vector.size() != 1 || 3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) !(identifier = args_vector[0]->AsIdentifier())) { 3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *err = Err(function, "Bad argument to defined().", 3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "defined() takes one argument which should be an identifier."); 3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Value(); 331d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 332d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (scope->GetValue(identifier->value().value())) 3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Value(function, true); 3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Value(function, false); 336d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 337d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 338a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// import ---------------------------------------------------------------------- 339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kImport[] = "import"; 341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kImport_Help[] = 342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "import: Import a file into the current scope.\n" 343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " The import command loads the rules and variables resulting from\n" 345a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " executing the given file into the current scope.\n" 346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " By convention, imported files are named with a .gni extension.\n" 348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " It does not do an \"include\". The imported file is executed in a\n" 350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " standalone environment from the caller of the import command. The\n" 351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " results of this execution are cached for other files that import the\n" 352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " same .gni file.\n" 353a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 354a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " Note that you can not import a BUILD.gn file that's otherwise used\n" 355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " in the build. Files must either be imported or implicitly loaded as\n" 356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " a result of deps rules, but not both.\n" 357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " The imported file's scope will be merged with the scope at the point\n" 359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " import was called. If there is a conflict (both the current scope and\n" 360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " the imported file define some variable or rule with the same name)\n" 361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " a runtime error will be thrown. Therefore, it's good practice to\n" 362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " minimize the stuff that an imported file defines.\n" 363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "Examples:\n" 365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " import(\"//build/rules/idl_compilation_rule.gni\")\n" 367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " # Looks in the current directory.\n" 369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " import(\"my_vars.gni\")\n"; 370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunImport(Scope* scope, 372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const FunctionCallNode* function, 373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::vector<Value>& args, 374a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 375d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!EnsureSingleStringArg(function, args, err) || 376d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch !EnsureNotProcessingImport(function, scope, err)) 377d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 378d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const SourceDir& input_dir = scope->GetSourceDir(); 380d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch SourceFile import_file = 381d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch input_dir.ResolveRelativeFile(args[0].string_value()); 382d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scope->settings()->import_manager().DoImport(import_file, function, 383d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scope, err); 384d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 385d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 386d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 387a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// set_sources_assignment_filter ----------------------------------------------- 388a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 389a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter"; 390a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kSetSourcesAssignmentFilter_Help[] = 391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "TODO(brettw) write this."; 392a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 393a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunSetSourcesAssignmentFilter(Scope* scope, 394a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const FunctionCallNode* function, 395a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::vector<Value>& args, 396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 397d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (args.size() != 1) { 398d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err = Err(function, "set_sources_assignment_filter takes one argument."); 399d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 400d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scoped_ptr<PatternList> f(new PatternList); 401d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch f->SetFromValue(args[0], err); 402d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!err->has_error()) 403d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scope->set_sources_assignment_filter(f.Pass()); 404d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 405d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 406d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 407d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 408a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// print ----------------------------------------------------------------------- 409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kPrint[] = "print"; 411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kPrint_Help[] = 412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "print(...)\n" 413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " Prints all arguments to the console separated by spaces. A newline is\n" 414a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " automatically appended to the end.\n" 415a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 416a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " This function is intended for debugging. Note that build files are run\n" 417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " in parallel so you may get interleaved prints. A buildfile may also\n" 418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " be executed more than once in parallel in the context of different\n" 419a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " toolchains so the prints from one file may be duplicated or\n" 420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " interleaved with itself.\n" 421a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "Examples:\n" 423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " print(\"Hello world\")\n" 424a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "\n" 425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " print(sources, deps)\n"; 426a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 427a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunPrint(Scope* scope, 428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const FunctionCallNode* function, 429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::vector<Value>& args, 430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 431d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < args.size(); i++) { 432d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (i != 0) 433d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::cout << " "; 4343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::cout << args[i].ToString(false); 435d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 436d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::cout << std::endl; 437d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 438d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 439d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// ----------------------------------------------------------------------------- 441d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo() 4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) : self_evaluating_args_runner(NULL), 4443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) generic_block_runner(NULL), 445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) executed_block_runner(NULL), 446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) no_block_runner(NULL), 447a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) help(NULL) { 448d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 449d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 4503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)FunctionInfo::FunctionInfo(SelfEvaluatingArgsFunction seaf, const char* in_help) 4513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) : self_evaluating_args_runner(seaf), 4523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) generic_block_runner(NULL), 4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) executed_block_runner(NULL), 4543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) no_block_runner(NULL), 4553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) help(in_help) { 4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 4573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo(GenericBlockFunction gbf, const char* in_help) 4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) : self_evaluating_args_runner(NULL), 4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) generic_block_runner(gbf), 461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) executed_block_runner(NULL), 462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) no_block_runner(NULL), 463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) help(in_help) { 464d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 465d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf, const char* in_help) 4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) : self_evaluating_args_runner(NULL), 4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) generic_block_runner(NULL), 469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) executed_block_runner(ebf), 470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) no_block_runner(NULL), 471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) help(in_help) { 472d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 473d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo(NoBlockFunction nbf, const char* in_help) 4753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) : self_evaluating_args_runner(NULL), 4763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) generic_block_runner(NULL), 477a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) executed_block_runner(NULL), 478a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) no_block_runner(nbf), 479a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) help(in_help) { 480d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 481d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 482a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Setup the function map via a static initializer. We use this because it 483a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// avoids race conditions without having to do some global setup function or 484a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// locking-heavy singleton checks at runtime. In practice, we always need this 485a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// before we can do anything interesting, so it's OK to wait for the 486a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// initializer. 487a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)struct FunctionInfoInitializer { 488a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FunctionInfoMap map; 489a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 490a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FunctionInfoInitializer() { 491a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) #define INSERT_FUNCTION(command) \ 492a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) map[k##command] = FunctionInfo(&Run##command, k##command##_Help); 493a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 494a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Assert) 495a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Component) 496a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Config) 497a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Copy) 498a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Custom) 499a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(DeclareArgs) 5003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) INSERT_FUNCTION(Defined) 501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(ExecScript) 502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Executable) 503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Group) 504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Import) 505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Print) 506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(ProcessFileTemplate) 507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(ReadFile) 508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(SetDefaults) 509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(SetDefaultToolchain) 510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(SetSourcesAssignmentFilter) 511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(SharedLibrary) 512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(StaticLibrary) 513a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Template) 514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Test) 515d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) INSERT_FUNCTION(ToBuildPath) 516a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Tool) 517a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(Toolchain) 5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) INSERT_FUNCTION(ToolchainArgs) 519a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) INSERT_FUNCTION(WriteFile) 520a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 521a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) #undef INSERT_FUNCTION 522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 523a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}; 524a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const FunctionInfoInitializer function_info; 525d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 526a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const FunctionInfoMap& GetFunctions() { 527a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return function_info.map; 528d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 529d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 530a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunFunction(Scope* scope, 531a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const FunctionCallNode* function, 5323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const ListNode* args_list, 533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) BlockNode* block, 534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Err* err) { 535d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Token& name = function->function(); 536d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 537a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const FunctionInfoMap& function_map = GetFunctions(); 538a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FunctionInfoMap::const_iterator found_function = 539a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) function_map.find(name.value()); 540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (found_function == function_map.end()) { 541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // No build-in function matching this, check for a template. 542d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const FunctionCallNode* rule = 543d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch scope->GetTemplate(function->function().value().as_string()); 5443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (rule) { 5453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Value args = args_list->Execute(scope, err); 5463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (err->has_error()) 5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Value(); 5483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return RunTemplateInvocation(scope, function, args.list_value(), block, 5493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) rule, err); 5503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 551d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 552a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) *err = Err(name, "Unknown function."); 553a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return Value(); 554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 5563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (found_function->second.self_evaluating_args_runner) { 5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return found_function->second.self_evaluating_args_runner( 5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scope, function, args_list, err); 5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 5603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 5613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // All other function types take a pre-executed set of args. 5623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Value args = args_list->Execute(scope, err); 5633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (err->has_error()) 5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return Value(); 5653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 566a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (found_function->second.generic_block_runner) { 567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!block) { 568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FillNeedsBlockError(function, err); 569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return Value(); 570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return found_function->second.generic_block_runner( 5723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scope, function, args.list_value(), block, err); 573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (found_function->second.executed_block_runner) { 576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!block) { 577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FillNeedsBlockError(function, err); 578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return Value(); 579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 580d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 581d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Scope block_scope(scope); 582d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch block->ExecuteBlockInScope(&block_scope, err); 583d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (err->has_error()) 584d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return Value(); 585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return found_function->second.executed_block_runner( 5863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function, args.list_value(), &block_scope, err); 587d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 588d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 589a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Otherwise it's a no-block function. 5903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return found_function->second.no_block_runner(scope, function, 5913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) args.list_value(), err); 592d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 593a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} // namespace functions 595