[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / tools / gn / function_template.cc
blob17dda0662d9fa8bfb82f943f57149d11f26e27d2
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.
5 #include "tools/gn/functions.h"
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"
12 namespace functions {
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 "Variables and templates:\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 " A template will typically forward some or all variables from the\n"
48 " invoking scope to a target that it defines. Often, such variables\n"
49 " might be optional. Use the pattern:\n"
50 "\n"
51 " if (defined(invoker.deps)) {\n"
52 " deps = invoker.deps\n"
53 " }\n"
54 "\n"
55 " The function forward_variables_from() provides a shortcut to forward\n"
56 " one or more or possibly all variables in this manner:\n"
57 "\n"
58 " forward_variables_from(invoker, [\"deps\", \"public_deps\"])\n"
59 "\n"
60 "Target naming:\n"
61 "\n"
62 " Your template should almost always define a built-in target with the\n"
63 " name the template invoker specified. For example, if you have an IDL\n"
64 " template and somebody does:\n"
65 " idl(\"foo\") {...\n"
66 " you will normally want this to expand to something defining a\n"
67 " source_set or static_library named \"foo\" (among other things you may\n"
68 " need). This way, when another target specifies a dependency on\n"
69 " \"foo\", the static_library or source_set will be linked.\n"
70 "\n"
71 " It is also important that any other targets your template expands to\n"
72 " have globally unique names, or you will get collisions.\n"
73 "\n"
74 " Access the invoking name in your template via the implicit\n"
75 " \"target_name\" variable. This should also be the basis for how other\n"
76 " targets that a template expands to ensure uniqueness.\n"
77 "\n"
78 " A typical example would be a template that defines an action to\n"
79 " generate some source files, and a source_set to compile that source.\n"
80 " Your template would name the source_set \"target_name\" because\n"
81 " that's what you want external targets to depend on to link your code.\n"
82 " And you would name the action something like \"${target_name}_action\"\n"
83 " to make it unique. The source set would have a dependency on the\n"
84 " action to make it run.\n"
85 "\n"
86 "Example of defining a template:\n"
87 "\n"
88 " template(\"my_idl\") {\n"
89 " # Be nice and help callers debug problems by checking that the\n"
90 " # variables the template requires are defined. This gives a nice\n"
91 " # message rather than giving the user an error about an\n"
92 " # undefined variable in the file defining the template\n"
93 " #\n"
94 " # You can also use defined() to give default values to variables\n"
95 " # unspecified by the invoker.\n"
96 " assert(defined(invoker.sources),\n"
97 " \"Need sources in $target_name listing the idl files.\")\n"
98 "\n"
99 " # Name of the intermediate target that does the code gen. This must\n"
100 " # incorporate the target name so it's unique across template\n"
101 " # instantiations.\n"
102 " code_gen_target_name = target_name + \"_code_gen\"\n"
103 "\n"
104 " # Intermediate target to convert IDL to C source. Note that the name\n"
105 " # is based on the name the invoker of the template specified. This\n"
106 " # way, each time the template is invoked we get a unique\n"
107 " # intermediate action name (since all target names are in the global\n"
108 " # scope).\n"
109 " action_foreach(code_gen_target_name) {\n"
110 " # Access the scope defined by the invoker via the implicit\n"
111 " # \"invoker\" variable.\n"
112 " sources = invoker.sources\n"
113 "\n"
114 " # Note that we need an absolute path for our script file name.\n"
115 " # The current directory when executing this code will be that of\n"
116 " # the invoker (this is why we can use the \"sources\" directly\n"
117 " # above without having to rebase all of the paths). But if we need\n"
118 " # to reference a script relative to the template file, we'll need\n"
119 " # to use an absolute path instead.\n"
120 " script = \"//tools/idl/idl_code_generator.py\"\n"
121 "\n"
122 " # Tell GN how to expand output names given the sources.\n"
123 " # See \"gn help source_expansion\" for more.\n"
124 " outputs = [ \"$target_gen_dir/{{source_name_part}}.cc\",\n"
125 " \"$target_gen_dir/{{source_name_part}}.h\" ]\n"
126 " }\n"
127 "\n"
128 " # Name the source set the same as the template invocation so\n"
129 " # instancing this template produces something that other targets\n"
130 " # can link to in their deps.\n"
131 " source_set(target_name) {\n"
132 " # Generates the list of sources, we get these from the\n"
133 " # action_foreach above.\n"
134 " sources = get_target_outputs(\":$code_gen_target_name\")\n"
135 "\n"
136 " # This target depends on the files produced by the above code gen\n"
137 " # target.\n"
138 " deps = [ \":$code_gen_target_name\" ]\n"
139 " }\n"
140 " }\n"
141 "\n"
142 "Example of invoking the resulting template:\n"
143 "\n"
144 " # This calls the template code above, defining target_name to be\n"
145 " # \"foo_idl_files\" and \"invoker\" to be the set of stuff defined in\n"
146 " # the curly brackets.\n"
147 " my_idl(\"foo_idl_files\") {\n"
148 " # Goes into the template as \"invoker.sources\".\n"
149 " sources = [ \"foo.idl\", \"bar.idl\" ]\n"
150 " }\n"
151 "\n"
152 " # Here is a target that depends on our template.\n"
153 " executable(\"my_exe\") {\n"
154 " # Depend on the name we gave the template call above. Internally,\n"
155 " # this will produce a dependency from executable to the source_set\n"
156 " # inside the template (since it has this name), which will in turn\n"
157 " # depend on the code gen action.\n"
158 " deps = [ \":foo_idl_files\" ]\n"
159 " }\n";
161 Value RunTemplate(Scope* scope,
162 const FunctionCallNode* function,
163 const std::vector<Value>& args,
164 BlockNode* block,
165 Err* err) {
166 // Of course you can have configs and targets in a template. But here, we're
167 // not actually executing the block, only declaring it. Marking the template
168 // declaration as non-nestable means that you can't put it inside a target,
169 // for example.
170 NonNestableBlock non_nestable(scope, function, "template");
171 if (!non_nestable.Enter(err))
172 return Value();
174 // TODO(brettw) determine if the function is built-in and throw an error if
175 // it is.
176 if (args.size() != 1) {
177 *err = Err(function->function(),
178 "Need exactly one string arg to template.");
179 return Value();
181 if (!args[0].VerifyTypeIs(Value::STRING, err))
182 return Value();
183 std::string template_name = args[0].string_value();
185 const Template* existing_template = scope->GetTemplate(template_name);
186 if (existing_template) {
187 *err = Err(function, "Duplicate template definition.",
188 "A template with this name was already defined.");
189 err->AppendSubErr(Err(existing_template->GetDefinitionRange(),
190 "Previous definition."));
191 return Value();
194 scope->AddTemplate(template_name, new Template(scope, function));
195 return Value();
198 } // namespace functions