Document GN invoker and target name variables.
There was some confusion about this, and one would also expect that
these build-in variables would be listed in the help under the other
built-in variables.
BUG=468991
Review-Url: https://codereview.chromium.org/2149213002
Cr-Original-Commit-Position: refs/heads/master@{#405584}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: d93e5cf487e27ae69e20ea4fabb35c9246864302
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md
index ff096cc..acf0ac1 100644
--- a/tools/gn/docs/reference.md
+++ b/tools/gn/docs/reference.md
@@ -539,6 +539,15 @@
```
+### **Printing outputs**
+
+```
+ The "outputs" section will list all outputs that apply, including
+ the outputs computed from the tool definition (eg for "executable",
+ "static_library", ... targets).
+
+```
+
### **Printing deps**
```
@@ -2493,11 +2502,16 @@
set_defaults can be used for built-in target types ("executable",
"shared_library", etc.) and custom ones defined via the "template"
- command.
+ command. It can be called more than once and the most recent call in
+ any scope will apply, but there is no way to refer to the previous
+ defaults and modify them (each call to set_defaults must supply a
+ complete list of all defaults it wants). If you want to share
+ defaults, store them in a separate variable.
```
-### **Example**:
+### **Example**
+
```
set_defaults("static_library") {
configs = [ "//tools/mything:settings" ]
@@ -2645,6 +2659,33 @@
```
+## **split_list**: Splits a list into N different sub-lists.
+
+```
+ result = split_list(input, n)
+
+ Given a list and a number N, splits the list into N sub-lists of
+ approximately equal size. The return value is a list of the sub-lists.
+ The result will always be a list of size N. If N is greater than the
+ number of elements in the input, it will be padded with empty lists.
+
+ The expected use is to divide source files into smaller uniform
+ chunks.
+
+```
+
+### **Example**
+
+```
+ The code:
+ mylist = [1, 2, 3, 4, 5, 6]
+ print(split_list(mylist, 3))
+
+ Will print:
+ [[1, 2], [3, 4], [5, 6]
+
+
+```
## **static_library**: Declare a static library target.
```
@@ -3591,6 +3632,40 @@
```
+## **invoker**: [string] The invoking scope inside a template.
+
+```
+ Inside a template invocation, this variable refers to the scope of
+ the invoker of the template. Outside of template invocations, this
+ variable is undefined.
+
+ All of the variables defined inside the template invocation are
+ accessible as members of the "invoker" scope. This is the way that
+ templates read values set by the callers.
+
+ This is often used with "defined" to see if a value is set on the
+ invoking scope.
+
+ See "gn help template" for more examples.
+
+```
+
+### **Example**
+
+```
+ template("my_template") {
+ print(invoker.sources) # Prints [ "a.cc", "b.cc" ]
+ print(defined(invoker.foo)) # Prints false.
+ print(defined(invoker.bar)) # Prints true.
+ }
+
+ my_template("doom_melon") {
+ sources = [ "a.cc", "b.cc" ]
+ bar = 123
+ }
+
+
+```
## **python_path**: Absolute path of Python.
```
@@ -3721,6 +3796,49 @@
```
+## **target_name**: [string] The name of the current target.
+
+```
+ Inside a target or template invocation, this variable refers to the
+ name given to the target or template invocation. Outside of these,
+ this variable is undefined.
+
+ This is most often used in template definitions to name targets
+ defined in the template based on the name of the invocation. This
+ is necessary both to ensure generated targets have unique names and
+ to generate a target with the exact name of the invocation that
+ other targets can depend on.
+
+ Be aware that this value will always reflect the innermost scope. So
+ when defining a target inside a template, target_name will refer to
+ the target rather than the template invocation. To get the name of the
+ template invocation in this case, you should save target_name to a
+ temporary variable outside of any target definitions.
+
+ See "gn help template" for more examples.
+
+```
+
+### **Example**
+
+```
+ executable("doom_melon") {
+ print(target_name) # Prints "doom_melon".
+ }
+
+ template("my_template") {
+ print(target_name) # Prints "space_ray" when invoked below.
+
+ executable(target_name + "_impl") {
+ print(target_name) # Prints "space_ray_impl".
+ }
+ }
+
+ my_template("space_ray") {
+ }
+
+
+```
## **target_os**: The desired operating system for the build.
```
diff --git a/tools/gn/functions.cc b/tools/gn/functions.cc
index 0102bd7..dcea722 100644
--- a/tools/gn/functions.cc
+++ b/tools/gn/functions.cc
@@ -101,7 +101,7 @@
// Set the target name variable to the current target, and mark it used
// because we don't want to issue an error if the script ignores it.
- const base::StringPiece target_name("target_name");
+ const base::StringPiece target_name(variables::kTargetName);
block_scope->SetValue(target_name, Value(function, args[0].string_value()),
function);
block_scope->MarkUsed(target_name);
diff --git a/tools/gn/template.cc b/tools/gn/template.cc
index 3c4d76d..e865264 100644
--- a/tools/gn/template.cc
+++ b/tools/gn/template.cc
@@ -12,6 +12,7 @@
#include "tools/gn/scope.h"
#include "tools/gn/scope_per_file_provider.h"
#include "tools/gn/value.h"
+#include "tools/gn/variables.h"
Template::Template(const Scope* scope, const FunctionCallNode* def)
: closure_(scope->MakeClosure()),
@@ -77,14 +78,14 @@
// Scope.SetValue will copy the value which will in turn copy the scope, but
// if we instead create a value and then set the scope on it, the copy can
// be avoided.
- const char kInvoker[] = "invoker";
- template_scope.SetValue(kInvoker, Value(nullptr, std::unique_ptr<Scope>()),
- invocation);
- Value* invoker_value = template_scope.GetMutableValue(kInvoker, false);
+ template_scope.SetValue(variables::kInvoker,
+ Value(nullptr, std::unique_ptr<Scope>()), invocation);
+ Value* invoker_value =
+ template_scope.GetMutableValue(variables::kInvoker, false);
invoker_value->SetScopeValue(std::move(invocation_scope));
template_scope.set_source_dir(scope->GetSourceDir());
- const base::StringPiece target_name("target_name");
+ const base::StringPiece target_name(variables::kTargetName);
template_scope.SetValue(target_name,
Value(invocation, args[0].string_value()),
invocation);
@@ -107,7 +108,7 @@
// to overwrite the value of "invoker" and free the Scope owned by the
// value. So we need to look it up again and don't do anything if it doesn't
// exist.
- invoker_value = template_scope.GetMutableValue(kInvoker, false);
+ invoker_value = template_scope.GetMutableValue(variables::kInvoker, false);
if (invoker_value && invoker_value->type() == Value::SCOPE) {
if (!invoker_value->scope_value()->CheckForUnusedVars(err))
return Value();
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc
index 7b2c4a0..948495c 100644
--- a/tools/gn/variables.cc
+++ b/tools/gn/variables.cc
@@ -44,6 +44,38 @@
" - \"mac\"\n"
" - \"win\"\n";
+const char kInvoker[] = "invoker";
+const char kInvoker_HelpShort[] =
+ "invoker: [string] The invoking scope inside a template.";
+const char kInvoker_Help[] =
+ "invoker: [string] The invoking scope inside a template.\n"
+ "\n"
+ " Inside a template invocation, this variable refers to the scope of\n"
+ " the invoker of the template. Outside of template invocations, this\n"
+ " variable is undefined.\n"
+ "\n"
+ " All of the variables defined inside the template invocation are\n"
+ " accessible as members of the \"invoker\" scope. This is the way that\n"
+ " templates read values set by the callers.\n"
+ "\n"
+ " This is often used with \"defined\" to see if a value is set on the\n"
+ " invoking scope.\n"
+ "\n"
+ " See \"gn help template\" for more examples.\n"
+ "\n"
+ "Example\n"
+ "\n"
+ " template(\"my_template\") {\n"
+ " print(invoker.sources) # Prints [ \"a.cc\", \"b.cc\" ]\n"
+ " print(defined(invoker.foo)) # Prints false.\n"
+ " print(defined(invoker.bar)) # Prints true.\n"
+ " }\n"
+ "\n"
+ " my_template(\"doom_melon\") {\n"
+ " sources = [ \"a.cc\", \"b.cc\" ]\n"
+ " bar = 123\n"
+ " }\n";
+
const char kTargetCpu[] = "target_cpu";
const char kTargetCpu_HelpShort[] =
"target_cpu: [string] The desired cpu architecture for the build.";
@@ -76,6 +108,47 @@
" - \"arm64\"\n"
" - \"mipsel\"\n";
+const char kTargetName[] = "target_name";
+const char kTargetName_HelpShort[] =
+ "target_name: [string] The name of the current target.";
+const char kTargetName_Help[] =
+ "target_name: [string] The name of the current target.\n"
+ "\n"
+ " Inside a target or template invocation, this variable refers to the\n"
+ " name given to the target or template invocation. Outside of these,\n"
+ " this variable is undefined.\n"
+ "\n"
+ " This is most often used in template definitions to name targets\n"
+ " defined in the template based on the name of the invocation. This\n"
+ " is necessary both to ensure generated targets have unique names and\n"
+ " to generate a target with the exact name of the invocation that\n"
+ " other targets can depend on.\n"
+ "\n"
+ " Be aware that this value will always reflect the innermost scope. So\n"
+ " when defining a target inside a template, target_name will refer to\n"
+ " the target rather than the template invocation. To get the name of the\n"
+ " template invocation in this case, you should save target_name to a\n"
+ " temporary variable outside of any target definitions.\n"
+ "\n"
+ " See \"gn help template\" for more examples.\n"
+ "\n"
+ "Example\n"
+ "\n"
+ " executable(\"doom_melon\") {\n"
+ " print(target_name) # Prints \"doom_melon\".\n"
+ " }\n"
+ "\n"
+ " template(\"my_template\") {\n"
+ " print(target_name) # Prints \"space_ray\" when invoked below.\n"
+ "\n"
+ " executable(target_name + \"_impl\") {\n"
+ " print(target_name) # Prints \"space_ray_impl\".\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " my_template(\"space_ray\") {\n"
+ " }\n";
+
const char kTargetOs[] = "target_os";
const char kTargetOs_HelpShort[] =
"target_os: [string] The desired operating system for the build.";
@@ -1713,6 +1786,7 @@
INSERT_VARIABLE(DefaultToolchain)
INSERT_VARIABLE(HostCpu)
INSERT_VARIABLE(HostOs)
+ INSERT_VARIABLE(Invoker)
INSERT_VARIABLE(PythonPath)
INSERT_VARIABLE(RootBuildDir)
INSERT_VARIABLE(RootGenDir)
@@ -1720,6 +1794,7 @@
INSERT_VARIABLE(TargetCpu)
INSERT_VARIABLE(TargetOs)
INSERT_VARIABLE(TargetGenDir)
+ INSERT_VARIABLE(TargetName)
INSERT_VARIABLE(TargetOutDir)
}
return info_map;
diff --git a/tools/gn/variables.h b/tools/gn/variables.h
index 8ed165f..0e092e4 100644
--- a/tools/gn/variables.h
+++ b/tools/gn/variables.h
@@ -37,6 +37,10 @@
extern const char kDefaultToolchain_HelpShort[];
extern const char kDefaultToolchain_Help[];
+extern const char kInvoker[];
+extern const char kInvoker_HelpShort[];
+extern const char kInvoker_Help[];
+
extern const char kPythonPath[];
extern const char kPythonPath_HelpShort[];
extern const char kPythonPath_Help[];
@@ -57,6 +61,10 @@
extern const char kTargetCpu_HelpShort[];
extern const char kTargetCpu_Help[];
+extern const char kTargetName[];
+extern const char kTargetName_HelpShort[];
+extern const char kTargetName_Help[];
+
extern const char kTargetOs[];
extern const char kTargetOs_HelpShort[];
extern const char kTargetOs_Help[];