• 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/parse_tree.h"
8 #include "tools/gn/scope.h"
9 #include "tools/gn/value.h"
10 
11 namespace functions {
12 
13 const char kTemplate[] = "template";
14 const char kTemplate_Help[] =
15     "template: Define a template rule.\n"
16     "\n"
17     "  A template defines a custom rule name that can expand to one or more\n"
18     "  other rules (typically built-in rules like \"static_library\"). It\n"
19     "  provides a way to add to the built-in target types.\n"
20     "\n"
21     "  The template() function is used to declare a template. To invoke the\n"
22     "  template, just use the name of the template like any other target\n"
23     "  type.\n"
24     "\n"
25     "More details:\n"
26     "\n"
27     "  Semantically, the code in the template is stored. When a function\n"
28     "  with the name is called, the block following the invocation is\n"
29     "  executed, *then* your template code is executed. So if the invocation\n"
30     "  sets the |source| variable, for example, that variable will be\n"
31     "  accessible to you when the template code runs.\n"
32     "\n"
33     "  The template() function does not generate a closure, so the\n"
34     "  environment, current directory, etc. will all be the same as from\n"
35     "  the template is invoked.\n"
36     "\n"
37     "Hints:\n"
38     "\n"
39     "  If your template expands to more than one target, be sure to name\n"
40     "  the intermediate targets based on the name of the template\n"
41     "  instantiation so that the names are globally unique. The variable\n"
42     "  |target_name| will be this name.\n"
43     "\n"
44     "  Likewise, you will always want to generate a target in your template\n"
45     "  with the original |target_name|. Otherwise, invoking your template\n"
46     "  will not actually generate a node in the dependency graph that other\n"
47     "  targets can reference.\n"
48     "\n"
49     "  Often you will want to declare your template in a special file that\n"
50     "  other files will import (see \"gn help import\") so your template\n"
51     "  rule can be shared across build files.\n"
52     "\n"
53     "Example of defining a template:\n"
54     "\n"
55     "  template(\"my_idl\") {\n"
56     "    # Maps input files to output files, used in both targets below.\n"
57     "    filter = [ \"$target_gen_dir/{{source_name_part}}.cc\",\n"
58     "               \"$target_gen_dir/{{source_name_part}}.h\" ]\n"
59     "\n"
60     "    # Intermediate target to compile IDL to C source.\n"
61     "    custom(\"${target_name}_code_gen\") {\n"
62     "      # The |sources| will be inherited from the surrounding scope so\n"
63     "      # we don't need to redefine it.\n"
64     "      script = \"foo.py\"\n"
65     "      outputs = filter  # Variable from above.\n"
66     "    }\n"
67     "\n"
68     "    # Name the static library the same as the template invocation so\n"
69     "    # instanting this template produces something that other targets\n"
70     "    # can link to in their deps.\n"
71     "    static_library(target_name) {\n"
72     "      # Generates the list of sources.\n"
73     "      # See \"gn help process_file_template\"\n"
74     "      sources = process_file_template(sources, filter)\n"
75     "    }\n"
76     "  }\n"
77     "\n"
78     "Example of invoking the resulting template:\n"
79     "\n"
80     "  my_idl(\"foo_idl_files\") {\n"
81     "    sources = [ \"foo.idl\", \"bar.idl\" ]\n"
82     "  }\n";
83 
RunTemplate(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,BlockNode * block,Err * err)84 Value RunTemplate(Scope* scope,
85                   const FunctionCallNode* function,
86                   const std::vector<Value>& args,
87                   BlockNode* block,
88                   Err* err) {
89   // TODO(brettw) determine if the function is built-in and throw an error if
90   // it is.
91   if (args.size() != 1) {
92     *err = Err(function->function(),
93                "Need exactly one string arg to template.");
94     return Value();
95   }
96   if (!args[0].VerifyTypeIs(Value::STRING, err))
97     return Value();
98   std::string template_name = args[0].string_value();
99 
100   const FunctionCallNode* existing_template = scope->GetTemplate(template_name);
101   if (existing_template) {
102     *err = Err(function, "Duplicate template definition.",
103                "A template with this name was already defined.");
104     err->AppendSubErr(Err(existing_template->function(),
105                           "Previous definition."));
106     return Value();
107   }
108 
109   scope->AddTemplate(template_name, function);
110   return Value();
111 }
112 
113 }  // namespace functions
114