tools/gn: simplify BlockNode semantics
[chromium-blink-merge.git] / tools / gn / functions_target.cc
blob1441b8e6fa0d59ecf906aae5b8db708959e92cf9
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/config_values_generator.h"
8 #include "tools/gn/err.h"
9 #include "tools/gn/parse_tree.h"
10 #include "tools/gn/scope.h"
11 #include "tools/gn/target_generator.h"
12 #include "tools/gn/value.h"
13 #include "tools/gn/variables.h"
15 #define DEPENDENT_CONFIG_VARS \
16 " Dependent configs: all_dependent_configs, public_configs\n"
17 #define DEPS_VARS \
18 " Deps: data_deps, deps, forward_dependent_configs_from, public_deps\n"
19 #define GENERAL_TARGET_VARS \
20 " General: check_includes, configs, data, inputs, output_name,\n" \
21 " output_extension, public, sources, testonly, visibility\n"
23 namespace functions {
25 namespace {
27 Value ExecuteGenericTarget(const char* target_type,
28 Scope* scope,
29 const FunctionCallNode* function,
30 const std::vector<Value>& args,
31 BlockNode* block,
32 Err* err) {
33 if (!EnsureNotProcessingImport(function, scope, err) ||
34 !EnsureNotProcessingBuildConfig(function, scope, err))
35 return Value();
36 Scope block_scope(scope);
37 if (!FillTargetBlockScope(scope, function, target_type, block,
38 args, &block_scope, err))
39 return Value();
41 block->Execute(&block_scope, err);
42 if (err->has_error())
43 return Value();
45 TargetGenerator::GenerateTarget(&block_scope, function, args,
46 target_type, err);
47 if (err->has_error())
48 return Value();
50 block_scope.CheckForUnusedVars(err);
51 return Value();
54 } // namespace
56 // action ----------------------------------------------------------------------
58 // Common help paragraph on script runtime execution directories.
59 #define SCRIPT_EXECUTION_CONTEXT \
60 " The script will be executed with the given arguments with the current\n"\
61 " directory being that of the root build directory. If you pass files\n"\
62 " to your script, see \"gn help rebase_path\" for how to convert\n" \
63 " file names to be relative to the build directory (file names in the\n" \
64 " sources, outputs, and inputs will be all treated as relative to the\n" \
65 " current build file and converted as needed automatically).\n"
67 // Common help paragraph on script output directories.
68 #define SCRIPT_EXECUTION_OUTPUTS \
69 " All output files must be inside the output directory of the build.\n" \
70 " You would generally use |$target_out_dir| or |$target_gen_dir| to\n" \
71 " reference the output or generated intermediate file directories,\n" \
72 " respectively.\n"
74 #define ACTION_DEPS \
75 " The \"deps\" and \"public_deps\" for an action will always be\n" \
76 " completed before any part of the action is run so it can depend on\n" \
77 " the output of previous steps. The \"data_deps\" will be built if the\n" \
78 " action is built, but may not have completed before all steps of the\n" \
79 " action are started. This can give additional parallelism in the build\n"\
80 " for runtime-only dependencies.\n"
82 const char kAction[] = "action";
83 const char kAction_HelpShort[] =
84 "action: Declare a target that runs a script a single time.";
85 const char kAction_Help[] =
86 "action: Declare a target that runs a script a single time.\n"
87 "\n"
88 " This target type allows you to run a script a single time to produce\n"
89 " or more output files. If you want to run a script once for each of a\n"
90 " set of input files, see \"gn help action_foreach\".\n"
91 "\n"
92 "Inputs\n"
93 "\n"
94 " In an action the \"sources\" and \"inputs\" are treated the same:\n"
95 " they're both input dependencies on script execution with no special\n"
96 " handling. If you want to pass the sources to your script, you must do\n"
97 " so explicitly by including them in the \"args\". Note also that this\n"
98 " means there is no special handling of paths since GN doesn't know\n"
99 " which of the args are paths and not. You will want to use\n"
100 " rebase_path() to convert paths to be relative to the root_build_dir.\n"
101 "\n"
102 " You can dynamically write input dependencies (for incremental rebuilds\n"
103 " if an input file changes) by writing a depfile when the script is run\n"
104 " (see \"gn help depfile\"). This is more flexible than \"inputs\".\n"
105 "\n"
106 " It is recommended you put inputs to your script in the \"sources\"\n"
107 " variable, and stuff like other Python files required to run your\n"
108 " script in the \"inputs\" variable.\n"
109 "\n"
110 ACTION_DEPS
111 "\n"
112 "Outputs\n"
113 "\n"
114 " You should specify files created by your script by specifying them in\n"
115 " the \"outputs\".\n"
116 "\n"
117 SCRIPT_EXECUTION_CONTEXT
118 "\n"
119 "File name handling\n"
120 "\n"
121 SCRIPT_EXECUTION_OUTPUTS
122 "\n"
123 "Variables\n"
124 "\n"
125 " args, data, data_deps, depfile, deps, outputs*, script*,\n"
126 " inputs, sources\n"
127 " * = required\n"
128 "\n"
129 "Example\n"
130 "\n"
131 " action(\"run_this_guy_once\") {\n"
132 " script = \"doprocessing.py\"\n"
133 " sources = [ \"my_configuration.txt\" ]\n"
134 " outputs = [ \"$target_gen_dir/insightful_output.txt\" ]\n"
135 "\n"
136 " # Our script imports this Python file so we want to rebuild if it\n"
137 " # changes.\n"
138 " inputs = [ \"helper_library.py\" ]\n"
139 "\n"
140 " # Note that we have to manually pass the sources to our script if\n"
141 " # the script needs them as inputs.\n"
142 " args = [ \"--out\", rebase_path(target_gen_dir, root_build_dir) ] +\n"
143 " rebase_path(sources, root_build_dir)\n"
144 " }\n";
146 Value RunAction(Scope* scope,
147 const FunctionCallNode* function,
148 const std::vector<Value>& args,
149 BlockNode* block,
150 Err* err) {
151 return ExecuteGenericTarget(functions::kAction, scope, function, args,
152 block, err);
155 // action_foreach --------------------------------------------------------------
157 const char kActionForEach[] = "action_foreach";
158 const char kActionForEach_HelpShort[] =
159 "action_foreach: Declare a target that runs a script over a set of files.";
160 const char kActionForEach_Help[] =
161 "action_foreach: Declare a target that runs a script over a set of files.\n"
162 "\n"
163 " This target type allows you to run a script once-per-file over a set\n"
164 " of sources. If you want to run a script once that takes many files as\n"
165 " input, see \"gn help action\".\n"
166 "\n"
167 "Inputs\n"
168 "\n"
169 " The script will be run once per file in the \"sources\" variable. The\n"
170 " \"outputs\" variable should specify one or more files with a source\n"
171 " expansion pattern in it (see \"gn help source_expansion\"). The output\n"
172 " file(s) for each script invocation should be unique. Normally you\n"
173 " use \"{{source_name_part}}\" in each output file.\n"
174 "\n"
175 " If your script takes additional data as input, such as a shared\n"
176 " configuration file or a Python module it uses, those files should be\n"
177 " listed in the \"inputs\" variable. These files are treated as\n"
178 " dependencies of each script invocation.\n"
179 "\n"
180 " You can dynamically write input dependencies (for incremental rebuilds\n"
181 " if an input file changes) by writing a depfile when the script is run\n"
182 " (see \"gn help depfile\"). This is more flexible than \"inputs\".\n"
183 "\n"
184 ACTION_DEPS
185 "\n"
186 "Outputs\n"
187 "\n"
188 SCRIPT_EXECUTION_CONTEXT
189 "\n"
190 "File name handling\n"
191 "\n"
192 SCRIPT_EXECUTION_OUTPUTS
193 "\n"
194 "Variables\n"
195 "\n"
196 " args, data, data_deps, depfile, deps, outputs*, script*,\n"
197 " inputs, sources*\n"
198 " * = required\n"
199 "\n"
200 "Example\n"
201 "\n"
202 " # Runs the script over each IDL file. The IDL script will generate\n"
203 " # both a .cc and a .h file for each input.\n"
204 " action_foreach(\"my_idl\") {\n"
205 " script = \"idl_processor.py\"\n"
206 " sources = [ \"foo.idl\", \"bar.idl\" ]\n"
207 "\n"
208 " # Our script reads this file each time, so we need to list is as a\n"
209 " # dependency so we can rebuild if it changes.\n"
210 " inputs = [ \"my_configuration.txt\" ]\n"
211 "\n"
212 " # Transformation from source file name to output file names.\n"
213 " outputs = [ \"$target_gen_dir/{{source_name_part}}.h\",\n"
214 " \"$target_gen_dir/{{source_name_part}}.cc\" ]\n"
215 "\n"
216 " # Note that since \"args\" is opaque to GN, if you specify paths\n"
217 " # here, you will need to convert it to be relative to the build\n"
218 " # directory using \"rebase_path()\".\n"
219 " args = [\n"
220 " \"{{source}}\",\n"
221 " \"-o\",\n"
222 " rebase_path(relative_target_gen_dir, root_build_dir) +\n"
223 " \"/{{source_name_part}}.h\" ]\n"
224 " }\n"
225 "\n";
226 Value RunActionForEach(Scope* scope,
227 const FunctionCallNode* function,
228 const std::vector<Value>& args,
229 BlockNode* block,
230 Err* err) {
231 return ExecuteGenericTarget(functions::kActionForEach, scope, function, args,
232 block, err);
235 // copy ------------------------------------------------------------------------
237 const char kCopy[] = "copy";
238 const char kCopy_HelpShort[] =
239 "copy: Declare a target that copies files.";
240 const char kCopy_Help[] =
241 "copy: Declare a target that copies files.\n"
242 "\n"
243 "File name handling\n"
244 "\n"
245 " All output files must be inside the output directory of the build.\n"
246 " You would generally use |$target_out_dir| or |$target_gen_dir| to\n"
247 " reference the output or generated intermediate file directories,\n"
248 " respectively.\n"
249 "\n"
250 " Both \"sources\" and \"outputs\" must be specified. Sources can\n"
251 " as many files as you want, but there can only be one item in the\n"
252 " outputs list (plural is used for the name for consistency with\n"
253 " other target types).\n"
254 "\n"
255 " If there is more than one source file, your output name should specify\n"
256 " a mapping from each source files to output file names using source\n"
257 " expansion (see \"gn help source_expansion\"). The placeholders will\n"
258 " will look like \"{{source_name_part}}\", for example.\n"
259 "\n"
260 "Examples\n"
261 "\n"
262 " # Write a rule that copies a checked-in DLL to the output directory.\n"
263 " copy(\"mydll\") {\n"
264 " sources = [ \"mydll.dll\" ]\n"
265 " outputs = [ \"$target_out_dir/mydll.dll\" ]\n"
266 " }\n"
267 "\n"
268 " # Write a rule to copy several files to the target generated files\n"
269 " # directory.\n"
270 " copy(\"myfiles\") {\n"
271 " sources = [ \"data1.dat\", \"data2.dat\", \"data3.dat\" ]\n"
272 "\n"
273 " # Use source expansion to generate output files with the\n"
274 " # corresponding file names in the gen dir. This will just copy each\n"
275 " # file.\n"
276 " outputs = [ \"$target_gen_dir/{{source_file_part}}\" ]\n"
277 " }\n";
279 Value RunCopy(const FunctionCallNode* function,
280 const std::vector<Value>& args,
281 Scope* scope,
282 Err* err) {
283 if (!EnsureNotProcessingImport(function, scope, err) ||
284 !EnsureNotProcessingBuildConfig(function, scope, err))
285 return Value();
286 TargetGenerator::GenerateTarget(scope, function, args, functions::kCopy, err);
287 return Value();
290 // executable ------------------------------------------------------------------
292 const char kExecutable[] = "executable";
293 const char kExecutable_HelpShort[] =
294 "executable: Declare an executable target.";
295 const char kExecutable_Help[] =
296 "executable: Declare an executable target.\n"
297 "\n"
298 "Variables\n"
299 "\n"
300 CONFIG_VALUES_VARS_HELP
301 DEPS_VARS
302 DEPENDENT_CONFIG_VARS
303 GENERAL_TARGET_VARS;
305 Value RunExecutable(Scope* scope,
306 const FunctionCallNode* function,
307 const std::vector<Value>& args,
308 BlockNode* block,
309 Err* err) {
310 return ExecuteGenericTarget(functions::kExecutable, scope, function, args,
311 block, err);
314 // group -----------------------------------------------------------------------
316 const char kGroup[] = "group";
317 const char kGroup_HelpShort[] =
318 "group: Declare a named group of targets.";
319 const char kGroup_Help[] =
320 "group: Declare a named group of targets.\n"
321 "\n"
322 " This target type allows you to create meta-targets that just collect a\n"
323 " set of dependencies into one named target. Groups can additionally\n"
324 " specify configs that apply to their dependents.\n"
325 "\n"
326 " Depending on a group is exactly like depending directly on that\n"
327 " group's deps. Direct dependent configs will get automatically\n"
328 " forwarded through the group so you shouldn't need to use\n"
329 " \"forward_dependent_configs_from.\n"
330 "\n"
331 "Variables\n"
332 "\n"
333 DEPS_VARS
334 DEPENDENT_CONFIG_VARS
335 "\n"
336 "Example\n"
337 "\n"
338 " group(\"all\") {\n"
339 " deps = [\n"
340 " \"//project:runner\",\n"
341 " \"//project:unit_tests\",\n"
342 " ]\n"
343 " }\n";
345 Value RunGroup(Scope* scope,
346 const FunctionCallNode* function,
347 const std::vector<Value>& args,
348 BlockNode* block,
349 Err* err) {
350 return ExecuteGenericTarget(functions::kGroup, scope, function, args,
351 block, err);
354 // shared_library --------------------------------------------------------------
356 const char kSharedLibrary[] = "shared_library";
357 const char kSharedLibrary_HelpShort[] =
358 "shared_library: Declare a shared library target.";
359 const char kSharedLibrary_Help[] =
360 "shared_library: Declare a shared library target.\n"
361 "\n"
362 " A shared library will be specified on the linker line for targets\n"
363 " listing the shared library in its \"deps\". If you don't want this\n"
364 " (say you dynamically load the library at runtime), then you should\n"
365 " depend on the shared library via \"data_deps\" instead.\n"
366 "\n"
367 "Variables\n"
368 "\n"
369 CONFIG_VALUES_VARS_HELP
370 DEPS_VARS
371 DEPENDENT_CONFIG_VARS
372 GENERAL_TARGET_VARS;
374 Value RunSharedLibrary(Scope* scope,
375 const FunctionCallNode* function,
376 const std::vector<Value>& args,
377 BlockNode* block,
378 Err* err) {
379 return ExecuteGenericTarget(functions::kSharedLibrary, scope, function, args,
380 block, err);
383 // source_set ------------------------------------------------------------------
385 extern const char kSourceSet[] = "source_set";
386 extern const char kSourceSet_HelpShort[] =
387 "source_set: Declare a source set target.";
388 extern const char kSourceSet_Help[] =
389 "source_set: Declare a source set target.\n"
390 "\n"
391 " A source set is a collection of sources that get compiled, but are not\n"
392 " linked to produce any kind of library. Instead, the resulting object\n"
393 " files are implicitly added to the linker line of all targets that\n"
394 " depend on the source set.\n"
395 "\n"
396 " In most cases, a source set will behave like a static library, except\n"
397 " no actual library file will be produced. This will make the build go\n"
398 " a little faster by skipping creation of a large static library, while\n"
399 " maintaining the organizational benefits of focused build targets.\n"
400 "\n"
401 " The main difference between a source set and a static library is\n"
402 " around handling of exported symbols. Most linkers assume declaring\n"
403 " a function exported means exported from the static library. The linker\n"
404 " can then do dead code elimination to delete code not reachable from\n"
405 " exported functions.\n"
406 "\n"
407 " A source set will not do this code elimination since there is no link\n"
408 " step. This allows you to link many sources sets into a shared library\n"
409 " and have the \"exported symbol\" notation indicate \"export from the\n"
410 " final shared library and not from the intermediate targets.\" There is\n"
411 " no way to express this concept when linking multiple static libraries\n"
412 " into a shared library.\n"
413 "\n"
414 "Variables\n"
415 "\n"
416 CONFIG_VALUES_VARS_HELP
417 DEPS_VARS
418 DEPENDENT_CONFIG_VARS
419 GENERAL_TARGET_VARS;
421 Value RunSourceSet(Scope* scope,
422 const FunctionCallNode* function,
423 const std::vector<Value>& args,
424 BlockNode* block,
425 Err* err) {
426 return ExecuteGenericTarget(functions::kSourceSet, scope, function, args,
427 block, err);
430 // static_library --------------------------------------------------------------
432 const char kStaticLibrary[] = "static_library";
433 const char kStaticLibrary_HelpShort[] =
434 "static_library: Declare a static library target.";
435 const char kStaticLibrary_Help[] =
436 "static_library: Declare a static library target.\n"
437 "\n"
438 " Make a \".a\" / \".lib\" file.\n"
439 "\n"
440 " If you only need the static library for intermediate results in the\n"
441 " build, you should consider a source_set instead since it will skip\n"
442 " the (potentially slow) step of creating the intermediate library file.\n"
443 "\n"
444 "Variables\n"
445 "\n"
446 CONFIG_VALUES_VARS_HELP
447 DEPS_VARS
448 DEPENDENT_CONFIG_VARS
449 GENERAL_TARGET_VARS;
451 Value RunStaticLibrary(Scope* scope,
452 const FunctionCallNode* function,
453 const std::vector<Value>& args,
454 BlockNode* block,
455 Err* err) {
456 return ExecuteGenericTarget(functions::kStaticLibrary, scope, function, args,
457 block, err);
460 } // namespace functions