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/template.h"
     10 #include "tools/gn/value.h"
     11 
     12 namespace functions {
     13 
     14 const char kTemplate[] = "template";
     15 const char kTemplate_HelpShort[] =
     16     "template: Define a template rule.";
     17 const char kTemplate_Help[] =
     18     "template: Define a template rule.\n"
     19     "\n"
     20     "  A template defines a custom name that acts like a function. It\n"
     21     "  provides a way to add to the built-in target types.\n"
     22     "\n"
     23     "  The template() function is used to declare a template. To invoke the\n"
     24     "  template, just use the name of the template like any other target\n"
     25     "  type.\n"
     26     "\n"
     27     "  Often you will want to declare your template in a special file that\n"
     28     "  other files will import (see \"gn help import\") so your template\n"
     29     "  rule can be shared across build files.\n"
     30     "\n"
     31     "More details:\n"
     32     "\n"
     33     "  When you call template() it creates a closure around all variables\n"
     34     "  currently in scope with the code in the template block. When the\n"
     35     "  template is invoked, the closure will be executed.\n"
     36     "\n"
     37     "  When the template is invoked, the code in the caller is executed and\n"
     38     "  passed to the template code as an implicit \"invoker\" variable. The\n"
     39     "  template uses this to read state out of the invoking code.\n"
     40     "\n"
     41     "  One thing explicitly excluded from the closure is the \"current\n"
     42     "  directory\" against which relative file names are resolved. The\n"
     43     "  current directory will be that of the invoking code, since typically\n"
     44     "  that code specifies the file names. This means all files internal\n"
     45     "  to the template should use absolute names.\n"
     46     "\n"
     47     "Target naming:\n"
     48     "\n"
     49     "  Your template should almost always define a built-in target with the\n"
     50     "  name the template invoker specified. For example, if you have an IDL\n"
     51     "  template and somebody does:\n"
     52     "    idl(\"foo\") {...\n"
     53     "  you will normally want this to expand to something defining a\n"
     54     "  source_set or static_library named \"foo\" (among other things you may\n"
     55     "  need). This way, when another target specifies a dependency on\n"
     56     "  \"foo\", the static_library or source_set will be linked.\n"
     57     "\n"
     58     "  It is also important that any other targets your template expands to\n"
     59     "  have globally unique names, or you will get collisions.\n"
     60     "\n"
     61     "  Access the invoking name in your template via the implicit\n"
     62     "  \"target_name\" variable. This should also be the basis of how other\n"
     63     "  targets that a template expands to to ensure uniquness.\n"
     64     "\n"
     65     "  A typical example would be a template that defines an action to\n"
     66     "  generate some source files, and a source_set to compile that source.\n"
     67     "  Your template would name the source_set \"target_name\" because\n"
     68     "  that's what you want external targets to depend on to link your code.\n"
     69     "  And you would name the action something like \"${target_name}_action\"\n"
     70     "  to make it unique. The source set would have a dependency on the\n"
     71     "  action to make it run.\n"
     72     "\n"
     73     "Example of defining a template:\n"
     74     "\n"
     75     "  template(\"my_idl\") {\n"
     76     "    # Be nice and help callers debug problems by checking that the\n"
     77     "    # variables the template requires are defined. This gives a nice\n"
     78     "    # message rather than giving the user an error about an\n"
     79     "    # undefined variable in the file defining the template\n"
     80     "    #\n"
     81     "    # You can also use defined() to give default values to variables\n"
     82     "    # unspecified by the invoker.\n"
     83     "    assert(defined(invoker.sources),\n"
     84     "           \"Need sources in $target_name listing the idl files.\")\n"
     85     "\n"
     86     "    # Name of the intermediate target that does the code gen. This must\n"
     87     "    # incorporate the target name so it's unique across template\n"
     88     "    # instantiations.\n"
     89     "    code_gen_target_name = target_name + \"_code_gen\"\n"
     90     "\n"
     91     "    # Intermediate target to convert IDL to C source. Note that the name\n"
     92     "    # is based on the name the invoker of the template specified. This\n"
     93     "    # way, each time the template is invoked we get a unique\n"
     94     "    # intermediate action name (since all target names are in the global\n"
     95     "    # scope).\n"
     96     "    action_foreach(code_gen_target_name) {\n"
     97     "      # Access the scope defined by the invoker via the implicit\n"
     98     "      # \"invoker\" variable.\n"
     99     "      sources = invoker.sources\n"
    100     "\n"
    101     "      # Note that we need an absolute path for our script file name.\n"
    102     "      # The current directory when executing this code will be that of\n"
    103     "      # the invoker (this is why we can use the \"sources\" directly\n"
    104     "      # above without having to rebase all of the paths). But if we need\n"
    105     "      # to reference a script relative to the template file, we'll need\n"
    106     "      # to use an absolute path instead.\n"
    107     "      script = \"//tools/idl/idl_code_generator.py\"\n"
    108     "\n"
    109     "      # Tell GN how to expand output names given the sources.\n"
    110     "      # See \"gn help source_expansion\" for more.\n"
    111     "      outputs = [ \"$target_gen_dir/{{source_name_part}}.cc\",\n"
    112     "                  \"$target_gen_dir/{{source_name_part}}.h\" ]\n"
    113     "    }\n"
    114     "\n"
    115     "    # Name the source set the same as the template invocation so\n"
    116     "    # instancing this template produces something that other targets\n"
    117     "    # can link to in their deps.\n"
    118     "    source_set(target_name) {\n"
    119     "      # Generates the list of sources, we get these from the\n"
    120     "      # action_foreach above.\n"
    121     "      sources = get_target_outputs(\":$code_gen_target_name\")\n"
    122     "\n"
    123     "      # This target depends on the files produced by the above code gen\n"
    124     "      # target.\n"
    125     "      deps = [ \":$code_gen_target_name\" ]\n"
    126     "    }\n"
    127     "  }\n"
    128     "\n"
    129     "Example of invoking the resulting template:\n"
    130     "\n"
    131     "  # This calls the template code above, defining target_name to be\n"
    132     "  # \"foo_idl_files\" and \"invoker\" to be the set of stuff defined in\n"
    133     "  # the curly brackets.\n"
    134     "  my_idl(\"foo_idl_files\") {\n"
    135     "    # Goes into the template as \"invoker.sources\".\n"
    136     "    sources = [ \"foo.idl\", \"bar.idl\" ]\n"
    137     "  }\n"
    138     "\n"
    139     "  # Here is a target that depends on our template.\n"
    140     "  executable(\"my_exe\") {\n"
    141     "    # Depend on the name we gave the template call above. Internally,\n"
    142     "    # this will produce a dependency from executable to the source_set\n"
    143     "    # inside the template (since it has this name), which will in turn\n"
    144     "    # depend on the code gen action.\n"
    145     "    deps = [ \":foo_idl_files\" ]\n"
    146     "  }\n";
    147 
    148 Value RunTemplate(Scope* scope,
    149                   const FunctionCallNode* function,
    150                   const std::vector<Value>& args,
    151                   BlockNode* block,
    152                   Err* err) {
    153   // TODO(brettw) determine if the function is built-in and throw an error if
    154   // it is.
    155   if (args.size() != 1) {
    156     *err = Err(function->function(),
    157                "Need exactly one string arg to template.");
    158     return Value();
    159   }
    160   if (!args[0].VerifyTypeIs(Value::STRING, err))
    161     return Value();
    162   std::string template_name = args[0].string_value();
    163 
    164   const Template* existing_template = scope->GetTemplate(template_name);
    165   if (existing_template) {
    166     *err = Err(function, "Duplicate template definition.",
    167                "A template with this name was already defined.");
    168     err->AppendSubErr(Err(existing_template->GetDefinitionRange(),
    169                           "Previous definition."));
    170     return Value();
    171   }
    172 
    173   scope->AddTemplate(template_name, new Template(scope, function));
    174   return Value();
    175 }
    176 
    177 }  // namespace functions
    178