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 "gn/functions.h"
6
7 #include "gn/parse_tree.h"
8 #include "gn/scope.h"
9 #include "gn/template.h"
10 #include "gn/value.h"
11
12 namespace functions {
13
14 const char kTemplate[] = "template";
15 const char kTemplate_HelpShort[] = "template: Define a template rule.";
16 const char kTemplate_Help[] =
17 R"(template: Define a template rule.
18
19 A template defines a custom name that acts like a function. It provides a way
20 to add to the built-in target types.
21
22 The template() function is used to declare a template. To invoke the
23 template, just use the name of the template like any other target type.
24
25 Often you will want to declare your template in a special file that other
26 files will import (see "gn help import") so your template rule can be shared
27 across build files.
28
29 Variables and templates:
30
31 When you call template() it creates a closure around all variables currently
32 in scope with the code in the template block. When the template is invoked,
33 the closure will be executed.
34
35 When the template is invoked, the code in the caller is executed and passed
36 to the template code as an implicit "invoker" variable. The template uses
37 this to read state out of the invoking code.
38
39 One thing explicitly excluded from the closure is the "current directory"
40 against which relative file names are resolved. The current directory will be
41 that of the invoking code, since typically that code specifies the file
42 names. This means all files internal to the template should use absolute
43 names.
44
45 A template will typically forward some or all variables from the invoking
46 scope to a target that it defines. Often, such variables might be optional.
47 Use the pattern:
48
49 if (defined(invoker.deps)) {
50 deps = invoker.deps
51 }
52
53 The function forward_variables_from() provides a shortcut to forward one or
54 more or possibly all variables in this manner:
55
56 forward_variables_from(invoker, ["deps", "public_deps"])
57
58 Target naming
59
60 Your template should almost always define a built-in target with the name the
61 template invoker specified. For example, if you have an IDL template and
62 somebody does:
63 idl("foo") {...
64 you will normally want this to expand to something defining a source_set or
65 static_library named "foo" (among other things you may need). This way, when
66 another target specifies a dependency on "foo", the static_library or
67 source_set will be linked.
68
69 It is also important that any other targets your template expands to have
70 unique names, or you will get collisions.
71
72 Access the invoking name in your template via the implicit "target_name"
73 variable. This should also be the basis for how other targets that a template
74 expands to ensure uniqueness.
75
76 A typical example would be a template that defines an action to generate some
77 source files, and a source_set to compile that source. Your template would
78 name the source_set "target_name" because that's what you want external
79 targets to depend on to link your code. And you would name the action
80 something like "${target_name}_action" to make it unique. The source set
81 would have a dependency on the action to make it run.
82
83 Overriding builtin targets
84
85 You can use template to redefine a built-in target in which case your template
86 takes a precedence over the built-in one. All uses of the target from within
87 the template definition will refer to the built-in target which makes it
88 possible to extend the behavior of the built-in target:
89
90 template("shared_library") {
91 shared_library(shlib) {
92 forward_variables_from(invoker, "*")
93 ...
94 }
95 }
96
97 Example of defining a template
98
99 template("my_idl") {
100 # Be nice and help callers debug problems by checking that the variables
101 # the template requires are defined. This gives a nice message rather than
102 # giving the user an error about an undefined variable in the file defining
103 # the template
104 #
105 # You can also use defined() to give default values to variables
106 # unspecified by the invoker.
107 assert(defined(invoker.sources),
108 "Need sources in $target_name listing the idl files.")
109
110 # Name of the intermediate target that does the code gen. This must
111 # incorporate the target name so it's unique across template
112 # instantiations.
113 code_gen_target_name = target_name + "_code_gen"
114
115 # Intermediate target to convert IDL to C source. Note that the name is
116 # based on the name the invoker of the template specified. This way, each
117 # time the template is invoked we get a unique intermediate action name
118 # (since all target names are in the global scope).
119 action_foreach(code_gen_target_name) {
120 # Access the scope defined by the invoker via the implicit "invoker"
121 # variable.
122 sources = invoker.sources
123
124 # Note that we need an absolute path for our script file name. The
125 # current directory when executing this code will be that of the invoker
126 # (this is why we can use the "sources" directly above without having to
127 # rebase all of the paths). But if we need to reference a script relative
128 # to the template file, we'll need to use an absolute path instead.
129 script = "//tools/idl/idl_code_generator.py"
130
131 # Tell GN how to expand output names given the sources.
132 # See "gn help source_expansion" for more.
133 outputs = [ "$target_gen_dir/{{source_name_part}}.cc",
134 "$target_gen_dir/{{source_name_part}}.h" ]
135 }
136
137 # Name the source set the same as the template invocation so instancing
138 # this template produces something that other targets can link to in their
139 # deps.
140 source_set(target_name) {
141 # Generates the list of sources, we get these from the action_foreach
142 # above.
143 sources = get_target_outputs(":$code_gen_target_name")
144
145 # This target depends on the files produced by the above code gen target.
146 deps = [ ":$code_gen_target_name" ]
147 }
148 }
149
150 Example of invoking the resulting template
151
152 # This calls the template code above, defining target_name to be
153 # "foo_idl_files" and "invoker" to be the set of stuff defined in the curly
154 # brackets.
155 my_idl("foo_idl_files") {
156 # Goes into the template as "invoker.sources".
157 sources = [ "foo.idl", "bar.idl" ]
158 }
159
160 # Here is a target that depends on our template.
161 executable("my_exe") {
162 # Depend on the name we gave the template call above. Internally, this will
163 # produce a dependency from executable to the source_set inside the
164 # template (since it has this name), which will in turn depend on the code
165 # gen action.
166 deps = [ ":foo_idl_files" ]
167 }
168 )";
169
RunTemplate(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)170 Value RunTemplate(Scope* scope,
171 const FunctionCallNode* function,
172 const std::vector<Value>& args,
173 BlockNode* block,
174 Err* err) {
175 // Of course you can have configs and targets in a template. But here, we're
176 // not actually executing the block, only declaring it. Marking the template
177 // declaration as non-nestable means that you can't put it inside a target,
178 // for example.
179 NonNestableBlock non_nestable(scope, function, "template");
180 if (!non_nestable.Enter(err))
181 return Value();
182
183 // TODO(brettw) determine if the function is built-in and throw an error if
184 // it is.
185 if (args.size() != 1) {
186 *err =
187 Err(function->function(), "Need exactly one string arg to template.");
188 return Value();
189 }
190 if (!args[0].VerifyTypeIs(Value::STRING, err))
191 return Value();
192 std::string template_name = args[0].string_value();
193
194 const Template* existing_template = scope->GetTemplate(template_name);
195 if (existing_template) {
196 *err = Err(function, "Duplicate template definition.",
197 "A template with this name was already defined.");
198 err->AppendSubErr(
199 Err(existing_template->GetDefinitionRange(), "Previous definition."));
200 return Value();
201 }
202
203 scope->AddTemplate(template_name, new Template(scope, function));
204
205 // The template object above created a closure around the variables in the
206 // current scope. The template code will execute in that context when it's
207 // invoked. But this means that any variables defined above that are used
208 // by the template won't get marked used just by defining the template. The
209 // result can be spurious unused variable errors.
210 //
211 // The "right" thing to do would be to walk the syntax tree inside the
212 // template, find all identifier references, and mark those variables used.
213 // This is annoying and error-prone to implement and takes extra time to run
214 // for this narrow use case.
215 //
216 // Templates are most often defined in .gni files which don't get
217 // used-variable checking anyway, and this case is annoying enough that the
218 // incremental value of unused variable checking isn't worth the
219 // alternatives. So all values in scope before this template definition are
220 // exempted from unused variable checking.
221 scope->MarkAllUsed();
222
223 return Value();
224 }
225
226 } // namespace functions
227