From: uazo Date: Wed, 8 Dec 2021 11:08:45 +0000 Subject: Allow 'ninja -t compdb' accept one target --- src/ninja.cc | 64 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/src/ninja.cc b/src/ninja.cc index ed004ac8f1fe1a5107db8b1f5c02c4ba957daef4..bbb79da561ddec497863230cd99ffbe98b9a76e5 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef _WIN32 #include "getopt.h" @@ -73,6 +74,8 @@ struct Options { /// Whether phony cycles should warn or print an error. bool phony_cycle_should_err; + + const char* user_given_target; }; /// The Ninja main() loads up a series of data structures; various tools need @@ -211,6 +214,7 @@ void Usage(const BuildConfig& config) { " -l N do not start new jobs if the load average is greater than N\n" " -n dry run (don't run commands but act like they succeeded)\n" " -v show all command lines while building\n" +" -a generate compilation database for given target\n" "\n" " -d MODE enable debugging (use -d list to list modes)\n" " -t TOOL run a subtool (use -t list to list subtools)\n" @@ -662,7 +666,56 @@ void EncodeJSONString(const char *str) { } } +bool GetAllDependentEdges(Node* node, std::vector* depend_edges, + std::unordered_set* visited_nodes=NULL, + std::unordered_set* visited_edges=NULL) { + if (visited_nodes == NULL || visited_edges == NULL) { + std::unordered_set visited_nodes_; + std::unordered_set visited_edges_; + return GetAllDependentEdges(node, depend_edges, &visited_nodes_, &visited_edges_); + } + if (node == NULL || depend_edges == NULL) { + Error("Internal error"); + return false; + } + if (visited_nodes->count(node)) { + return true; + } else { + visited_nodes->insert(node); + } + Edge* edge = node->in_edge(); + // Leaf node + if (!edge || visited_edges->count(edge)) { + return true; + } else { + visited_edges->insert(edge); + depend_edges->push_back(edge); + } + for (Node* input_node : edge->inputs_) { + if (!GetAllDependentEdges(input_node, depend_edges, visited_nodes, visited_edges)) + return false; + } + return true; +} + int NinjaMain::ToolCompilationDatabase(const Options* options, int argc, char* argv[]) { + std::vector* edges_to_process = &(state_.edges_); + + if (options->user_given_target) { + string err; + Node* user_given_target = CollectTarget( + options->user_given_target, &err); + if (!err.empty()) { + Error("%s: %s", options->user_given_target, err.c_str()); + return 1; + } + + std::vector user_interested_edges; + if (!GetAllDependentEdges(user_given_target, &user_interested_edges)) + return 1; + edges_to_process = &user_interested_edges; + } + bool first = true; vector cwd; @@ -676,8 +729,8 @@ int NinjaMain::ToolCompilationDatabase(const Options* options, int argc, char* a } putchar('['); - for (vector::iterator e = state_.edges_.begin(); - e != state_.edges_.end(); ++e) { + for (vector::iterator e = edges_to_process->begin(); + e != edges_to_process->end(); ++e) { if ((*e)->inputs_.empty()) continue; for (int i = 0; i != argc; ++i) { @@ -1047,9 +1100,14 @@ int ReadFlags(int* argc, char*** argv, int opt; while (!options->tool && - (opt = getopt_long(*argc, *argv, "d:f:j:k:l:nt:vw:C:h", kLongOptions, + (opt = getopt_long(*argc, *argv, "a:d:f:j:k:l:nt:vw:C:h", kLongOptions, NULL)) != -1) { switch (opt) { + case 'a': + options->user_given_target = optarg; + if (!options->user_given_target) + Fatal("Expecting one target name"); + break; case 'd': if (!DebugEnable(optarg)) return 1;