Chromium Code Reviews| Index: tools/gn/function_template.cc |
| diff --git a/tools/gn/function_template.cc b/tools/gn/function_template.cc |
| index 6136f41ec36fab722457bcc6b978b160e1ce7b38..57aadc1a629b843aa843319db98990f953a592b8 100644 |
| --- a/tools/gn/function_template.cc |
| +++ b/tools/gn/function_template.cc |
| @@ -15,148 +15,143 @@ const char kTemplate[] = "template"; |
| const char kTemplate_HelpShort[] = |
| "template: Define a template rule."; |
| const char kTemplate_Help[] = |
| - "template: Define a template rule.\n" |
| - "\n" |
| - " A template defines a custom name that acts like a function. It\n" |
| - " provides a way to add to the built-in target types.\n" |
| - "\n" |
| - " The template() function is used to declare a template. To invoke the\n" |
| - " template, just use the name of the template like any other target\n" |
| - " type.\n" |
| - "\n" |
| - " Often you will want to declare your template in a special file that\n" |
| - " other files will import (see \"gn help import\") so your template\n" |
| - " rule can be shared across build files.\n" |
| - "\n" |
| - "Variables and templates:\n" |
| - "\n" |
| - " When you call template() it creates a closure around all variables\n" |
| - " currently in scope with the code in the template block. When the\n" |
| - " template is invoked, the closure will be executed.\n" |
| - "\n" |
| - " When the template is invoked, the code in the caller is executed and\n" |
| - " passed to the template code as an implicit \"invoker\" variable. The\n" |
| - " template uses this to read state out of the invoking code.\n" |
| - "\n" |
| - " One thing explicitly excluded from the closure is the \"current\n" |
| - " directory\" against which relative file names are resolved. The\n" |
| - " current directory will be that of the invoking code, since typically\n" |
| - " that code specifies the file names. This means all files internal\n" |
| - " to the template should use absolute names.\n" |
| - "\n" |
| - " A template will typically forward some or all variables from the\n" |
| - " invoking scope to a target that it defines. Often, such variables\n" |
| - " might be optional. Use the pattern:\n" |
| - "\n" |
| - " if (defined(invoker.deps)) {\n" |
| - " deps = invoker.deps\n" |
| - " }\n" |
| - "\n" |
| - " The function forward_variables_from() provides a shortcut to forward\n" |
| - " one or more or possibly all variables in this manner:\n" |
| - "\n" |
| - " forward_variables_from(invoker, [\"deps\", \"public_deps\"])\n" |
| - "\n" |
| - "Target naming:\n" |
| - "\n" |
| - " Your template should almost always define a built-in target with the\n" |
| - " name the template invoker specified. For example, if you have an IDL\n" |
| - " template and somebody does:\n" |
| - " idl(\"foo\") {...\n" |
| - " you will normally want this to expand to something defining a\n" |
| - " source_set or static_library named \"foo\" (among other things you may\n" |
| - " need). This way, when another target specifies a dependency on\n" |
| - " \"foo\", the static_library or source_set will be linked.\n" |
| - "\n" |
| - " It is also important that any other targets your template expands to\n" |
| - " have globally unique names, or you will get collisions.\n" |
| - "\n" |
| - " Access the invoking name in your template via the implicit\n" |
| - " \"target_name\" variable. This should also be the basis for how other\n" |
| - " targets that a template expands to ensure uniqueness.\n" |
| - "\n" |
| - " A typical example would be a template that defines an action to\n" |
| - " generate some source files, and a source_set to compile that source.\n" |
| - " Your template would name the source_set \"target_name\" because\n" |
| - " that's what you want external targets to depend on to link your code.\n" |
| - " And you would name the action something like \"${target_name}_action\"\n" |
| - " to make it unique. The source set would have a dependency on the\n" |
| - " action to make it run.\n" |
| - "\n" |
| - "Example of defining a template:\n" |
| - "\n" |
| - " template(\"my_idl\") {\n" |
| - " # Be nice and help callers debug problems by checking that the\n" |
| - " # variables the template requires are defined. This gives a nice\n" |
| - " # message rather than giving the user an error about an\n" |
| - " # undefined variable in the file defining the template\n" |
| - " #\n" |
| - " # You can also use defined() to give default values to variables\n" |
| - " # unspecified by the invoker.\n" |
| - " assert(defined(invoker.sources),\n" |
| - " \"Need sources in $target_name listing the idl files.\")\n" |
| - "\n" |
| - " # Name of the intermediate target that does the code gen. This must\n" |
| - " # incorporate the target name so it's unique across template\n" |
| - " # instantiations.\n" |
| - " code_gen_target_name = target_name + \"_code_gen\"\n" |
| - "\n" |
| - " # Intermediate target to convert IDL to C source. Note that the name\n" |
| - " # is based on the name the invoker of the template specified. This\n" |
| - " # way, each time the template is invoked we get a unique\n" |
| - " # intermediate action name (since all target names are in the global\n" |
| - " # scope).\n" |
| - " action_foreach(code_gen_target_name) {\n" |
| - " # Access the scope defined by the invoker via the implicit\n" |
| - " # \"invoker\" variable.\n" |
| - " sources = invoker.sources\n" |
| - "\n" |
| - " # Note that we need an absolute path for our script file name.\n" |
| - " # The current directory when executing this code will be that of\n" |
| - " # the invoker (this is why we can use the \"sources\" directly\n" |
| - " # above without having to rebase all of the paths). But if we need\n" |
| - " # to reference a script relative to the template file, we'll need\n" |
| - " # to use an absolute path instead.\n" |
| - " script = \"//tools/idl/idl_code_generator.py\"\n" |
| - "\n" |
| - " # Tell GN how to expand output names given the sources.\n" |
| - " # See \"gn help source_expansion\" for more.\n" |
| - " outputs = [ \"$target_gen_dir/{{source_name_part}}.cc\",\n" |
| - " \"$target_gen_dir/{{source_name_part}}.h\" ]\n" |
| - " }\n" |
| - "\n" |
| - " # Name the source set the same as the template invocation so\n" |
| - " # instancing this template produces something that other targets\n" |
| - " # can link to in their deps.\n" |
| - " source_set(target_name) {\n" |
| - " # Generates the list of sources, we get these from the\n" |
| - " # action_foreach above.\n" |
| - " sources = get_target_outputs(\":$code_gen_target_name\")\n" |
| - "\n" |
| - " # This target depends on the files produced by the above code gen\n" |
| - " # target.\n" |
| - " deps = [ \":$code_gen_target_name\" ]\n" |
| - " }\n" |
| - " }\n" |
| - "\n" |
| - "Example of invoking the resulting template:\n" |
| - "\n" |
| - " # This calls the template code above, defining target_name to be\n" |
| - " # \"foo_idl_files\" and \"invoker\" to be the set of stuff defined in\n" |
| - " # the curly brackets.\n" |
| - " my_idl(\"foo_idl_files\") {\n" |
| - " # Goes into the template as \"invoker.sources\".\n" |
| - " sources = [ \"foo.idl\", \"bar.idl\" ]\n" |
| - " }\n" |
| - "\n" |
| - " # Here is a target that depends on our template.\n" |
| - " executable(\"my_exe\") {\n" |
| - " # Depend on the name we gave the template call above. Internally,\n" |
| - " # this will produce a dependency from executable to the source_set\n" |
| - " # inside the template (since it has this name), which will in turn\n" |
| - " # depend on the code gen action.\n" |
| - " deps = [ \":foo_idl_files\" ]\n" |
| - " }\n"; |
| + R"(template: Define a template rule. |
| + |
| + A template defines a custom name that acts like a function. It provides a way |
| + to add to the built-in target types. |
| + |
| + The template() function is used to declare a template. To invoke the |
| + template, just use the name of the template like any other target type. |
| + |
| + Often you will want to declare your template in a special file that other |
| + files will import (see "gn help import") so your template rule can be shared |
| + across build files. |
| + |
| +Variables and templates: |
| + |
| + When you call template() it creates a closure around all variables currently |
| + in scope with the code in the template block. When the template is invoked, |
| + the closure will be executed. |
| + |
| + When the template is invoked, the code in the caller is executed and passed |
| + to the template code as an implicit "invoker" variable. The template uses |
| + this to read state out of the invoking code. |
| + |
| + One thing explicitly excluded from the closure is the "current directory" |
| + against which relative file names are resolved. The current directory will be |
| + that of the invoking code, since typically that code specifies the file |
| + names. This means all files internal to the template should use absolute |
| + names. |
| + |
| + A template will typically forward some or all variables from the invoking |
| + scope to a target that it defines. Often, such variables might be optional. |
| + Use the pattern: |
| + |
| + if (defined(invoker.deps)) { |
| + deps = invoker.deps |
| + } |
| + |
| + The function forward_variables_from() provides a shortcut to forward one or |
| + more or possibly all variables in this manner: |
| + |
| + forward_variables_from(invoker, ["deps", "public_deps"]) |
| + |
| +Target naming |
| + |
| + Your template should almost always define a built-in target with the name the |
| + template invoker specified. For example, if you have an IDL template and |
| + somebody does: |
| + idl("foo") {... |
| + you will normally want this to expand to something defining a source_set or |
| + static_library named "foo" (among other things you may need). This way, when |
| + another target specifies a dependency on "foo", the static_library or |
| + source_set will be linked. |
| + |
| + It is also important that any other targets your template expands to have |
| + unique names, or you will get collisions. |
| + |
| + Access the invoking name in your template via the implicit "target_name" |
| + variable. This should also be the basis for how other targets that a template |
| + expands to ensure uniqueness. |
| + |
| + A typical example would be a template that defines an action to generate some |
| + source files, and a source_set to compile that source. Your template would |
| + name the source_set "target_name" because that's what you want external |
| + targets to depend on to link your code. And you would name the action |
| + something like "${target_name}_action" to make it unique. The source set |
| + would have a dependency on the action to make it run. |
| + |
| +Example of defining a template |
| + |
| + template("my_idl") { |
| + # Be nice and help callers debug problems by checking that the variables |
| + # the template requires are defined. This gives a nice message rather than |
| + # giving the user an error about an undefined variable in the file defining |
| + # the template |
| + # |
| + # You can also use defined() to give default values to variables |
| + # unspecified by the invoker. |
| + assert(defined(invoker.sources), |
| + "Need sources in $target_name listing the idl files.") |
| + |
| + # Name of the intermediate target that does the code gen. This must |
| + # incorporate the target name so it's unique across template |
| + # instantiations. |
| + code_gen_target_name = target_name + "_code_gen" |
| + |
| + # Intermediate target to convert IDL to C source. Note that the name is |
| + # based on the name the invoker of the template specified. This way, each |
| + # time the template is invoked we get a unique intermediate action name |
| + # (since all target names are in the global scope). |
| + action_foreach(code_gen_target_name) { |
| + # Access the scope defined by the invoker via the implicit "invoker" |
| + # variable. |
| + sources = invoker.sources |
| + |
| + # Note that we need an absolute path for our script file name. The |
| + # current directory when executing this code will be that of the invoker |
| + # (this is why we can use the "sources" directly above without having to |
| + # rebase all of the paths). But if we need to reference a script relative |
| + # to the template file, we'll need to use an absolute path instead. |
| + script = "//tools/idl/idl_code_generator.py" |
| + |
| + # Tell GN how to expand output names given the sources. |
| + # See "gn help source_expansion" for more. |
| + outputs = [ "$target_gen_dir/{{source_name_part}}.cc", |
| + "$target_gen_dir/{{source_name_part}}.h" ] |
| + } |
| + |
| + # Name the source set the same as the template invocation so instancing |
| + # this template produces something that other targets can link to in their |
| + # deps. |
| + source_set(target_name) { |
| + # Generates the list of sources, we get these from the action_foreach |
| + # above. |
| + sources = get_target_outputs(":$code_gen_target_name") |
| + |
| + # This target depends on the files produced by the above code gen target. |
| + deps = [ ":$code_gen_target_name" ] |
| + } |
| + } |
| + |
| +Example of invoking the resulting template |
| + |
| + # This calls the template code above, defining target_name to be |
| + # "foo_idl_files" and "invoker" to be the set of stuff defined in the curly |
| + # brackets. |
| + my_idl("foo_idl_files") { |
| + # Goes into the template as "invoker.sources". |
| + sources = [ "foo.idl", "bar.idl" ] |
| + } |
| + |
| + # Here is a target that depends on our template. |
| + executable("my_exe") { |
| + # Depend on the name we gave the template call above. Internally, this will |
| + # produce a dependency from executable to the source_set inside the |
| + # template (since it has this name), which will in turn depend on the code |
| + # gen action. |
| + deps = [ ":foo_idl_files" ] |
| + })"; |
|
scottmg
2016/11/08 00:30:30
here
|
| Value RunTemplate(Scope* scope, |
| const FunctionCallNode* function, |