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 "tools/gn/functions.h"
6
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"
14
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"
22
23namespace functions {
24
25namespace {
26
27Value 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();
40
41  block->ExecuteBlockInScope(&block_scope, err);
42  if (err->has_error())
43    return Value();
44
45  TargetGenerator::GenerateTarget(&block_scope, function, args,
46                                  target_type, err);
47  if (err->has_error())
48    return Value();
49
50  block_scope.CheckForUnusedVars(err);
51  return Value();
52}
53
54}  // namespace
55
56// action ----------------------------------------------------------------------
57
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"
66
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"
73
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"
81
82const char kAction[] = "action";
83const char kAction_HelpShort[] =
84    "action: Declare a target that runs a script a single time.";
85const 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";
145
146Value 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);
153}
154
155// action_foreach --------------------------------------------------------------
156
157const char kActionForEach[] = "action_foreach";
158const char kActionForEach_HelpShort[] =
159    "action_foreach: Declare a target that runs a script over a set of files.";
160const 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";
226Value 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);
233}
234
235// copy ------------------------------------------------------------------------
236
237const char kCopy[] = "copy";
238const char kCopy_HelpShort[] =
239    "copy: Declare a target that copies files.";
240const 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";
278
279Value 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();
288}
289
290// executable ------------------------------------------------------------------
291
292const char kExecutable[] = "executable";
293const char kExecutable_HelpShort[] =
294    "executable: Declare an executable target.";
295const 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;
304
305Value 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);
312}
313
314// group -----------------------------------------------------------------------
315
316const char kGroup[] = "group";
317const char kGroup_HelpShort[] =
318    "group: Declare a named group of targets.";
319const 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";
344
345Value 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);
352}
353
354// shared_library --------------------------------------------------------------
355
356const char kSharedLibrary[] = "shared_library";
357const char kSharedLibrary_HelpShort[] =
358    "shared_library: Declare a shared library target.";
359const 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;
373
374Value 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);
381}
382
383// source_set ------------------------------------------------------------------
384
385extern const char kSourceSet[] = "source_set";
386extern const char kSourceSet_HelpShort[] =
387    "source_set: Declare a source set target.";
388extern 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;
420
421Value 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);
428}
429
430// static_library --------------------------------------------------------------
431
432const char kStaticLibrary[] = "static_library";
433const char kStaticLibrary_HelpShort[] =
434    "static_library: Declare a static library target.";
435const 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;
450
451Value 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);
458}
459
460}  // namespace functions
461