Home | History | Annotate | Download | only in gn
      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 
     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