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 {