1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "tools/gn/functions.h" 6 7 #include "tools/gn/parse_tree.h" 8 #include "tools/gn/scope.h" 9 #include "tools/gn/value.h" 10 11 namespace functions { 12 13 const char kTemplate[] = "template"; 14 const char kTemplate_Help[] = 15 "template: Define a template rule.\n" 16 "\n" 17 " A template defines a custom rule name that can expand to one or more\n" 18 " other rules (typically built-in rules like \"static_library\"). It\n" 19 " provides a way to add to the built-in target types.\n" 20 "\n" 21 " The template() function is used to declare a template. To invoke the\n" 22 " template, just use the name of the template like any other target\n" 23 " type.\n" 24 "\n" 25 "More details:\n" 26 "\n" 27 " Semantically, the code in the template is stored. When a function\n" 28 " with the name is called, the block following the invocation is\n" 29 " executed, *then* your template code is executed. So if the invocation\n" 30 " sets the |source| variable, for example, that variable will be\n" 31 " accessible to you when the template code runs.\n" 32 "\n" 33 " The template() function does not generate a closure, so the\n" 34 " environment, current directory, etc. will all be the same as from\n" 35 " the template is invoked.\n" 36 "\n" 37 "Hints:\n" 38 "\n" 39 " If your template expands to more than one target, be sure to name\n" 40 " the intermediate targets based on the name of the template\n" 41 " instantiation so that the names are globally unique. The variable\n" 42 " |target_name| will be this name.\n" 43 "\n" 44 " Likewise, you will always want to generate a target in your template\n" 45 " with the original |target_name|. Otherwise, invoking your template\n" 46 " will not actually generate a node in the dependency graph that other\n" 47 " targets can reference.\n" 48 "\n" 49 " Often you will want to declare your template in a special file that\n" 50 " other files will import (see \"gn help import\") so your template\n" 51 " rule can be shared across build files.\n" 52 "\n" 53 "Example of defining a template:\n" 54 "\n" 55 " template(\"my_idl\") {\n" 56 " # Maps input files to output files, used in both targets below.\n" 57 " filter = [ \"$target_gen_dir/{{source_name_part}}.cc\",\n" 58 " \"$target_gen_dir/{{source_name_part}}.h\" ]\n" 59 "\n" 60 " # Intermediate target to compile IDL to C source.\n" 61 " custom(\"${target_name}_code_gen\") {\n" 62 " # The |sources| will be inherited from the surrounding scope so\n" 63 " # we don't need to redefine it.\n" 64 " script = \"foo.py\"\n" 65 " outputs = filter # Variable from above.\n" 66 " }\n" 67 "\n" 68 " # Name the static library the same as the template invocation so\n" 69 " # instanting this template produces something that other targets\n" 70 " # can link to in their deps.\n" 71 " static_library(target_name) {\n" 72 " # Generates the list of sources.\n" 73 " # See \"gn help process_file_template\"\n" 74 " sources = process_file_template(sources, filter)\n" 75 " }\n" 76 " }\n" 77 "\n" 78 "Example of invoking the resulting template:\n" 79 "\n" 80 " my_idl(\"foo_idl_files\") {\n" 81 " sources = [ \"foo.idl\", \"bar.idl\" ]\n" 82 " }\n"; 83 84 Value RunTemplate(Scope* scope, 85 const FunctionCallNode* function, 86 const std::vector<Value>& args, 87 BlockNode* block, 88 Err* err) { 89 // TODO(brettw) determine if the function is built-in and throw an error if 90 // it is. 91 if (args.size() != 1) { 92 *err = Err(function->function(), 93 "Need exactly one string arg to template."); 94 return Value(); 95 } 96 if (!args[0].VerifyTypeIs(Value::STRING, err)) 97 return Value(); 98 std::string template_name = args[0].string_value(); 99 100 const FunctionCallNode* existing_template = scope->GetTemplate(template_name); 101 if (existing_template) { 102 *err = Err(function, "Duplicate template definition.", 103 "A template with this name was already defined."); 104 err->AppendSubErr(Err(existing_template->function(), 105 "Previous definition.")); 106 return Value(); 107 } 108 109 scope->AddTemplate(template_name, function); 110 return Value(); 111 } 112 113 } // namespace functions 114