diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2011-10-03 03:02:11 (GMT) |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2011-11-04 19:10:31 (GMT) |
commit | 4836a864667df3a8c1dd90bb9db7571c6a91e4dc (patch) | |
tree | e31a16b42f2607395c429b5e35f9d3fed243412a | |
parent | 801377e0651d35a8f006ea3722a44f52cfe787bf (diff) | |
download | Ninja-4836a864667df3a8c1dd90bb9db7571c6a91e4dc.zip Ninja-4836a864667df3a8c1dd90bb9db7571c6a91e4dc.tar.gz Ninja-4836a864667df3a8c1dd90bb9db7571c6a91e4dc.tar.bz2 |
Add a "commands" tool
This tool performs a post-order traversal of the build graph, starting
from a list of targets specified on the command line, and for each
build statement encountered, prints the evaluated command line.
Use cases include:
- Generating input for a tool which needs to know the full command line
for every command invoked during a build. Many static analysis
and indexing tools require this information.
- Generating a build script which does not depend on Ninja.
For example, such a script could be used by Ninja to bootstrap
itself.
-rw-r--r-- | doc/manual.asciidoc | 4 | ||||
-rw-r--r-- | src/ninja.cc | 44 |
2 files changed, 42 insertions, 6 deletions
diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc index d59f471..bc15a1f 100644 --- a/doc/manual.asciidoc +++ b/doc/manual.asciidoc @@ -382,6 +382,10 @@ than the _depth_ mode. It returns non-zero if an error occurs. one. It can be used to know which rule name to pass to +ninja -t targets rule _name_+. +`commands`:: given a list of targets, print a list of commands which, if +executed in order, may be used to rebuild those targets, assuming that all +output files are out of date. + `clean`:: remove built files. If used like this +ninja -t clean+ it removes all the built files, except for those created by the generator. If used like this +ninja -t clean -g+ it also removes built files created by the diff --git a/src/ninja.cc b/src/ninja.cc index a058e95..47693d1 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -65,12 +65,13 @@ void Usage(const BuildConfig& config) { " -t TOOL run a subtool.\n" " terminates toplevel options; further flags are passed to the tool.\n" " tools are:\n" -" browse browse dependency graph in a web browser\n" -" graph output graphviz dot file for targets\n" -" query show inputs/outputs for a path\n" -" targets list targets by their rule or depth in the DAG\n" -" rules list all rules\n" -" clean clean built files\n", +" browse browse dependency graph in a web browser\n" +" graph output graphviz dot file for targets\n" +" query show inputs/outputs for a path\n" +" targets list targets by their rule or depth in the DAG\n" +" rules list all rules\n" +" commands list all commands required to rebuild given targets\n" +" clean clean built files\n", config.parallelism); } @@ -357,6 +358,35 @@ int CmdRules(State* state, int argc, char* argv[]) { return 0; } +void PrintCommands(Edge* edge, set<Edge*>* seen) { + if (!edge) + return; + if (!seen->insert(edge).second) + return; + + for (vector<Node*>::iterator in = edge->inputs_.begin(); + in != edge->inputs_.end(); ++in) + PrintCommands((*in)->in_edge_, seen); + + if (!edge->is_phony()) + puts(edge->EvaluateCommand().c_str()); +} + +int CmdCommands(State* state, int argc, char* argv[]) { + vector<Node*> nodes; + string err; + if (!CollectTargetsFromArgs(state, argc, argv, &nodes, &err)) { + Error("%s", err.c_str()); + return 1; + } + + set<Edge*> seen; + for (vector<Node*>::iterator in = nodes.begin(); in != nodes.end(); ++in) + PrintCommands((*in)->in_edge_, &seen); + + return 0; +} + int CmdClean(State* state, int argc, char* argv[], const BuildConfig& config) { bool generator = false; bool clean_rules = false; @@ -489,6 +519,8 @@ reload: return CmdTargets(&state, argc, argv); if (tool == "rules") return CmdRules(&state, argc, argv); + if (tool == "commands") + return CmdCommands(&state, argc, argv); // The clean tool uses getopt, and expects argv[0] to contain the name of // the tool, i.e. "clean". if (tool == "clean") |