• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 namespace functions {
24 
25 namespace {
26 
ExecuteGenericTarget(const char * target_type,Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)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();
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 
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";
145 
RunAction(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)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);
153 }
154 
155 // action_foreach --------------------------------------------------------------
156 
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";
RunActionForEach(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)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);
233 }
234 
235 // copy ------------------------------------------------------------------------
236 
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";
278 
RunCopy(const FunctionCallNode * function,const std::vector<Value> & args,Scope * scope,Err * err)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();
288 }
289 
290 // executable ------------------------------------------------------------------
291 
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;
304 
RunExecutable(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)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);
312 }
313 
314 // group -----------------------------------------------------------------------
315 
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";
344 
RunGroup(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)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);
352 }
353 
354 // shared_library --------------------------------------------------------------
355 
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;
373 
RunSharedLibrary(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)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);
381 }
382 
383 // source_set ------------------------------------------------------------------
384 
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;
420 
RunSourceSet(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)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);
428 }
429 
430 // static_library --------------------------------------------------------------
431 
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;
450 
RunStaticLibrary(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)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);
458 }
459 
460 }  // namespace functions
461