Add optional 'mnemonic' var to actions
This will replace the "ACTION" prefix for the ninja
description of a given action.
Change-Id: Ib394f193e0aaa9ff3453c7b8e10a07a2b84150ad
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/15260
Reviewed-by: Takuto Ikuta <tikuta@google.com>
Commit-Queue: Takuto Ikuta <tikuta@google.com>
diff --git a/docs/reference.md b/docs/reference.md
index 76ef2a9..093c711 100644
--- a/docs/reference.md
+++ b/docs/reference.md
@@ -132,6 +132,7 @@
* [lib_dirs: [directory list] Additional library directories.](#var_lib_dirs)
* [libs: [string list] Additional libraries to link.](#var_libs)
* [metadata: [scope] Metadata of this target.](#var_metadata)
+ * [mnemonic: [string] Prefix displayed when ninja runs this action.](#var_mnemonic)
* [module_name: [string] The name for the compiled module.](#var_module_name)
* [output_conversion: Data format for generated_file targets.](#var_output_conversion)
* [output_dir: [directory] Directory to put output file in.](#var_output_dir)
@@ -1416,9 +1417,9 @@
output_extension, output_name, public, sources, testonly,
visibility
Action variables: args, bridge_header, configs, data, depfile,
- framework_dirs, inputs, module_deps, module_name,
- outputs*, pool, response_file_contents, script*,
- sources
+ framework_dirs, inputs, mnemonic, module_deps,
+ module_name, outputs*, pool, response_file_contents,
+ script*, sources
* = required
```
@@ -1517,9 +1518,9 @@
output_extension, output_name, public, sources, testonly,
visibility
Action variables: args, bridge_header, configs, data, depfile,
- framework_dirs, inputs, module_deps, module_name,
- outputs*, pool, response_file_contents, script*,
- sources
+ framework_dirs, inputs, mnemonic, module_deps,
+ module_name, outputs*, pool, response_file_contents,
+ script*, sources
* = required
```
@@ -1532,6 +1533,10 @@
script = "idl_processor.py"
sources = [ "foo.idl", "bar.idl" ]
+ # Causes ninja to output "IDL <label>" rather than the default
+ # "ACTION <label>" when building this action.
+ mnemonic = "IDL"
+
# Our script reads this file each time, so we need to list it as a
# dependency so we can rebuild if it changes.
inputs = [ "my_configuration.txt" ]
@@ -2454,6 +2459,13 @@
which will return true or false depending on whether bar is defined in the
named scope foo. It will throw an error if foo is not defined or is not a
scope.
+
+ You can also check a named scope using a subscript string expression:
+ defined(foo[bar + "_name"])
+ Which will return true or false depending on whether the subscript
+ expression expands to the name of a member of the scope foo. It will
+ throw an error if foo is not defined or is not a scope, or if the
+ expression does not expand to a string, or if it is an empty string.
```
#### **Example**
@@ -6058,6 +6070,17 @@
}
}
```
+### <a name="var_mnemonic"></a>**mnemonic**: [string] Prefix displayed when ninja runs this action.
+
+```
+ Tools in GN can set their ninja "description" which is displayed when
+ building a target. These are commonly set with the format "CXX $output"
+ or "LINK $label". By default, all GN actions will have the description
+ "ACTION $label". Setting a mnemonic will override the "ACTION" prefix
+ with another string, but the label will still be unconditionally displayed.
+
+ Whitespace is not allowed within a mnemonic.
+```
### <a name="var_module_name"></a>**module_name**: [string] The name for the compiled module.
```
diff --git a/misc/vim/syntax/gn.vim b/misc/vim/syntax/gn.vim
index df2d0d8..2719560 100644
--- a/misc/vim/syntax/gn.vim
+++ b/misc/vim/syntax/gn.vim
@@ -51,7 +51,7 @@
syn keyword gnVariable lib_dirs libs output_extension output_name outputs
syn keyword gnVariable public public_configs public_deps scripte sources
syn keyword gnVariable testonly visibility contents output_conversion rebase
-syn keyword gnVariable walk_keys gen_deps
+syn keyword gnVariable walk_keys gen_deps mnemonic
hi def link gnVariable Keyword
" Strings
diff --git a/src/gn/action_target_generator.cc b/src/gn/action_target_generator.cc
index 513015b..9cc9c83 100644
--- a/src/gn/action_target_generator.cc
+++ b/src/gn/action_target_generator.cc
@@ -5,6 +5,8 @@
#include "gn/action_target_generator.h"
#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "gn/build_settings.h"
#include "gn/config_values_generator.h"
#include "gn/err.h"
@@ -58,6 +60,9 @@
if (!FillDepfile())
return;
+ if (!FillMnemonic())
+ return;
+
if (!FillPool())
return;
@@ -168,6 +173,29 @@
return true;
}
+bool ActionTargetGenerator::FillMnemonic() {
+ const Value* value = scope_->GetValue(variables::kMnemonic, true);
+ if (!value)
+ return true;
+
+ if (!value->VerifyTypeIs(Value::STRING, err_))
+ return false;
+
+ auto s = value->string_value();
+ if (!base::IsStringUTF8(s)) {
+ *err_ = Err(value->origin(), "Mnemonics must be valid UTF-8");
+ return false;
+ }
+ auto widestr = base::UTF8ToUTF16(s);
+ if (std::any_of(widestr.begin(), widestr.end(), base::IsUnicodeWhitespace)) {
+ *err_ = Err(value->origin(), "Mnemonics can't contain whitespace");
+ return false;
+ }
+
+ target_->action_values().mnemonic() = std::move(s);
+ return true;
+}
+
bool ActionTargetGenerator::FillPool() {
const Value* value = scope_->GetValue(variables::kPool, true);
if (!value)
diff --git a/src/gn/action_target_generator.h b/src/gn/action_target_generator.h
index 9073cd7..6cbe8ae 100644
--- a/src/gn/action_target_generator.h
+++ b/src/gn/action_target_generator.h
@@ -26,6 +26,7 @@
bool FillScriptArgs();
bool FillResponseFileContents();
bool FillDepfile();
+ bool FillMnemonic();
bool FillPool();
bool FillInputs();
diff --git a/src/gn/action_values.h b/src/gn/action_values.h
index 9daf918..5ac1a7a 100644
--- a/src/gn/action_values.h
+++ b/src/gn/action_values.h
@@ -44,6 +44,10 @@
bool has_depfile() const { return !depfile_.ranges().empty(); }
void set_depfile(const SubstitutionPattern& depfile) { depfile_ = depfile; }
+ // prefix to the ninja output description for this action.
+ std::string& mnemonic() { return mnemonic_; }
+ const std::string& mnemonic() const { return mnemonic_; }
+
// Response file contents. Empty means no response file.
SubstitutionList& rsp_file_contents() { return rsp_file_contents_; }
const SubstitutionList& rsp_file_contents() const {
@@ -57,6 +61,7 @@
SubstitutionList outputs_;
SubstitutionPattern depfile_;
SubstitutionList rsp_file_contents_;
+ std::string mnemonic_;
ActionValues(const ActionValues&) = delete;
ActionValues& operator=(const ActionValues&) = delete;
diff --git a/src/gn/command_desc.cc b/src/gn/command_desc.cc
index e3cd1eb..99f7e45 100644
--- a/src/gn/command_desc.cc
+++ b/src/gn/command_desc.cc
@@ -308,6 +308,7 @@
{variables::kRustCrateRoot, DefaultHandler},
{variables::kSwiftModuleName, DefaultHandler},
{variables::kSwiftBridgeHeader, DefaultHandler},
+ {variables::kMnemonic, DefaultHandler},
{"runtime_deps", DefaultHandler}};
}
diff --git a/src/gn/functions_target.cc b/src/gn/functions_target.cc
index 4ca2c10..72c95e2 100644
--- a/src/gn/functions_target.cc
+++ b/src/gn/functions_target.cc
@@ -28,9 +28,9 @@
" Rust variables: aliased_deps, crate_root, crate_name, crate_type\n"
#define ACTION_VARS \
" Action variables: args, bridge_header, configs, data, depfile,\n" \
- " framework_dirs, inputs, module_deps, module_name,\n" \
- " outputs*, pool, response_file_contents, script*,\n" \
- " sources\n"
+ " framework_dirs, inputs, mnemonic, module_deps,\n" \
+ " module_name, outputs*, pool, response_file_contents,\n" \
+ " script*, sources\n"
namespace functions {
@@ -257,6 +257,10 @@
script = "idl_processor.py"
sources = [ "foo.idl", "bar.idl" ]
+ # Causes ninja to output "IDL <label>" rather than the default
+ # "ACTION <label>" when building this action.
+ mnemonic = "IDL"
+
# Our script reads this file each time, so we need to list it as a
# dependency so we can rebuild if it changes.
inputs = [ "my_configuration.txt" ]
diff --git a/src/gn/ninja_action_target_writer.cc b/src/gn/ninja_action_target_writer.cc
index c33fc6e..f4f0867 100644
--- a/src/gn/ninja_action_target_writer.cc
+++ b/src/gn/ninja_action_target_writer.cc
@@ -156,7 +156,10 @@
SubstitutionWriter::WriteWithNinjaVariables(arg, args_escape_options, out_);
}
out_ << std::endl;
- out_ << " description = ACTION " << target_label << std::endl;
+ auto mnemonic = target_->action_values().mnemonic();
+ if (mnemonic.empty())
+ mnemonic = "ACTION";
+ out_ << " description = " << mnemonic << " " << target_label << std::endl;
out_ << " restat = 1" << std::endl;
const Tool* tool =
target_->toolchain()->GetTool(GeneralTool::kGeneralToolAction);
diff --git a/src/gn/variables.cc b/src/gn/variables.cc
index 28f174d..07ce016 100644
--- a/src/gn/variables.cc
+++ b/src/gn/variables.cc
@@ -572,6 +572,21 @@
See also "gn help action" and "gn help action_foreach".
)";
+const char kMnemonic[] = "mnemonic";
+const char kMnemonic_HelpShort[] =
+ "mnemonic: [string] Prefix displayed when ninja runs this action.";
+const char kMnemonic_Help[] =
+ R"(mnemonic: [string] Prefix displayed when ninja runs this action.
+
+ Tools in GN can set their ninja "description" which is displayed when
+ building a target. These are commonly set with the format "CXX $output"
+ or "LINK $label". By default, all GN actions will have the description
+ "ACTION $label". Setting a mnemonic will override the "ACTION" prefix
+ with another string, but the label will still be unconditionally displayed.
+
+ Whitespace is not allowed within a mnemonic.
+)";
+
const char kAssertNoDeps[] = "assert_no_deps";
const char kAssertNoDeps_HelpShort[] =
"assert_no_deps: [label pattern list] Ensure no deps on these targets.";
@@ -2330,6 +2345,7 @@
INSERT_VARIABLE(Defines)
INSERT_VARIABLE(Depfile)
INSERT_VARIABLE(Deps)
+ INSERT_VARIABLE(Mnemonic)
INSERT_VARIABLE(Externs)
INSERT_VARIABLE(Friend)
INSERT_VARIABLE(FrameworkDirs)
diff --git a/src/gn/variables.h b/src/gn/variables.h
index 169a5af..ac392d9 100644
--- a/src/gn/variables.h
+++ b/src/gn/variables.h
@@ -358,6 +358,10 @@
extern const char kGenDeps_HelpShort[];
extern const char kGenDeps_Help[];
+extern const char kMnemonic[];
+extern const char kMnemonic_HelpShort[];
+extern const char kMnemonic_Help[];
+
// -----------------------------------------------------------------------------
struct VariableInfo {