From 9256e162599bc6ededc3c52c08b6c4f8981e0d8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=9Aniatowski?= Date: Mon, 22 Feb 2021 23:36:07 +0100 Subject: [PATCH] fixup! Add a -t missingdeps tool to detect some classes of build flakes --- src/missing_deps.cc | 52 +++++++++++++++++++++++++++++++++------- src/missing_deps_test.cc | 2 +- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/missing_deps.cc b/src/missing_deps.cc index 16359c87f5..eaa3f73cc5 100644 --- a/src/missing_deps.cc +++ b/src/missing_deps.cc @@ -25,6 +25,44 @@ #include "state.h" #include "util.h" +namespace { + +/// ImplicitDepLoader variant that stores dep nodes into the given output +/// without updating graph deps like the base loader does. +struct NodeStoringImplicitDepLoader : public ImplicitDepLoader { + NodeStoringImplicitDepLoader( + State* state, DepsLog* deps_log, DiskInterface* disk_interface, + DepfileParserOptions const* depfile_parser_options, + std::vector* dep_nodes_output) + : ImplicitDepLoader(state, deps_log, disk_interface, + depfile_parser_options), + dep_nodes_output_(dep_nodes_output) {} + + protected: + virtual bool ProcessDepfileDeps(Edge* edge, + std::vector* depfile_ins, + std::string* err); + + private: + std::vector* dep_nodes_output_; +}; + +bool NodeStoringImplicitDepLoader::ProcessDepfileDeps( + Edge* edge, std::vector* depfile_ins, std::string* err) { + for (std::vector::iterator i = depfile_ins->begin(); + i != depfile_ins->end(); ++i) { + uint64_t slash_bits; + if (!CanonicalizePath(const_cast(i->str_), &i->len_, &slash_bits, + err)) + return false; + Node* node = state_->GetNode(*i, slash_bits); + dep_nodes_output_->push_back(node); + } + return true; +} + +} // namespace + MissingDependencyScannerDelegate::~MissingDependencyScannerDelegate() {} void MissingDependencyPrinter::OnMissingDep(Node* node, const std::string& path, @@ -37,8 +75,7 @@ MissingDependencyScanner::MissingDependencyScanner( MissingDependencyScannerDelegate* delegate, DepsLog* deps_log, State* state, DiskInterface* disk_interface) : delegate_(delegate), deps_log_(deps_log), state_(state), - disk_interface_(disk_interface), missing_dep_path_count_(0) { -} + disk_interface_(disk_interface), missing_dep_path_count_(0) {} void MissingDependencyScanner::ProcessNode(Node* node) { if (!node) @@ -61,14 +98,11 @@ void MissingDependencyScanner::ProcessNode(Node* node) { ProcessNodeDeps(node, deps->nodes, deps->node_count); } else { DepfileParserOptions parser_opts; - ImplicitDepNodeLoader dep_loader(state_, deps_log_, disk_interface_, - &parser_opts); - std::string depfile = edge->GetUnescapedDepfile(); - if (depfile.empty()) - return; - std::string err; std::vector depfile_deps; - dep_loader.LoadDepfileDepNodes(edge, depfile, &depfile_deps, &err); + NodeStoringImplicitDepLoader dep_loader(state_, deps_log_, disk_interface_, + &parser_opts, &depfile_deps); + std::string err; + dep_loader.LoadDeps(edge, &err); if (!depfile_deps.empty()) ProcessNodeDeps(node, &depfile_deps[0], depfile_deps.size()); } diff --git a/src/missing_deps_test.cc b/src/missing_deps_test.cc index d543c9f383..7b62e6cc48 100644 --- a/src/missing_deps_test.cc +++ b/src/missing_deps_test.cc @@ -154,7 +154,7 @@ TEST_F(MissingDependencyScannerTest, CycleInGraph) { CreateGraphDependencyBetween("generated_header", "compiled_object"); // The missing-deps tool doesn't deal with cycles in the graph, beacuse // there will be an error loading the graph before we get to the tool. - // This test is to illstrate that. + // This test is to illustrate that. std::string err; std::vector nodes = state_.RootNodes(&err); ASSERT_NE("", err);