| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "tools/gn/functions.h" | 5 #include "tools/gn/functions.h" |
| 6 | 6 |
| 7 #include "tools/gn/parse_tree.h" | 7 #include "tools/gn/parse_tree.h" |
| 8 #include "tools/gn/scope.h" | 8 #include "tools/gn/scope.h" |
| 9 #include "tools/gn/template.h" | 9 #include "tools/gn/template.h" |
| 10 #include "tools/gn/value.h" | 10 #include "tools/gn/value.h" |
| 11 | 11 |
| 12 namespace functions { | 12 namespace functions { |
| 13 | 13 |
| 14 const char kTemplate[] = "template"; | 14 const char kTemplate[] = "template"; |
| 15 const char kTemplate_HelpShort[] = | 15 const char kTemplate_HelpShort[] = |
| 16 "template: Define a template rule."; | 16 "template: Define a template rule."; |
| 17 const char kTemplate_Help[] = | 17 const char kTemplate_Help[] = |
| 18 "template: Define a template rule.\n" | 18 R"(template: Define a template rule. |
| 19 "\n" | 19 |
| 20 " A template defines a custom name that acts like a function. It\n" | 20 A template defines a custom name that acts like a function. It provides a way |
| 21 " provides a way to add to the built-in target types.\n" | 21 to add to the built-in target types. |
| 22 "\n" | 22 |
| 23 " The template() function is used to declare a template. To invoke the\n" | 23 The template() function is used to declare a template. To invoke the |
| 24 " template, just use the name of the template like any other target\n" | 24 template, just use the name of the template like any other target type. |
| 25 " type.\n" | 25 |
| 26 "\n" | 26 Often you will want to declare your template in a special file that other |
| 27 " Often you will want to declare your template in a special file that\n" | 27 files will import (see "gn help import") so your template rule can be shared |
| 28 " other files will import (see \"gn help import\") so your template\n" | 28 across build files. |
| 29 " rule can be shared across build files.\n" | 29 |
| 30 "\n" | 30 Variables and templates: |
| 31 "Variables and templates:\n" | 31 |
| 32 "\n" | 32 When you call template() it creates a closure around all variables currently |
| 33 " When you call template() it creates a closure around all variables\n" | 33 in scope with the code in the template block. When the template is invoked, |
| 34 " currently in scope with the code in the template block. When the\n" | 34 the closure will be executed. |
| 35 " template is invoked, the closure will be executed.\n" | 35 |
| 36 "\n" | 36 When the template is invoked, the code in the caller is executed and passed |
| 37 " When the template is invoked, the code in the caller is executed and\n" | 37 to the template code as an implicit "invoker" variable. The template uses |
| 38 " passed to the template code as an implicit \"invoker\" variable. The\n" | 38 this to read state out of the invoking code. |
| 39 " template uses this to read state out of the invoking code.\n" | 39 |
| 40 "\n" | 40 One thing explicitly excluded from the closure is the "current directory" |
| 41 " One thing explicitly excluded from the closure is the \"current\n" | 41 against which relative file names are resolved. The current directory will be |
| 42 " directory\" against which relative file names are resolved. The\n" | 42 that of the invoking code, since typically that code specifies the file |
| 43 " current directory will be that of the invoking code, since typically\n" | 43 names. This means all files internal to the template should use absolute |
| 44 " that code specifies the file names. This means all files internal\n" | 44 names. |
| 45 " to the template should use absolute names.\n" | 45 |
| 46 "\n" | 46 A template will typically forward some or all variables from the invoking |
| 47 " A template will typically forward some or all variables from the\n" | 47 scope to a target that it defines. Often, such variables might be optional. |
| 48 " invoking scope to a target that it defines. Often, such variables\n" | 48 Use the pattern: |
| 49 " might be optional. Use the pattern:\n" | 49 |
| 50 "\n" | 50 if (defined(invoker.deps)) { |
| 51 " if (defined(invoker.deps)) {\n" | 51 deps = invoker.deps |
| 52 " deps = invoker.deps\n" | 52 } |
| 53 " }\n" | 53 |
| 54 "\n" | 54 The function forward_variables_from() provides a shortcut to forward one or |
| 55 " The function forward_variables_from() provides a shortcut to forward\n" | 55 more or possibly all variables in this manner: |
| 56 " one or more or possibly all variables in this manner:\n" | 56 |
| 57 "\n" | 57 forward_variables_from(invoker, ["deps", "public_deps"]) |
| 58 " forward_variables_from(invoker, [\"deps\", \"public_deps\"])\n" | 58 |
| 59 "\n" | 59 Target naming |
| 60 "Target naming:\n" | 60 |
| 61 "\n" | 61 Your template should almost always define a built-in target with the name the |
| 62 " Your template should almost always define a built-in target with the\n" | 62 template invoker specified. For example, if you have an IDL template and |
| 63 " name the template invoker specified. For example, if you have an IDL\n" | 63 somebody does: |
| 64 " template and somebody does:\n" | 64 idl("foo") {... |
| 65 " idl(\"foo\") {...\n" | 65 you will normally want this to expand to something defining a source_set or |
| 66 " you will normally want this to expand to something defining a\n" | 66 static_library named "foo" (among other things you may need). This way, when |
| 67 " source_set or static_library named \"foo\" (among other things you may\n" | 67 another target specifies a dependency on "foo", the static_library or |
| 68 " need). This way, when another target specifies a dependency on\n" | 68 source_set will be linked. |
| 69 " \"foo\", the static_library or source_set will be linked.\n" | 69 |
| 70 "\n" | 70 It is also important that any other targets your template expands to have |
| 71 " It is also important that any other targets your template expands to\n" | 71 unique names, or you will get collisions. |
| 72 " have globally unique names, or you will get collisions.\n" | 72 |
| 73 "\n" | 73 Access the invoking name in your template via the implicit "target_name" |
| 74 " Access the invoking name in your template via the implicit\n" | 74 variable. This should also be the basis for how other targets that a template |
| 75 " \"target_name\" variable. This should also be the basis for how other\n" | 75 expands to ensure uniqueness. |
| 76 " targets that a template expands to ensure uniqueness.\n" | 76 |
| 77 "\n" | 77 A typical example would be a template that defines an action to generate some |
| 78 " A typical example would be a template that defines an action to\n" | 78 source files, and a source_set to compile that source. Your template would |
| 79 " generate some source files, and a source_set to compile that source.\n" | 79 name the source_set "target_name" because that's what you want external |
| 80 " Your template would name the source_set \"target_name\" because\n" | 80 targets to depend on to link your code. And you would name the action |
| 81 " that's what you want external targets to depend on to link your code.\n" | 81 something like "${target_name}_action" to make it unique. The source set |
| 82 " And you would name the action something like \"${target_name}_action\"\n" | 82 would have a dependency on the action to make it run. |
| 83 " to make it unique. The source set would have a dependency on the\n" | 83 |
| 84 " action to make it run.\n" | 84 Example of defining a template |
| 85 "\n" | 85 |
| 86 "Example of defining a template:\n" | 86 template("my_idl") { |
| 87 "\n" | 87 # Be nice and help callers debug problems by checking that the variables |
| 88 " template(\"my_idl\") {\n" | 88 # the template requires are defined. This gives a nice message rather than |
| 89 " # Be nice and help callers debug problems by checking that the\n" | 89 # giving the user an error about an undefined variable in the file defining |
| 90 " # variables the template requires are defined. This gives a nice\n" | 90 # the template |
| 91 " # message rather than giving the user an error about an\n" | 91 # |
| 92 " # undefined variable in the file defining the template\n" | 92 # You can also use defined() to give default values to variables |
| 93 " #\n" | 93 # unspecified by the invoker. |
| 94 " # You can also use defined() to give default values to variables\n" | 94 assert(defined(invoker.sources), |
| 95 " # unspecified by the invoker.\n" | 95 "Need sources in $target_name listing the idl files.") |
| 96 " assert(defined(invoker.sources),\n" | 96 |
| 97 " \"Need sources in $target_name listing the idl files.\")\n" | 97 # Name of the intermediate target that does the code gen. This must |
| 98 "\n" | 98 # incorporate the target name so it's unique across template |
| 99 " # Name of the intermediate target that does the code gen. This must\n" | 99 # instantiations. |
| 100 " # incorporate the target name so it's unique across template\n" | 100 code_gen_target_name = target_name + "_code_gen" |
| 101 " # instantiations.\n" | 101 |
| 102 " code_gen_target_name = target_name + \"_code_gen\"\n" | 102 # Intermediate target to convert IDL to C source. Note that the name is |
| 103 "\n" | 103 # based on the name the invoker of the template specified. This way, each |
| 104 " # Intermediate target to convert IDL to C source. Note that the name\n" | 104 # time the template is invoked we get a unique intermediate action name |
| 105 " # is based on the name the invoker of the template specified. This\n" | 105 # (since all target names are in the global scope). |
| 106 " # way, each time the template is invoked we get a unique\n" | 106 action_foreach(code_gen_target_name) { |
| 107 " # intermediate action name (since all target names are in the global\n" | 107 # Access the scope defined by the invoker via the implicit "invoker" |
| 108 " # scope).\n" | 108 # variable. |
| 109 " action_foreach(code_gen_target_name) {\n" | 109 sources = invoker.sources |
| 110 " # Access the scope defined by the invoker via the implicit\n" | 110 |
| 111 " # \"invoker\" variable.\n" | 111 # Note that we need an absolute path for our script file name. The |
| 112 " sources = invoker.sources\n" | 112 # current directory when executing this code will be that of the invoker |
| 113 "\n" | 113 # (this is why we can use the "sources" directly above without having to |
| 114 " # Note that we need an absolute path for our script file name.\n" | 114 # rebase all of the paths). But if we need to reference a script relative |
| 115 " # The current directory when executing this code will be that of\n" | 115 # to the template file, we'll need to use an absolute path instead. |
| 116 " # the invoker (this is why we can use the \"sources\" directly\n" | 116 script = "//tools/idl/idl_code_generator.py" |
| 117 " # above without having to rebase all of the paths). But if we need\n" | 117 |
| 118 " # to reference a script relative to the template file, we'll need\n" | 118 # Tell GN how to expand output names given the sources. |
| 119 " # to use an absolute path instead.\n" | 119 # See "gn help source_expansion" for more. |
| 120 " script = \"//tools/idl/idl_code_generator.py\"\n" | 120 outputs = [ "$target_gen_dir/{{source_name_part}}.cc", |
| 121 "\n" | 121 "$target_gen_dir/{{source_name_part}}.h" ] |
| 122 " # Tell GN how to expand output names given the sources.\n" | 122 } |
| 123 " # See \"gn help source_expansion\" for more.\n" | 123 |
| 124 " outputs = [ \"$target_gen_dir/{{source_name_part}}.cc\",\n" | 124 # Name the source set the same as the template invocation so instancing |
| 125 " \"$target_gen_dir/{{source_name_part}}.h\" ]\n" | 125 # this template produces something that other targets can link to in their |
| 126 " }\n" | 126 # deps. |
| 127 "\n" | 127 source_set(target_name) { |
| 128 " # Name the source set the same as the template invocation so\n" | 128 # Generates the list of sources, we get these from the action_foreach |
| 129 " # instancing this template produces something that other targets\n" | 129 # above. |
| 130 " # can link to in their deps.\n" | 130 sources = get_target_outputs(":$code_gen_target_name") |
| 131 " source_set(target_name) {\n" | 131 |
| 132 " # Generates the list of sources, we get these from the\n" | 132 # This target depends on the files produced by the above code gen target. |
| 133 " # action_foreach above.\n" | 133 deps = [ ":$code_gen_target_name" ] |
| 134 " sources = get_target_outputs(\":$code_gen_target_name\")\n" | 134 } |
| 135 "\n" | 135 } |
| 136 " # This target depends on the files produced by the above code gen\n" | 136 |
| 137 " # target.\n" | 137 Example of invoking the resulting template |
| 138 " deps = [ \":$code_gen_target_name\" ]\n" | 138 |
| 139 " }\n" | 139 # This calls the template code above, defining target_name to be |
| 140 " }\n" | 140 # "foo_idl_files" and "invoker" to be the set of stuff defined in the curly |
| 141 "\n" | 141 # brackets. |
| 142 "Example of invoking the resulting template:\n" | 142 my_idl("foo_idl_files") { |
| 143 "\n" | 143 # Goes into the template as "invoker.sources". |
| 144 " # This calls the template code above, defining target_name to be\n" | 144 sources = [ "foo.idl", "bar.idl" ] |
| 145 " # \"foo_idl_files\" and \"invoker\" to be the set of stuff defined in\n" | 145 } |
| 146 " # the curly brackets.\n" | 146 |
| 147 " my_idl(\"foo_idl_files\") {\n" | 147 # Here is a target that depends on our template. |
| 148 " # Goes into the template as \"invoker.sources\".\n" | 148 executable("my_exe") { |
| 149 " sources = [ \"foo.idl\", \"bar.idl\" ]\n" | 149 # Depend on the name we gave the template call above. Internally, this will |
| 150 " }\n" | 150 # produce a dependency from executable to the source_set inside the |
| 151 "\n" | 151 # template (since it has this name), which will in turn depend on the code |
| 152 " # Here is a target that depends on our template.\n" | 152 # gen action. |
| 153 " executable(\"my_exe\") {\n" | 153 deps = [ ":foo_idl_files" ] |
| 154 " # Depend on the name we gave the template call above. Internally,\n" | 154 } |
| 155 " # this will produce a dependency from executable to the source_set\n" | 155 )"; |
| 156 " # inside the template (since it has this name), which will in turn\n" | |
| 157 " # depend on the code gen action.\n" | |
| 158 " deps = [ \":foo_idl_files\" ]\n" | |
| 159 " }\n"; | |
| 160 | 156 |
| 161 Value RunTemplate(Scope* scope, | 157 Value RunTemplate(Scope* scope, |
| 162 const FunctionCallNode* function, | 158 const FunctionCallNode* function, |
| 163 const std::vector<Value>& args, | 159 const std::vector<Value>& args, |
| 164 BlockNode* block, | 160 BlockNode* block, |
| 165 Err* err) { | 161 Err* err) { |
| 166 // Of course you can have configs and targets in a template. But here, we're | 162 // Of course you can have configs and targets in a template. But here, we're |
| 167 // not actually executing the block, only declaring it. Marking the template | 163 // not actually executing the block, only declaring it. Marking the template |
| 168 // declaration as non-nestable means that you can't put it inside a target, | 164 // declaration as non-nestable means that you can't put it inside a target, |
| 169 // for example. | 165 // for example. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 // used-variable checking anyway, and this case is annoying enough that the | 204 // used-variable checking anyway, and this case is annoying enough that the |
| 209 // incremental value of unused variable checking isn't worth the | 205 // incremental value of unused variable checking isn't worth the |
| 210 // alternatives. So all values in scope before this template definition are | 206 // alternatives. So all values in scope before this template definition are |
| 211 // exempted from unused variable checking. | 207 // exempted from unused variable checking. |
| 212 scope->MarkAllUsed(); | 208 scope->MarkAllUsed(); |
| 213 | 209 |
| 214 return Value(); | 210 return Value(); |
| 215 } | 211 } |
| 216 | 212 |
| 217 } // namespace functions | 213 } // namespace functions |
| OLD | NEW |