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/template.h"
13 #include "tools/gn/value.h"
14 #include "tools/gn/variables.h"
16 #define DEPENDENT_CONFIG_VARS \
17 " Dependent configs: all_dependent_configs, public_configs\n"
19 " Deps: data_deps, deps, forward_dependent_configs_from, public_deps\n"
20 #define GENERAL_TARGET_VARS \
21 " General: check_includes, configs, data, inputs, output_name,\n" \
22 " output_extension, public, sources, testonly, visibility\n"
28 Value
ExecuteGenericTarget(const char* target_type
,
30 const FunctionCallNode
* function
,
31 const std::vector
<Value
>& args
,
34 if (!EnsureNotProcessingImport(function
, scope
, err
) ||
35 !EnsureNotProcessingBuildConfig(function
, scope
, err
))
37 Scope
block_scope(scope
);
38 if (!FillTargetBlockScope(scope
, function
, target_type
, block
,
39 args
, &block_scope
, err
))
42 block
->Execute(&block_scope
, err
);
46 TargetGenerator::GenerateTarget(&block_scope
, function
, args
,
51 block_scope
.CheckForUnusedVars(err
);
57 // action ----------------------------------------------------------------------
59 // Common help paragraph on script runtime execution directories.
60 #define SCRIPT_EXECUTION_CONTEXT \
61 " The script will be executed with the given arguments with the current\n"\
62 " directory being that of the root build directory. If you pass files\n"\
63 " to your script, see \"gn help rebase_path\" for how to convert\n" \
64 " file names to be relative to the build directory (file names in the\n" \
65 " sources, outputs, and inputs will be all treated as relative to the\n" \
66 " current build file and converted as needed automatically).\n"
68 // Common help paragraph on script output directories.
69 #define SCRIPT_EXECUTION_OUTPUTS \
70 " All output files must be inside the output directory of the build.\n" \
71 " You would generally use |$target_out_dir| or |$target_gen_dir| to\n" \
72 " reference the output or generated intermediate file directories,\n" \
76 " The \"deps\" and \"public_deps\" for an action will always be\n" \
77 " completed before any part of the action is run so it can depend on\n" \
78 " the output of previous steps. The \"data_deps\" will be built if the\n" \
79 " action is built, but may not have completed before all steps of the\n" \
80 " action are started. This can give additional parallelism in the build\n"\
81 " for runtime-only dependencies.\n"
83 const char kAction
[] = "action";
84 const char kAction_HelpShort
[] =
85 "action: Declare a target that runs a script a single time.";
86 const char kAction_Help
[] =
87 "action: Declare a target that runs a script a single time.\n"
89 " This target type allows you to run a script a single time to produce\n"
90 " or more output files. If you want to run a script once for each of a\n"
91 " set of input files, see \"gn help action_foreach\".\n"
95 " In an action the \"sources\" and \"inputs\" are treated the same:\n"
96 " they're both input dependencies on script execution with no special\n"
97 " handling. If you want to pass the sources to your script, you must do\n"
98 " so explicitly by including them in the \"args\". Note also that this\n"
99 " means there is no special handling of paths since GN doesn't know\n"
100 " which of the args are paths and not. You will want to use\n"
101 " rebase_path() to convert paths to be relative to the root_build_dir.\n"
103 " You can dynamically write input dependencies (for incremental rebuilds\n"
104 " if an input file changes) by writing a depfile when the script is run\n"
105 " (see \"gn help depfile\"). This is more flexible than \"inputs\".\n"
107 " It is recommended you put inputs to your script in the \"sources\"\n"
108 " variable, and stuff like other Python files required to run your\n"
109 " script in the \"inputs\" variable.\n"
115 " You should specify files created by your script by specifying them in\n"
116 " the \"outputs\".\n"
118 SCRIPT_EXECUTION_CONTEXT
120 "File name handling\n"
122 SCRIPT_EXECUTION_OUTPUTS
126 " args, data, data_deps, depfile, deps, outputs*, script*,\n"
132 " action(\"run_this_guy_once\") {\n"
133 " script = \"doprocessing.py\"\n"
134 " sources = [ \"my_configuration.txt\" ]\n"
135 " outputs = [ \"$target_gen_dir/insightful_output.txt\" ]\n"
137 " # Our script imports this Python file so we want to rebuild if it\n"
139 " inputs = [ \"helper_library.py\" ]\n"
141 " # Note that we have to manually pass the sources to our script if\n"
142 " # the script needs them as inputs.\n"
143 " args = [ \"--out\", rebase_path(target_gen_dir, root_build_dir) ] +\n"
144 " rebase_path(sources, root_build_dir)\n"
147 Value
RunAction(Scope
* scope
,
148 const FunctionCallNode
* function
,
149 const std::vector
<Value
>& args
,
152 return ExecuteGenericTarget(functions::kAction
, scope
, function
, args
,
156 // action_foreach --------------------------------------------------------------
158 const char kActionForEach
[] = "action_foreach";
159 const char kActionForEach_HelpShort
[] =
160 "action_foreach: Declare a target that runs a script over a set of files.";
161 const char kActionForEach_Help
[] =
162 "action_foreach: Declare a target that runs a script over a set of files.\n"
164 " This target type allows you to run a script once-per-file over a set\n"
165 " of sources. If you want to run a script once that takes many files as\n"
166 " input, see \"gn help action\".\n"
170 " The script will be run once per file in the \"sources\" variable. The\n"
171 " \"outputs\" variable should specify one or more files with a source\n"
172 " expansion pattern in it (see \"gn help source_expansion\"). The output\n"
173 " file(s) for each script invocation should be unique. Normally you\n"
174 " use \"{{source_name_part}}\" in each output file.\n"
176 " If your script takes additional data as input, such as a shared\n"
177 " configuration file or a Python module it uses, those files should be\n"
178 " listed in the \"inputs\" variable. These files are treated as\n"
179 " dependencies of each script invocation.\n"
181 " You can dynamically write input dependencies (for incremental rebuilds\n"
182 " if an input file changes) by writing a depfile when the script is run\n"
183 " (see \"gn help depfile\"). This is more flexible than \"inputs\".\n"
189 SCRIPT_EXECUTION_CONTEXT
191 "File name handling\n"
193 SCRIPT_EXECUTION_OUTPUTS
197 " args, data, data_deps, depfile, deps, outputs*, script*,\n"
198 " inputs, sources*\n"
203 " # Runs the script over each IDL file. The IDL script will generate\n"
204 " # both a .cc and a .h file for each input.\n"
205 " action_foreach(\"my_idl\") {\n"
206 " script = \"idl_processor.py\"\n"
207 " sources = [ \"foo.idl\", \"bar.idl\" ]\n"
209 " # Our script reads this file each time, so we need to list is as a\n"
210 " # dependency so we can rebuild if it changes.\n"
211 " inputs = [ \"my_configuration.txt\" ]\n"
213 " # Transformation from source file name to output file names.\n"
214 " outputs = [ \"$target_gen_dir/{{source_name_part}}.h\",\n"
215 " \"$target_gen_dir/{{source_name_part}}.cc\" ]\n"
217 " # Note that since \"args\" is opaque to GN, if you specify paths\n"
218 " # here, you will need to convert it to be relative to the build\n"
219 " # directory using \"rebase_path()\".\n"
223 " rebase_path(relative_target_gen_dir, root_build_dir) +\n"
224 " \"/{{source_name_part}}.h\" ]\n"
227 Value
RunActionForEach(Scope
* scope
,
228 const FunctionCallNode
* function
,
229 const std::vector
<Value
>& args
,
232 return ExecuteGenericTarget(functions::kActionForEach
, scope
, function
, args
,
236 // copy ------------------------------------------------------------------------
238 const char kCopy
[] = "copy";
239 const char kCopy_HelpShort
[] =
240 "copy: Declare a target that copies files.";
241 const char kCopy_Help
[] =
242 "copy: Declare a target that copies files.\n"
244 "File name handling\n"
246 " All output files must be inside the output directory of the build.\n"
247 " You would generally use |$target_out_dir| or |$target_gen_dir| to\n"
248 " reference the output or generated intermediate file directories,\n"
251 " Both \"sources\" and \"outputs\" must be specified. Sources can\n"
252 " as many files as you want, but there can only be one item in the\n"
253 " outputs list (plural is used for the name for consistency with\n"
254 " other target types).\n"
256 " If there is more than one source file, your output name should specify\n"
257 " a mapping from each source files to output file names using source\n"
258 " expansion (see \"gn help source_expansion\"). The placeholders will\n"
259 " will look like \"{{source_name_part}}\", for example.\n"
263 " # Write a rule that copies a checked-in DLL to the output directory.\n"
264 " copy(\"mydll\") {\n"
265 " sources = [ \"mydll.dll\" ]\n"
266 " outputs = [ \"$target_out_dir/mydll.dll\" ]\n"
269 " # Write a rule to copy several files to the target generated files\n"
271 " copy(\"myfiles\") {\n"
272 " sources = [ \"data1.dat\", \"data2.dat\", \"data3.dat\" ]\n"
274 " # Use source expansion to generate output files with the\n"
275 " # corresponding file names in the gen dir. This will just copy each\n"
277 " outputs = [ \"$target_gen_dir/{{source_file_part}}\" ]\n"
280 Value
RunCopy(const FunctionCallNode
* function
,
281 const std::vector
<Value
>& args
,
284 if (!EnsureNotProcessingImport(function
, scope
, err
) ||
285 !EnsureNotProcessingBuildConfig(function
, scope
, err
))
287 TargetGenerator::GenerateTarget(scope
, function
, args
, functions::kCopy
, err
);
291 // executable ------------------------------------------------------------------
293 const char kExecutable
[] = "executable";
294 const char kExecutable_HelpShort
[] =
295 "executable: Declare an executable target.";
296 const char kExecutable_Help
[] =
297 "executable: Declare an executable target.\n"
301 CONFIG_VALUES_VARS_HELP
303 DEPENDENT_CONFIG_VARS
306 Value
RunExecutable(Scope
* scope
,
307 const FunctionCallNode
* function
,
308 const std::vector
<Value
>& args
,
311 return ExecuteGenericTarget(functions::kExecutable
, scope
, function
, args
,
315 // group -----------------------------------------------------------------------
317 const char kGroup
[] = "group";
318 const char kGroup_HelpShort
[] =
319 "group: Declare a named group of targets.";
320 const char kGroup_Help
[] =
321 "group: Declare a named group of targets.\n"
323 " This target type allows you to create meta-targets that just collect a\n"
324 " set of dependencies into one named target. Groups can additionally\n"
325 " specify configs that apply to their dependents.\n"
327 " Depending on a group is exactly like depending directly on that\n"
328 " group's deps. Direct dependent configs will get automatically\n"
329 " forwarded through the group so you shouldn't need to use\n"
330 " \"forward_dependent_configs_from.\n"
335 DEPENDENT_CONFIG_VARS
339 " group(\"all\") {\n"
341 " \"//project:runner\",\n"
342 " \"//project:unit_tests\",\n"
346 Value
RunGroup(Scope
* scope
,
347 const FunctionCallNode
* function
,
348 const std::vector
<Value
>& args
,
351 return ExecuteGenericTarget(functions::kGroup
, scope
, function
, args
,
355 // shared_library --------------------------------------------------------------
357 const char kSharedLibrary
[] = "shared_library";
358 const char kSharedLibrary_HelpShort
[] =
359 "shared_library: Declare a shared library target.";
360 const char kSharedLibrary_Help
[] =
361 "shared_library: Declare a shared library target.\n"
363 " A shared library will be specified on the linker line for targets\n"
364 " listing the shared library in its \"deps\". If you don't want this\n"
365 " (say you dynamically load the library at runtime), then you should\n"
366 " depend on the shared library via \"data_deps\" instead.\n"
370 CONFIG_VALUES_VARS_HELP
372 DEPENDENT_CONFIG_VARS
375 Value
RunSharedLibrary(Scope
* scope
,
376 const FunctionCallNode
* function
,
377 const std::vector
<Value
>& args
,
380 return ExecuteGenericTarget(functions::kSharedLibrary
, scope
, function
, args
,
384 // source_set ------------------------------------------------------------------
386 extern const char kSourceSet
[] = "source_set";
387 extern const char kSourceSet_HelpShort
[] =
388 "source_set: Declare a source set target.";
389 extern const char kSourceSet_Help
[] =
390 "source_set: Declare a source set target.\n"
392 " A source set is a collection of sources that get compiled, but are not\n"
393 " linked to produce any kind of library. Instead, the resulting object\n"
394 " files are implicitly added to the linker line of all targets that\n"
395 " depend on the source set.\n"
397 " In most cases, a source set will behave like a static library, except\n"
398 " no actual library file will be produced. This will make the build go\n"
399 " a little faster by skipping creation of a large static library, while\n"
400 " maintaining the organizational benefits of focused build targets.\n"
402 " The main difference between a source set and a static library is\n"
403 " around handling of exported symbols. Most linkers assume declaring\n"
404 " a function exported means exported from the static library. The linker\n"
405 " can then do dead code elimination to delete code not reachable from\n"
406 " exported functions.\n"
408 " A source set will not do this code elimination since there is no link\n"
409 " step. This allows you to link many sources sets into a shared library\n"
410 " and have the \"exported symbol\" notation indicate \"export from the\n"
411 " final shared library and not from the intermediate targets.\" There is\n"
412 " no way to express this concept when linking multiple static libraries\n"
413 " into a shared library.\n"
417 CONFIG_VALUES_VARS_HELP
419 DEPENDENT_CONFIG_VARS
422 Value
RunSourceSet(Scope
* scope
,
423 const FunctionCallNode
* function
,
424 const std::vector
<Value
>& args
,
427 return ExecuteGenericTarget(functions::kSourceSet
, scope
, function
, args
,
431 // static_library --------------------------------------------------------------
433 const char kStaticLibrary
[] = "static_library";
434 const char kStaticLibrary_HelpShort
[] =
435 "static_library: Declare a static library target.";
436 const char kStaticLibrary_Help
[] =
437 "static_library: Declare a static library target.\n"
439 " Make a \".a\" / \".lib\" file.\n"
441 " If you only need the static library for intermediate results in the\n"
442 " build, you should consider a source_set instead since it will skip\n"
443 " the (potentially slow) step of creating the intermediate library file.\n"
447 CONFIG_VALUES_VARS_HELP
449 DEPENDENT_CONFIG_VARS
452 Value
RunStaticLibrary(Scope
* scope
,
453 const FunctionCallNode
* function
,
454 const std::vector
<Value
>& args
,
457 return ExecuteGenericTarget(functions::kStaticLibrary
, scope
, function
, args
,
461 // target ---------------------------------------------------------------------
463 const char kTarget
[] = "target";
464 const char kTarget_HelpShort
[] =
465 "target: Declare an target with the given programmatic type.";
466 const char kTarget_Help
[] =
467 "target: Declare an target with the given programmatic type.\n"
469 " target(target_type_string, target_name_string) { ... }\n"
471 " The target() function is a way to invoke a built-in target or template\n"
472 " with a type determined at runtime. This is useful for cases where the\n"
473 " type of a target might not be known statically.\n"
475 " Only templates and built-in target functions are supported for the\n"
476 " target_type_string parameter. Arbitrary functions, configs, and\n"
477 " toolchains are not supported.\n"
480 " target(\"source_set\", \"doom_melon\") {\n"
481 " Is equivalent to:\n"
482 " source_set(\"doom_melon\") {\n"
486 " if (foo_build_as_shared) {\n"
487 " my_type = \"shared_library\"\n"
489 " my_type = \"source_set\"\n"
492 " target(my_type, \"foo\") {\n"
495 Value
RunTarget(Scope
* scope
,
496 const FunctionCallNode
* function
,
497 const std::vector
<Value
>& args
,
500 if (args
.size() != 2) {
501 *err
= Err(function
, "Expected two arguments.",
502 "Dude, try \"gn help target\".");
506 // The first argument must be a string (the target type). Don't type-check
507 // the second argument since the target-specific function will do that.
508 if (!args
[0].VerifyTypeIs(Value::STRING
, err
))
510 const std::string
& target_type
= args
[0].string_value();
512 // The rest of the args are passed to the function.
513 std::vector
<Value
> sub_args(args
.begin() + 1, args
.end());
515 // Run a template if it is one.
516 const Template
* templ
= scope
->GetTemplate(target_type
);
518 return templ
->Invoke(scope
, function
, sub_args
, block
, err
);
520 // Otherwise, assume the target is a built-in target type.
521 return ExecuteGenericTarget(target_type
.c_str(), scope
, function
, sub_args
,
525 } // namespace functions