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/err.h"
6#include "tools/gn/functions.h"
7#include "tools/gn/parse_tree.h"
8#include "tools/gn/scope.h"
9
10namespace functions {
11
12const char kSetDefaults[] = "set_defaults";
13const char kSetDefaults_Help[] =
14    "set_defaults: Set default values for a target type.\n"
15    "\n"
16    "  set_defaults(<target_type_name>) { <values...> }\n"
17    "\n"
18    "  Sets the default values for a given target type. Whenever\n"
19    "  target_type_name is seen in the future, the values specified in\n"
20    "  set_default's block will be copied into the current scope.\n"
21    "\n"
22    "  When the target type is used, the variable copying is very strict.\n"
23    "  If a variable with that name is already in scope, the build will fail\n"
24    "  with an error.\n"
25    "\n"
26    "  set_defaults can be used for built-in target types (\"executable\",\n"
27    "  \"shared_library\", etc.) and custom ones defined via the \"template\"\n"
28    "  command.\n"
29    "\n"
30    "Example:\n"
31    "  set_defaults(\"static_library\") {\n"
32    "    configs = [ \"//tools/mything:settings\" ]\n"
33    "  }\n"
34    "\n"
35    "  static_library(\"mylib\")\n"
36    "    # The configs will be auto-populated as above. You can remove it if\n"
37    "    # you don't want the default for a particular default:\n"
38    "    configs -= \"//tools/mything:setgings\"\n"
39    "  }\n";
40
41Value RunSetDefaults(Scope* scope,
42                     const FunctionCallNode* function,
43                     const std::vector<Value>& args,
44                     BlockNode* block,
45                     Err* err) {
46  if (!EnsureSingleStringArg(function, args, err))
47    return Value();
48  const std::string& target_type(args[0].string_value());
49
50  // Ensure there aren't defaults already set.
51  //
52  // It might be nice to allow multiple calls set mutate the defaults. The
53  // main case for this is where some local portions of the code want
54  // additional defaults they specify in an imported file.
55  //
56  // Currently, we don't allow imports to clobber anything, so this wouldn't
57  // work. Additionally, allowing this would be undesirable since we don't
58  // want multiple imports to each try to set defaults, since it might look
59  // like the defaults are modified by each one in sequence, while in fact
60  // imports would always clobber previous values and it would be confusing.
61  //
62  // If we wanted this, the solution would be to allow imports to overwrite
63  // target defaults set up by the default build config only. That way there
64  // are no ordering issues, but this would be more work.
65  if (scope->GetTargetDefaults(target_type)) {
66    *err = Err(function->function(),
67               "This target type defaults were already set.");
68    return Value();
69  }
70
71  if (!block) {
72    FillNeedsBlockError(function, err);
73    return Value();
74  }
75
76  // Run the block for the rule invocation.
77  Scope block_scope(scope);
78  block->ExecuteBlockInScope(&block_scope, err);
79  if (err->has_error())
80    return Value();
81
82  // Now copy the values set on the scope we made into the free-floating one
83  // (with no containing scope) used to hold the target defaults.
84  Scope* dest = scope->MakeTargetDefaults(target_type);
85  block_scope.NonRecursiveMergeTo(dest, function, "<SHOULD NOT FAIL>", err);
86  return Value();
87}
88
89}  // namespace functions
90