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 <iostream>
8
9#include "base/strings/string_util.h"
10#include "tools/gn/config.h"
11#include "tools/gn/config_values_generator.h"
12#include "tools/gn/err.h"
13#include "tools/gn/input_file.h"
14#include "tools/gn/item_tree.h"
15#include "tools/gn/parse_tree.h"
16#include "tools/gn/scheduler.h"
17#include "tools/gn/scope.h"
18#include "tools/gn/settings.h"
19#include "tools/gn/target_manager.h"
20#include "tools/gn/token.h"
21#include "tools/gn/value.h"
22
23namespace {
24
25void FillNeedsBlockError(const FunctionCallNode* function, Err* err) {
26  *err = Err(function->function(), "This function call requires a block.",
27      "The block's \"{\" must be on the same line as the function "
28      "call's \")\".");
29}
30
31// This is called when a template is invoked. When we see a template
32// declaration, that funciton is RunTemplate.
33Value RunTemplateInvocation(Scope* scope,
34                            const FunctionCallNode* invocation,
35                            const std::vector<Value>& args,
36                            BlockNode* block,
37                            const FunctionCallNode* rule,
38                            Err* err) {
39  if (!EnsureNotProcessingImport(invocation, scope, err))
40    return Value();
41  Scope block_scope(scope);
42  if (!FillTargetBlockScope(scope, invocation,
43                            invocation->function().value().data(),
44                            block, args, &block_scope, err))
45    return Value();
46
47  // Run the block for the rule invocation.
48  block->ExecuteBlockInScope(&block_scope, err);
49  if (err->has_error())
50    return Value();
51
52  // Now run the rule itself with that block as the current scope.
53  rule->block()->ExecuteBlockInScope(&block_scope, err);
54  if (err->has_error())
55    return Value();
56
57  return Value();
58}
59
60}  // namespace
61
62// ----------------------------------------------------------------------------
63
64bool EnsureNotProcessingImport(const ParseNode* node,
65                               const Scope* scope,
66                               Err* err) {
67  if (scope->IsProcessingImport()) {
68    *err = Err(node, "Not valid from an import.",
69        "We need to talk about this thing you are doing here. Doing this\n"
70        "kind of thing from an imported file makes me feel like you are\n"
71        "abusing me. Imports are for defining defaults, variables, and rules.\n"
72        "The appropriate place for this kind of thing is really in a normal\n"
73        "BUILD file.");
74    return false;
75  }
76  return true;
77}
78
79bool EnsureNotProcessingBuildConfig(const ParseNode* node,
80                                    const Scope* scope,
81                                    Err* err) {
82  if (scope->IsProcessingBuildConfig()) {
83    *err = Err(node, "Not valid from the build config.",
84        "You can't do this kind of thing from the build config script, "
85        "silly!\nPut it in a regular BUILD file.");
86    return false;
87  }
88  return true;
89}
90
91bool FillTargetBlockScope(const Scope* scope,
92                          const FunctionCallNode* function,
93                          const char* target_type,
94                          const BlockNode* block,
95                          const std::vector<Value>& args,
96                          Scope* block_scope,
97                          Err* err) {
98  if (!block) {
99    FillNeedsBlockError(function, err);
100    return false;
101  }
102
103  // Copy the target defaults, if any, into the scope we're going to execute
104  // the block in.
105  const Scope* default_scope = scope->GetTargetDefaults(target_type);
106  if (default_scope) {
107    if (!default_scope->NonRecursiveMergeTo(block_scope, function,
108                                            "target defaults", err))
109      return false;
110  }
111
112  // The name is the single argument to the target function.
113  if (!EnsureSingleStringArg(function, args, err))
114    return false;
115
116  // Set the target name variable to the current target, and mark it used
117  // because we don't want to issue an error if the script ignores it.
118  const base::StringPiece target_name("target_name");
119  block_scope->SetValue(target_name, Value(function, args[0].string_value()),
120                        function);
121  block_scope->MarkUsed(target_name);
122  return true;
123}
124
125bool EnsureSingleStringArg(const FunctionCallNode* function,
126                           const std::vector<Value>& args,
127                           Err* err) {
128  if (args.size() != 1) {
129    *err = Err(function->function(), "Incorrect arguments.",
130               "This function requires a single string argument.");
131    return false;
132  }
133  return args[0].VerifyTypeIs(Value::STRING, err);
134}
135
136const SourceDir& SourceDirForFunctionCall(const FunctionCallNode* function) {
137  return function->function().location().file()->dir();
138}
139
140const Label& ToolchainLabelForScope(const Scope* scope) {
141  return scope->settings()->toolchain()->label();
142}
143
144Label MakeLabelForScope(const Scope* scope,
145                        const FunctionCallNode* function,
146                        const std::string& name) {
147  const SourceDir& input_dir = SourceDirForFunctionCall(function);
148  const Label& toolchain_label = ToolchainLabelForScope(scope);
149  return Label(input_dir, name, toolchain_label.dir(), toolchain_label.name());
150}
151
152namespace functions {
153
154// assert ----------------------------------------------------------------------
155
156const char kAssert[] = "assert";
157const char kAssert_Help[] =
158    "TODO(brettw) WRITE ME";
159
160Value RunAssert(Scope* scope,
161                const FunctionCallNode* function,
162                const std::vector<Value>& args,
163                Err* err) {
164  if (args.size() != 1) {
165    *err = Err(function->function(), "Wrong number of arguments.",
166               "assert() takes one argument, "
167               "were you expecting somethig else?");
168  } else if (args[0].InterpretAsInt() == 0) {
169    *err = Err(function->function(), "Assertion failed.");
170    if (args[0].origin()) {
171      // If you do "assert(foo)" we'd ideally like to show you where foo was
172      // set, and in this case the origin of the args will tell us that.
173      // However, if you do "assert(foo && bar)" the source of the value will
174      // be the assert like, which isn't so helpful.
175      //
176      // So we try to see if the args are from the same line or not. This will
177      // break if you do "assert(\nfoo && bar)" and we may show the second line
178      // as the source, oh well. The way around this is to check to see if the
179      // origin node is inside our function call block.
180      Location origin_location = args[0].origin()->GetRange().begin();
181      if (origin_location.file() != function->function().location().file() ||
182          origin_location.line_number() !=
183              function->function().location().line_number()) {
184        err->AppendSubErr(Err(args[0].origin()->GetRange(), "",
185                              "This is where it was set."));
186      }
187    }
188  }
189  return Value();
190}
191
192// config ----------------------------------------------------------------------
193
194const char kConfig[] = "config";
195const char kConfig_Help[] =
196    "TODO(brettw) write this.";
197
198Value RunConfig(const FunctionCallNode* function,
199                const std::vector<Value>& args,
200                Scope* scope,
201                Err* err) {
202  if (!EnsureSingleStringArg(function, args, err) ||
203      !EnsureNotProcessingImport(function, scope, err))
204    return Value();
205
206  Label label(MakeLabelForScope(scope, function, args[0].string_value()));
207
208  if (g_scheduler->verbose_logging())
209    g_scheduler->Log("Generating config", label.GetUserVisibleName(true));
210
211  // Create the empty config object.
212  ItemTree* tree = &scope->settings()->build_settings()->item_tree();
213  Config* config = Config::GetConfig(scope->settings(), function->GetRange(),
214                                     label, NULL, err);
215  if (err->has_error())
216    return Value();
217
218  // Fill it.
219  const SourceDir input_dir = SourceDirForFunctionCall(function);
220  ConfigValuesGenerator gen(&config->config_values(), scope,
221                            function->function(), input_dir, err);
222  gen.Run();
223  if (err->has_error())
224    return Value();
225
226  // Mark as complete.
227  {
228    base::AutoLock lock(tree->lock());
229    tree->MarkItemDefinedLocked(scope->settings()->build_settings(), label,
230                                err);
231  }
232  return Value();
233}
234
235// declare_args ----------------------------------------------------------------
236
237const char kDeclareArgs[] = "declare_args";
238const char kDeclareArgs_Help[] =
239    "TODO(brettw) write this.";
240
241Value RunDeclareArgs(const FunctionCallNode* function,
242                     const std::vector<Value>& args,
243                     Scope* scope,
244                     Err* err) {
245  // Only allow this to be called once. We use a variable in the current scope
246  // with a name the parser will reject if the user tried to type it.
247  const char did_declare_args_var[] = "@@declared_args";
248  if (scope->GetValue(did_declare_args_var)) {
249    *err = Err(function->function(), "Duplicate call to declared_args.");
250    err->AppendSubErr(
251        Err(scope->GetValue(did_declare_args_var)->origin()->GetRange(),
252                            "See the original call."));
253    return Value();
254  }
255
256  // Find the root scope where the values will be set.
257  Scope* root = scope->mutable_containing();
258  if (!root || root->containing() || !scope->IsProcessingBuildConfig()) {
259    *err = Err(function->function(), "declare_args called incorrectly."
260        "It must be called only from the build config script and in the "
261        "root scope.");
262    return Value();
263  }
264
265  // Take all variables set in the current scope as default values and put
266  // them in the parent scope. The values in the current scope are the defaults,
267  // then we apply the external args to this list.
268  Scope::KeyValueVector values;
269  scope->GetCurrentScopeValues(&values);
270  for (size_t i = 0; i < values.size(); i++) {
271    // TODO(brettw) actually import the arguments from the command line rather
272    // than only using the defaults.
273    root->SetValue(values[i].first, values[i].second,
274                   values[i].second.origin());
275  }
276
277  scope->SetValue(did_declare_args_var, Value(function, 1), NULL);
278  return Value();
279}
280
281// import ----------------------------------------------------------------------
282
283const char kImport[] = "import";
284const char kImport_Help[] =
285    "import: Import a file into the current scope.\n"
286    "\n"
287    "  The import command loads the rules and variables resulting from\n"
288    "  executing the given file into the current scope.\n"
289    "\n"
290    "  By convention, imported files are named with a .gni extension.\n"
291    "\n"
292    "  It does not do an \"include\". The imported file is executed in a\n"
293    "  standalone environment from the caller of the import command. The\n"
294    "  results of this execution are cached for other files that import the\n"
295    "  same .gni file.\n"
296    "\n"
297    "  Note that you can not import a BUILD.gn file that's otherwise used\n"
298    "  in the build. Files must either be imported or implicitly loaded as\n"
299    "  a result of deps rules, but not both.\n"
300    "\n"
301    "  The imported file's scope will be merged with the scope at the point\n"
302    "  import was called. If there is a conflict (both the current scope and\n"
303    "  the imported file define some variable or rule with the same name)\n"
304    "  a runtime error will be thrown. Therefore, it's good practice to\n"
305    "  minimize the stuff that an imported file defines.\n"
306    "\n"
307    "Examples:\n"
308    "\n"
309    "  import(\"//build/rules/idl_compilation_rule.gni\")\n"
310    "\n"
311    "  # Looks in the current directory.\n"
312    "  import(\"my_vars.gni\")\n";
313
314Value RunImport(Scope* scope,
315                const FunctionCallNode* function,
316                const std::vector<Value>& args,
317                Err* err) {
318  if (!EnsureSingleStringArg(function, args, err) ||
319      !EnsureNotProcessingImport(function, scope, err))
320    return Value();
321
322  const SourceDir input_dir = SourceDirForFunctionCall(function);
323  SourceFile import_file =
324      input_dir.ResolveRelativeFile(args[0].string_value());
325  scope->settings()->import_manager().DoImport(import_file, function,
326                                               scope, err);
327  return Value();
328}
329
330// set_defaults ----------------------------------------------------------------
331
332const char kSetDefaults[] = "set_defaults";
333const char kSetDefaults_Help[] =
334    "TODO(brettw) write this.";
335
336Value RunSetDefaults(Scope* scope,
337                     const FunctionCallNode* function,
338                     const std::vector<Value>& args,
339                     BlockNode* block,
340                     Err* err) {
341  if (!EnsureSingleStringArg(function, args, err))
342    return Value();
343  const std::string& target_type(args[0].string_value());
344
345  // Ensure there aren't defaults already set.
346  if (scope->GetTargetDefaults(target_type)) {
347    *err = Err(function->function(),
348               "This target type defaults were already set.");
349    return Value();
350  }
351
352  // Execute the block in a new scope that has a parent of the containing
353  // scope.
354  Scope block_scope(scope);
355  if (!FillTargetBlockScope(scope, function,
356                            function->function().value().data(),
357                            block, args, &block_scope, err))
358    return Value();
359
360  // Run the block for the rule invocation.
361  block->ExecuteBlockInScope(&block_scope, err);
362  if (err->has_error())
363    return Value();
364
365  // Now copy the values set on the scope we made into the free-floating one
366  // (with no containing scope) used to hold the target defaults.
367  Scope* dest = scope->MakeTargetDefaults(target_type);
368  block_scope.NonRecursiveMergeTo(dest, function, "<SHOULD NOT FAIL>", err);
369  return Value();
370}
371
372// set_sources_assignment_filter -----------------------------------------------
373
374const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter";
375const char kSetSourcesAssignmentFilter_Help[] =
376    "TODO(brettw) write this.";
377
378Value RunSetSourcesAssignmentFilter(Scope* scope,
379                                    const FunctionCallNode* function,
380                                    const std::vector<Value>& args,
381                                    Err* err) {
382  if (args.size() != 1) {
383    *err = Err(function, "set_sources_assignment_filter takes one argument.");
384  } else {
385    scoped_ptr<PatternList> f(new PatternList);
386    f->SetFromValue(args[0], err);
387    if (!err->has_error())
388      scope->set_sources_assignment_filter(f.Pass());
389  }
390  return Value();
391}
392
393// print -----------------------------------------------------------------------
394
395const char kPrint[] = "print";
396const char kPrint_Help[] =
397    "print(...)\n"
398    "  Prints all arguments to the console separated by spaces. A newline is\n"
399    "  automatically appended to the end.\n"
400    "\n"
401    "  This function is intended for debugging. Note that build files are run\n"
402    "  in parallel so you may get interleaved prints. A buildfile may also\n"
403    "  be executed more than once in parallel in the context of different\n"
404    "  toolchains so the prints from one file may be duplicated or\n"
405    "  interleaved with itself.\n"
406    "\n"
407    "Examples:\n"
408    "  print(\"Hello world\")\n"
409    "\n"
410    "  print(sources, deps)\n";
411
412Value RunPrint(Scope* scope,
413               const FunctionCallNode* function,
414               const std::vector<Value>& args,
415               Err* err) {
416  for (size_t i = 0; i < args.size(); i++) {
417    if (i != 0)
418      std::cout << " ";
419    std::cout << args[i].ToString();
420  }
421  std::cout << std::endl;
422  return Value();
423}
424
425// -----------------------------------------------------------------------------
426
427FunctionInfo::FunctionInfo()
428    : generic_block_runner(NULL),
429      executed_block_runner(NULL),
430      no_block_runner(NULL),
431      help(NULL) {
432}
433
434FunctionInfo::FunctionInfo(GenericBlockFunction gbf, const char* in_help)
435    : generic_block_runner(gbf),
436      executed_block_runner(NULL),
437      no_block_runner(NULL),
438      help(in_help) {
439}
440
441FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf, const char* in_help)
442    : generic_block_runner(NULL),
443      executed_block_runner(ebf),
444      no_block_runner(NULL),
445      help(in_help) {
446}
447
448FunctionInfo::FunctionInfo(NoBlockFunction nbf, const char* in_help)
449    : generic_block_runner(NULL),
450      executed_block_runner(NULL),
451      no_block_runner(nbf),
452      help(in_help) {
453}
454
455// Setup the function map via a static initializer. We use this because it
456// avoids race conditions without having to do some global setup function or
457// locking-heavy singleton checks at runtime. In practice, we always need this
458// before we can do anything interesting, so it's OK to wait for the
459// initializer.
460struct FunctionInfoInitializer {
461  FunctionInfoMap map;
462
463  FunctionInfoInitializer() {
464    #define INSERT_FUNCTION(command) \
465        map[k##command] = FunctionInfo(&Run##command, k##command##_Help);
466
467    INSERT_FUNCTION(Assert)
468    INSERT_FUNCTION(Component)
469    INSERT_FUNCTION(Config)
470    INSERT_FUNCTION(Copy)
471    INSERT_FUNCTION(Custom)
472    INSERT_FUNCTION(DeclareArgs)
473    INSERT_FUNCTION(ExecScript)
474    INSERT_FUNCTION(Executable)
475    INSERT_FUNCTION(Group)
476    INSERT_FUNCTION(Import)
477    INSERT_FUNCTION(Print)
478    INSERT_FUNCTION(ProcessFileTemplate)
479    INSERT_FUNCTION(ReadFile)
480    INSERT_FUNCTION(SetDefaults)
481    INSERT_FUNCTION(SetDefaultToolchain)
482    INSERT_FUNCTION(SetSourcesAssignmentFilter)
483    INSERT_FUNCTION(SharedLibrary)
484    INSERT_FUNCTION(StaticLibrary)
485    INSERT_FUNCTION(Template)
486    INSERT_FUNCTION(Test)
487    INSERT_FUNCTION(Tool)
488    INSERT_FUNCTION(Toolchain)
489    INSERT_FUNCTION(WriteFile)
490
491    #undef INSERT_FUNCTION
492  }
493};
494const FunctionInfoInitializer function_info;
495
496const FunctionInfoMap& GetFunctions() {
497  return function_info.map;
498}
499
500Value RunFunction(Scope* scope,
501                  const FunctionCallNode* function,
502                  const std::vector<Value>& args,
503                  BlockNode* block,
504                  Err* err) {
505  const Token& name = function->function();
506
507  const FunctionInfoMap& function_map = GetFunctions();
508  FunctionInfoMap::const_iterator found_function =
509      function_map.find(name.value());
510  if (found_function == function_map.end()) {
511    // No build-in function matching this, check for a template.
512    const FunctionCallNode* rule =
513        scope->GetTemplate(function->function().value().as_string());
514    if (rule)
515      return RunTemplateInvocation(scope, function, args, block, rule, err);
516
517    *err = Err(name, "Unknown function.");
518    return Value();
519  }
520
521  if (found_function->second.generic_block_runner) {
522    if (!block) {
523      FillNeedsBlockError(function, err);
524      return Value();
525    }
526    return found_function->second.generic_block_runner(
527        scope, function, args, block, err);
528  }
529
530  if (found_function->second.executed_block_runner) {
531    if (!block) {
532      FillNeedsBlockError(function, err);
533      return Value();
534    }
535
536    Scope block_scope(scope);
537    block->ExecuteBlockInScope(&block_scope, err);
538    if (err->has_error())
539      return Value();
540    return found_function->second.executed_block_runner(
541        function, args, &block_scope, err);
542  }
543
544  // Otherwise it's a no-block function.
545  return found_function->second.no_block_runner(scope, function, args, err);
546}
547
548}  // namespace functions
549