summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Despres <nicolas.despres@gmail.com>2015-09-21 12:01:33 +0200
committerNicolas Despres <nicolas.despres@gmail.com>2019-05-09 16:36:47 +0200
commitbb9512f53daa5913220282f0ad86a20d174e367c (patch)
treef4fdf019cad3ee6dc5fce2338f144431797607a2
parent2e64645749ff91eff2f999f03f55da360ae5913d (diff)
downloadninja-bb9512f53daa5913220282f0ad86a20d174e367c.tar.gz
Resurrect the 'rules' tool.
This tool is useful for writing shell completion script for tools expecting a rule name as argument. The tool was dropped by 34b46f28c. Fix #1024.
-rw-r--r--doc/manual.asciidoc3
-rw-r--r--src/eval_env.cc14
-rw-r--r--src/eval_env.h5
-rw-r--r--src/ninja.cc52
4 files changed, 74 insertions, 0 deletions
diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc
index c9309ad..7f3ab8a 100644
--- a/doc/manual.asciidoc
+++ b/doc/manual.asciidoc
@@ -283,6 +283,9 @@ target, show just the target's dependencies. _Available since Ninja 1.4._
`recompact`:: recompact the `.ninja_deps` file. _Available since Ninja 1.4._
+`rules`:: output the list of all rules (eventually with their description
+if they have one). It can be used to know which rule name to pass to
++ninja -t targets rule _name_+ or +ninja -t compdb+.
Writing your own Ninja files
----------------------------
diff --git a/src/eval_env.cc b/src/eval_env.cc
index aa3d2b6..e9b6c43 100644
--- a/src/eval_env.cc
+++ b/src/eval_env.cc
@@ -131,3 +131,17 @@ string EvalString::Serialize() const {
}
return result;
}
+
+string EvalString::Unparse() const {
+ string result;
+ for (TokenList::const_iterator i = parsed_.begin();
+ i != parsed_.end(); ++i) {
+ bool special = (i->second == SPECIAL);
+ if (special)
+ result.append("${");
+ result.append(i->first);
+ if (special)
+ result.append("}");
+ }
+ return result;
+}
diff --git a/src/eval_env.h b/src/eval_env.h
index 999ce42..8fb9bf4 100644
--- a/src/eval_env.h
+++ b/src/eval_env.h
@@ -33,8 +33,13 @@ struct Env {
/// A tokenized string that contains variable references.
/// Can be evaluated relative to an Env.
struct EvalString {
+ /// @return The evaluated string with variable expanded using value found in
+ /// environment @a env.
string Evaluate(Env* env) const;
+ /// @return The string with variables not expanded.
+ string Unparse() const;
+
void Clear() { parsed_.clear(); }
bool empty() const { return parsed_.empty(); }
diff --git a/src/ninja.cc b/src/ninja.cc
index 5f19a65..a093cd1 100644
--- a/src/ninja.cc
+++ b/src/ninja.cc
@@ -126,6 +126,7 @@ struct NinjaMain : public BuildLogUser {
int ToolCompilationDatabase(const Options* options, int argc, char* argv[]);
int ToolRecompact(const Options* options, int argc, char* argv[]);
int ToolUrtle(const Options* options, int argc, char** argv);
+ int ToolRules(const Options* options, int argc, char* argv[]);
/// Open the build log.
/// @return false on error.
@@ -561,6 +562,55 @@ int NinjaMain::ToolTargets(const Options* options, int argc, char* argv[]) {
}
}
+int NinjaMain::ToolRules(const Options* options, int argc, char* argv[]) {
+ // Parse options.
+
+ // The rules tool uses getopt, and expects argv[0] to contain the name of
+ // the tool, i.e. "rules".
+ argc++;
+ argv--;
+
+ bool print_description = false;
+
+ optind = 1;
+ int opt;
+ while ((opt = getopt(argc, argv, const_cast<char*>("hd"))) != -1) {
+ switch (opt) {
+ case 'd':
+ print_description = true;
+ break;
+ case 'h':
+ default:
+ printf("usage: ninja -t rules [options]\n"
+ "\n"
+ "options:\n"
+ " -d also print the description of the rule\n"
+ " -h print this message\n"
+ );
+ return 1;
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ // Print rules
+
+ typedef map<string, const Rule*> Rules;
+ const Rules& rules = state_.bindings_.GetRules();
+ for (Rules::const_iterator i = rules.begin(); i != rules.end(); ++i) {
+ printf("%s", i->first.c_str());
+ if (print_description) {
+ const Rule* rule = i->second;
+ const EvalString* description = rule->GetBinding("description");
+ if (description != NULL) {
+ printf(": %s", description->Unparse().c_str());
+ }
+ }
+ printf("\n");
+ }
+ return 0;
+}
+
enum PrintCommandMode { PCM_Single, PCM_All };
void PrintCommands(Edge* edge, set<Edge*>* seen, PrintCommandMode mode) {
if (!edge)
@@ -841,6 +891,8 @@ const Tool* ChooseTool(const string& tool_name) {
Tool::RUN_AFTER_LOAD, &NinjaMain::ToolCompilationDatabase },
{ "recompact", "recompacts ninja-internal data structures",
Tool::RUN_AFTER_LOAD, &NinjaMain::ToolRecompact },
+ { "rules", "list all rules",
+ Tool::RUN_AFTER_LOAD, &NinjaMain::ToolRules },
{ "urtle", NULL,
Tool::RUN_AFTER_FLAGS, &NinjaMain::ToolUrtle },
{ NULL, NULL, Tool::RUN_AFTER_FLAGS, NULL }