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/template.h" 10 #include "tools/gn/value.h" 11 12 namespace functions { 13 14 const char kTemplate[] = "template"; 15 const char kTemplate_HelpShort[] = 16 "template: Define a template rule."; 17 const char kTemplate_Help[] = 18 "template: Define a template rule.\n" 19 "\n" 20 " A template defines a custom name that acts like a function. It\n" 21 " provides a way to add to the built-in target types.\n" 22 "\n" 23 " The template() function is used to declare a template. To invoke the\n" 24 " template, just use the name of the template like any other target\n" 25 " type.\n" 26 "\n" 27 " Often you will want to declare your template in a special file that\n" 28 " other files will import (see \"gn help import\") so your template\n" 29 " rule can be shared across build files.\n" 30 "\n" 31 "More details:\n" 32 "\n" 33 " When you call template() it creates a closure around all variables\n" 34 " currently in scope with the code in the template block. When the\n" 35 " template is invoked, the closure will be executed.\n" 36 "\n" 37 " When the template is invoked, the code in the caller is executed and\n" 38 " passed to the template code as an implicit \"invoker\" variable. The\n" 39 " template uses this to read state out of the invoking code.\n" 40 "\n" 41 " One thing explicitly excluded from the closure is the \"current\n" 42 " directory\" against which relative file names are resolved. The\n" 43 " current directory will be that of the invoking code, since typically\n" 44 " that code specifies the file names. This means all files internal\n" 45 " to the template should use absolute names.\n" 46 "\n" 47 "Target naming:\n" 48 "\n" 49 " Your template should almost always define a built-in target with the\n" 50 " name the template invoker specified. For example, if you have an IDL\n" 51 " template and somebody does:\n" 52 " idl(\"foo\") {...\n" 53 " you will normally want this to expand to something defining a\n" 54 " source_set or static_library named \"foo\" (among other things you may\n" 55 " need). This way, when another target specifies a dependency on\n" 56 " \"foo\", the static_library or source_set will be linked.\n" 57 "\n" 58 " It is also important that any other targets your template expands to\n" 59 " have globally unique names, or you will get collisions.\n" 60 "\n" 61 " Access the invoking name in your template via the implicit\n" 62 " \"target_name\" variable. This should also be the basis of how other\n" 63 " targets that a template expands to to ensure uniquness.\n" 64 "\n" 65 " A typical example would be a template that defines an action to\n" 66 " generate some source files, and a source_set to compile that source.\n" 67 " Your template would name the source_set \"target_name\" because\n" 68 " that's what you want external targets to depend on to link your code.\n" 69 " And you would name the action something like \"${target_name}_action\"\n" 70 " to make it unique. The source set would have a dependency on the\n" 71 " action to make it run.\n" 72 "\n" 73 "Example of defining a template:\n" 74 "\n" 75 " template(\"my_idl\") {\n" 76 " # Be nice and help callers debug problems by checking that the\n" 77 " # variables the template requires are defined. This gives a nice\n" 78 " # message rather than giving the user an error about an\n" 79 " # undefined variable in the file defining the template\n" 80 " #\n" 81 " # You can also use defined() to give default values to variables\n" 82 " # unspecified by the invoker.\n" 83 " assert(defined(invoker.sources),\n" 84 " \"Need sources in $target_name listing the idl files.\")\n" 85 "\n" 86 " # Name of the intermediate target that does the code gen. This must\n" 87 " # incorporate the target name so it's unique across template\n" 88 " # instantiations.\n" 89 " code_gen_target_name = target_name + \"_code_gen\"\n" 90 "\n" 91 " # Intermediate target to convert IDL to C source. Note that the name\n" 92 " # is based on the name the invoker of the template specified. This\n" 93 " # way, each time the template is invoked we get a unique\n" 94 " # intermediate action name (since all target names are in the global\n" 95 " # scope).\n" 96 " action_foreach(code_gen_target_name) {\n" 97 " # Access the scope defined by the invoker via the implicit\n" 98 " # \"invoker\" variable.\n" 99 " sources = invoker.sources\n" 100 "\n" 101 " # Note that we need an absolute path for our script file name.\n" 102 " # The current directory when executing this code will be that of\n" 103 " # the invoker (this is why we can use the \"sources\" directly\n" 104 " # above without having to rebase all of the paths). But if we need\n" 105 " # to reference a script relative to the template file, we'll need\n" 106 " # to use an absolute path instead.\n" 107 " script = \"//tools/idl/idl_code_generator.py\"\n" 108 "\n" 109 " # Tell GN how to expand output names given the sources.\n" 110 " # See \"gn help source_expansion\" for more.\n" 111 " outputs = [ \"$target_gen_dir/{{source_name_part}}.cc\",\n" 112 " \"$target_gen_dir/{{source_name_part}}.h\" ]\n" 113 " }\n" 114 "\n" 115 " # Name the source set the same as the template invocation so\n" 116 " # instancing this template produces something that other targets\n" 117 " # can link to in their deps.\n" 118 " source_set(target_name) {\n" 119 " # Generates the list of sources, we get these from the\n" 120 " # action_foreach above.\n" 121 " sources = get_target_outputs(\":$code_gen_target_name\")\n" 122 "\n" 123 " # This target depends on the files produced by the above code gen\n" 124 " # target.\n" 125 " deps = [ \":$code_gen_target_name\" ]\n" 126 " }\n" 127 " }\n" 128 "\n" 129 "Example of invoking the resulting template:\n" 130 "\n" 131 " # This calls the template code above, defining target_name to be\n" 132 " # \"foo_idl_files\" and \"invoker\" to be the set of stuff defined in\n" 133 " # the curly brackets.\n" 134 " my_idl(\"foo_idl_files\") {\n" 135 " # Goes into the template as \"invoker.sources\".\n" 136 " sources = [ \"foo.idl\", \"bar.idl\" ]\n" 137 " }\n" 138 "\n" 139 " # Here is a target that depends on our template.\n" 140 " executable(\"my_exe\") {\n" 141 " # Depend on the name we gave the template call above. Internally,\n" 142 " # this will produce a dependency from executable to the source_set\n" 143 " # inside the template (since it has this name), which will in turn\n" 144 " # depend on the code gen action.\n" 145 " deps = [ \":foo_idl_files\" ]\n" 146 " }\n"; 147 148 Value RunTemplate(Scope* scope, 149 const FunctionCallNode* function, 150 const std::vector<Value>& args, 151 BlockNode* block, 152 Err* err) { 153 // TODO(brettw) determine if the function is built-in and throw an error if 154 // it is. 155 if (args.size() != 1) { 156 *err = Err(function->function(), 157 "Need exactly one string arg to template."); 158 return Value(); 159 } 160 if (!args[0].VerifyTypeIs(Value::STRING, err)) 161 return Value(); 162 std::string template_name = args[0].string_value(); 163 164 const Template* existing_template = scope->GetTemplate(template_name); 165 if (existing_template) { 166 *err = Err(function, "Duplicate template definition.", 167 "A template with this name was already defined."); 168 err->AppendSubErr(Err(existing_template->GetDefinitionRange(), 169 "Previous definition.")); 170 return Value(); 171 } 172 173 scope->AddTemplate(template_name, new Template(scope, function)); 174 return Value(); 175 } 176 177 } // namespace functions 178