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