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, direct_dependent_configs\n"
18 " Deps: data, datadeps, deps, forward_dependent_configs_from, hard_dep\n"
19 #define GENERAL_TARGET_VARS \
20 " General: configs, source_prereqs, sources\n"
26 Value
ExecuteGenericTarget(const char* target_type
,
28 const FunctionCallNode
* function
,
29 const std::vector
<Value
>& args
,
32 if (!EnsureNotProcessingImport(function
, scope
, err
) ||
33 !EnsureNotProcessingBuildConfig(function
, scope
, err
))
35 Scope
block_scope(scope
);
36 if (!FillTargetBlockScope(scope
, function
, target_type
, block
,
37 args
, &block_scope
, err
))
40 block
->ExecuteBlockInScope(&block_scope
, err
);
44 TargetGenerator::GenerateTarget(&block_scope
, function
, args
,
49 block_scope
.CheckForUnusedVars(err
);
55 // action ----------------------------------------------------------------------
57 // Common help paragraph on script runtime execution directories.
58 #define SCRIPT_EXECUTION_CONTEXT \
59 " The script will be executed with the given arguments with the current\n"\
60 " directory being that of the root build directory. If you pass files\n"\
61 " to your script, see \"gn help to_build_path\" for how to convert\n" \
62 " file names to be relative to the build directory (file names in the\n" \
63 " sources, outputs, and source_prereqs will be all treated as relative\n" \
64 " to the current build file and converted as needed automatically).\n"
66 // Common help paragraph on script output directories.
67 #define SCRIPT_EXECUTION_OUTPUTS \
68 " All output files must be inside the output directory of the build.\n" \
69 " You would generally use |$target_out_dir| or |$target_gen_dir| to\n" \
70 " reference the output or generated intermediate file directories,\n" \
73 const char kAction
[] = "action";
74 const char kAction_HelpShort
[] =
75 "action: Declare a target that runs a script a single time.";
76 const char kAction_Help
[] =
77 "action: Declare a target that runs a script a single time.\n"
79 " This target type allows you to run a script a single time to produce\n"
80 " or more output files. If you want to run a script once for each of a\n"
81 " set of input files, see \"gn help action_foreach\".\n"
83 " In an action the \"sources\" and \"source_prereqs\" are treated the\n"
84 " same: they're both input dependencies on script execution with no\n"
85 " special handling. If you want to pass the sources to your script, you\n"
86 " must do so explicitly by including them in the \"args\".\n"
88 " It is recommended you put inputs to your script in the \"sources\"\n"
89 " variable, and stuff like other Python files required to run your\n"
90 " script in the \"source_prereqs\" variable.\n"
92 " You should specify files created by your script by specifying them in\n"
95 SCRIPT_EXECUTION_CONTEXT
97 "File name handling\n"
99 SCRIPT_EXECUTION_OUTPUTS
103 " args, data, datadeps, depfile, deps, outputs*, script*,\n"
104 " source_prereqs, sources\n"
109 " action(\"run_this_guy_once\") {\n"
110 " script = \"doprocessing.py\"\n"
111 " sources = [ \"my_configuration.txt\" ]\n"
112 " outputs = [ \"$target_gen_dir/insightful_output.txt\" ]\n"
114 " # Our script imports this Python file so we want to rebuild if it\n"
116 " source_prereqs = [ \"helper_library.py\" ]\n"
118 " # Note that we have to manually pass the sources to our script if\n"
119 " # the script needs them as inputs.\n"
120 " args = [ \"--out\", to_build_path(target_gen_dir) ] + sources\n"
123 Value
RunAction(Scope
* scope
,
124 const FunctionCallNode
* function
,
125 const std::vector
<Value
>& args
,
128 return ExecuteGenericTarget(functions::kAction
, scope
, function
, args
,
132 // action_foreach --------------------------------------------------------------
134 const char kActionForEach
[] = "action_foreach";
135 const char kActionForEach_HelpShort
[] =
136 "action_foreach: Declare a target that runs a script over a set of files.";
137 const char kActionForEach_Help
[] =
138 "action_foreach: Declare a target that runs a script over a set of files.\n"
140 " This target type allows you to run a script once-per-file over a set\n"
141 " of sources. If you want to run a script once that takes many files as\n"
142 " input, see \"gn help action\".\n"
144 " The script will be run once per file in the \"sources\" variable. The\n"
145 " \"outputs\" variable should specify one or more files with a source\n"
146 " expansion pattern in it (see \"gn help source_expansion\"). The output\n"
147 " file(s) for each script invocation should be unique. Normally you\n"
148 " use \"{{source_name_part}}\" in each output file.\n"
150 " If your script takes additional data as input, such as a shared\n"
151 " configuration file or a Python module it uses, those files should be\n"
152 " listed in the \"source_prereqs\" variable. These files are treated as\n"
153 " dependencies of each script invocation.\n"
155 SCRIPT_EXECUTION_CONTEXT
157 "File name handling\n"
159 SCRIPT_EXECUTION_OUTPUTS
163 " args, data, datadeps, depfile, deps, outputs*, script*,\n"
164 " source_prereqs, sources*\n"
169 " # Runs the script over each IDL file. The IDL script will generate\n"
170 " # both a .cc and a .h file for each input.\n"
171 " action_foreach(\"my_idl\") {\n"
172 " script = \"idl_processor.py\"\n"
173 " sources = [ \"foo.idl\", \"bar.idl\" ]\n"
175 " # Our script reads this file each time, so we need to list is as a\n"
176 " # dependency so we can rebuild if it changes.\n"
177 " source_prereqs = [ \"my_configuration.txt\" ]\n"
179 " # Transformation from source file name to output file names.\n"
180 " outputs = [ \"$target_gen_dir/{{source_name_part}}.h\",\n"
181 " \"$target_gen_dir/{{source_name_part}}.cc\" ]\n"
183 " # Note that since \"args\" is opaque to GN, if you specify paths\n"
184 " # here, you will need to convert it to be relative to the build\n"
185 " # directory using \"to_build_path()\".\n"
186 " args = [ \"{{source}}\",\n"
188 " to_build_path(relative_target_gen_dir) + \"/\" +\n"
189 " {{source_name_part}}.h\" ]\n"
192 Value
RunActionForEach(Scope
* scope
,
193 const FunctionCallNode
* function
,
194 const std::vector
<Value
>& args
,
197 return ExecuteGenericTarget(functions::kActionForEach
, scope
, function
, args
,
201 // component -------------------------------------------------------------------
203 const char kComponent
[] = "component";
204 const char kComponent_HelpShort
[] =
205 "component: Declare a component target.";
206 const char kComponent_Help
[] =
207 "component: Declare a component target.\n"
209 " A component is a shared library, static library, or source set\n"
210 " depending on the component mode. This allows a project to separate\n"
211 " out a build into shared libraries for faster development (link time is\n"
212 " reduced) but to switch to a static build for releases (for better\n"
215 " To use this function you must set the value of the \"component_mode\"\n"
216 " variable to one of the following strings:\n"
217 " - \"shared_library\"\n"
218 " - \"static_library\"\n"
219 " - \"source_set\"\n"
220 " It is an error to call \"component\" without defining the mode\n"
221 " (typically this is done in the master build configuration file).\n";
223 Value
RunComponent(Scope
* scope
,
224 const FunctionCallNode
* function
,
225 const std::vector
<Value
>& args
,
228 // A component is either a shared or static library, depending on the value
229 // of |component_mode|.
230 const Value
* component_mode_value
=
231 scope
->GetValue(variables::kComponentMode
);
233 static const char helptext
[] =
234 "You're declaring a component here but have not defined "
235 "\"component_mode\" to\neither \"shared_library\" or \"static_library\".";
236 if (!component_mode_value
) {
237 *err
= Err(function
->function(), "No component mode set.", helptext
);
240 if (component_mode_value
->type() != Value::STRING
||
241 (component_mode_value
->string_value() != functions::kSharedLibrary
&&
242 component_mode_value
->string_value() != functions::kStaticLibrary
&&
243 component_mode_value
->string_value() != functions::kSourceSet
)) {
244 *err
= Err(function
->function(), "Invalid component mode set.", helptext
);
247 const std::string
& component_mode
= component_mode_value
->string_value();
249 if (!EnsureNotProcessingImport(function
, scope
, err
))
251 Scope
block_scope(scope
);
252 if (!FillTargetBlockScope(scope
, function
, component_mode
.c_str(), block
,
253 args
, &block_scope
, err
))
256 block
->ExecuteBlockInScope(&block_scope
, err
);
257 if (err
->has_error())
260 TargetGenerator::GenerateTarget(&block_scope
, function
, args
,
261 component_mode
, err
);
265 // copy ------------------------------------------------------------------------
267 const char kCopy
[] = "copy";
268 const char kCopy_HelpShort
[] =
269 "copy: Declare a target that copies files.";
270 const char kCopy_Help
[] =
271 "copy: Declare a target that copies files.\n"
273 "File name handling\n"
275 " All output files must be inside the output directory of the build.\n"
276 " You would generally use |$target_out_dir| or |$target_gen_dir| to\n"
277 " reference the output or generated intermediate file directories,\n"
280 " Both \"sources\" and \"outputs\" must be specified. Sources can\n"
281 " as many files as you want, but there can only be one item in the\n"
282 " outputs list (plural is used for the name for consistency with\n"
283 " other target types).\n"
285 " If there is more than one source file, your output name should specify\n"
286 " a mapping from each source files to output file names using source\n"
287 " expansion (see \"gn help source_expansion\"). The placeholders will\n"
288 " will look like \"{{source_name_part}}\", for example.\n"
292 " # Write a rule that copies a checked-in DLL to the output directory.\n"
293 " copy(\"mydll\") {\n"
294 " sources = [ \"mydll.dll\" ]\n"
295 " outputs = [ \"$target_out_dir/mydll.dll\" ]\n"
298 " # Write a rule to copy several files to the target generated files\n"
300 " copy(\"myfiles\") {\n"
301 " sources = [ \"data1.dat\", \"data2.dat\", \"data3.dat\" ]\n"
303 " # Use source expansion to generate output files with the\n"
304 " # corresponding file names in the gen dir. This will just copy each\n"
306 " outputs = [ \"$target_gen_dir/{{source_file_part}}\" ]\n"
309 Value
RunCopy(const FunctionCallNode
* function
,
310 const std::vector
<Value
>& args
,
313 if (!EnsureNotProcessingImport(function
, scope
, err
) ||
314 !EnsureNotProcessingBuildConfig(function
, scope
, err
))
316 TargetGenerator::GenerateTarget(scope
, function
, args
, functions::kCopy
, err
);
320 // executable ------------------------------------------------------------------
322 const char kExecutable
[] = "executable";
323 const char kExecutable_HelpShort
[] =
324 "executable: Declare an executable target.";
325 const char kExecutable_Help
[] =
326 "executable: Declare an executable target.\n"
330 CONFIG_VALUES_VARS_HELP
332 DEPENDENT_CONFIG_VARS
335 Value
RunExecutable(Scope
* scope
,
336 const FunctionCallNode
* function
,
337 const std::vector
<Value
>& args
,
340 return ExecuteGenericTarget(functions::kExecutable
, scope
, function
, args
,
344 // group -----------------------------------------------------------------------
346 const char kGroup
[] = "group";
347 const char kGroup_HelpShort
[] =
348 "group: Declare a named group of targets.";
349 const char kGroup_Help
[] =
350 "group: Declare a named group of targets.\n"
352 " This target type allows you to create meta-targets that just collect a\n"
353 " set of dependencies into one named target. Groups can additionally\n"
354 " specify configs that apply to their dependents.\n"
356 " Depending on a group is exactly like depending directly on that\n"
357 " group's deps. Direct dependent configs will get automatically\n"
358 " forwarded through the group so you shouldn't need to use\n"
359 " \"forward_dependent_configs_from.\n"
364 DEPENDENT_CONFIG_VARS
368 " group(\"all\") {\n"
370 " \"//project:runner\",\n"
371 " \"//project:unit_tests\",\n"
375 Value
RunGroup(Scope
* scope
,
376 const FunctionCallNode
* function
,
377 const std::vector
<Value
>& args
,
380 return ExecuteGenericTarget(functions::kGroup
, scope
, function
, args
,
384 // shared_library --------------------------------------------------------------
386 const char kSharedLibrary
[] = "shared_library";
387 const char kSharedLibrary_HelpShort
[] =
388 "shared_library: Declare a shared library target.";
389 const char kSharedLibrary_Help
[] =
390 "shared_library: Declare a shared library target.\n"
392 " A shared library will be specified on the linker line for targets\n"
393 " listing the shared library in its \"deps\". If you don't want this\n"
394 " (say you dynamically load the library at runtime), then you should\n"
395 " depend on the shared library via \"datadeps\" instead.\n"
399 CONFIG_VALUES_VARS_HELP
401 DEPENDENT_CONFIG_VARS
404 Value
RunSharedLibrary(Scope
* scope
,
405 const FunctionCallNode
* function
,
406 const std::vector
<Value
>& args
,
409 return ExecuteGenericTarget(functions::kSharedLibrary
, scope
, function
, args
,
413 // source_set ------------------------------------------------------------------
415 extern const char kSourceSet
[] = "source_set";
416 extern const char kSourceSet_HelpShort
[] =
417 "source_set: Declare a source set target.";
418 extern const char kSourceSet_Help
[] =
419 "source_set: Declare a source set target.\n"
421 " A source set is a collection of sources that get compiled, but are not\n"
422 " linked to produce any kind of library. Instead, the resulting object\n"
423 " files are implicitly added to the linker line of all targets that\n"
424 " depend on the source set.\n"
426 " In most cases, a source set will behave like a static library, except\n"
427 " no actual library file will be produced. This will make the build go\n"
428 " a little faster by skipping creation of a large static library, while\n"
429 " maintaining the organizational benefits of focused build targets.\n"
431 " The main difference between a source set and a static library is\n"
432 " around handling of exported symbols. Most linkers assume declaring\n"
433 " a function exported means exported from the static library. The linker\n"
434 " can then do dead code elimination to delete code not reachable from\n"
435 " exported functions.\n"
437 " A source set will not do this code elimination since there is no link\n"
438 " step. This allows you to link many sources sets into a shared library\n"
439 " and have the \"exported symbol\" notation indicate \"export from the\n"
440 " final shared library and not from the intermediate targets.\" There is\n"
441 " no way to express this concept when linking multiple static libraries\n"
442 " into a shared library.\n"
446 CONFIG_VALUES_VARS_HELP
448 DEPENDENT_CONFIG_VARS
451 Value
RunSourceSet(Scope
* scope
,
452 const FunctionCallNode
* function
,
453 const std::vector
<Value
>& args
,
456 return ExecuteGenericTarget(functions::kSourceSet
, scope
, function
, args
,
460 // static_library --------------------------------------------------------------
462 const char kStaticLibrary
[] = "static_library";
463 const char kStaticLibrary_HelpShort
[] =
464 "static_library: Declare a static library target.";
465 const char kStaticLibrary_Help
[] =
466 "static_library: Declare a static library target.\n"
468 " Make a \".a\" / \".lib\" file.\n"
470 " If you only need the static library for intermediate results in the\n"
471 " build, you should consider a source_set instead since it will skip\n"
472 " the (potentially slow) step of creating the intermediate library file.\n"
476 CONFIG_VALUES_VARS_HELP
478 DEPENDENT_CONFIG_VARS
481 Value
RunStaticLibrary(Scope
* scope
,
482 const FunctionCallNode
* function
,
483 const std::vector
<Value
>& args
,
486 return ExecuteGenericTarget(functions::kStaticLibrary
, scope
, function
, args
,
490 // test ------------------------------------------------------------------------
492 const char kTest
[] = "test";
493 const char kTest_HelpShort
[] =
494 "test: Declares a test target.";
495 const char kTest_Help
[] =
496 "test: Declares a test target.\n"
498 " This is like an executable target, but is named differently to make\n"
499 " the purpose of the target more obvious. It's possible in the future\n"
500 " we can do some enhancements like \"list all of the tests in a given\n"
503 " See \"gn help executable\" for usage.\n";
505 Value
RunTest(Scope
* scope
,
506 const FunctionCallNode
* function
,
507 const std::vector
<Value
>& args
,
510 return ExecuteGenericTarget(functions::kExecutable
, scope
, function
, args
,
514 } // namespace functions