Skip to content

Commit

Permalink
clean: remove outputs specified by dyndep files
Browse files Browse the repository at this point in the history
Some outputs may not be known in the main build manifest and are instead
discovered through a dyndep binding.  Load dyndep files that are
available during cleaning so that we can clean these outputs too.
  • Loading branch information
bradking committed Apr 18, 2019
1 parent c21f3f2 commit a3cbb4d
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/clean.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Cleaner::Cleaner(State* state,
DiskInterface* disk_interface)
: state_(state),
config_(config),
dyndep_loader_(state, disk_interface),
removed_(),
cleaned_(),
cleaned_files_count_(0),
Expand Down Expand Up @@ -103,6 +104,7 @@ void Cleaner::PrintFooter() {
int Cleaner::CleanAll(bool generator) {
Reset();
PrintHeader();
LoadDyndeps();
for (vector<Edge*>::iterator e = state_->edges_.begin();
e != state_->edges_.end(); ++e) {
// Do not try to remove phony targets
Expand Down Expand Up @@ -148,6 +150,7 @@ int Cleaner::CleanTarget(Node* target) {

Reset();
PrintHeader();
LoadDyndeps();
DoCleanTarget(target);
PrintFooter();
return status_;
Expand All @@ -170,6 +173,7 @@ int Cleaner::CleanTarget(const char* target) {
int Cleaner::CleanTargets(int target_count, char* targets[]) {
Reset();
PrintHeader();
LoadDyndeps();
for (int i = 0; i < target_count; ++i) {
string target_name = targets[i];
uint64_t slash_bits;
Expand Down Expand Up @@ -213,6 +217,7 @@ int Cleaner::CleanRule(const Rule* rule) {

Reset();
PrintHeader();
LoadDyndeps();
DoCleanRule(rule);
PrintFooter();
return status_;
Expand All @@ -237,6 +242,7 @@ int Cleaner::CleanRules(int rule_count, char* rules[]) {

Reset();
PrintHeader();
LoadDyndeps();
for (int i = 0; i < rule_count; ++i) {
const char* rule_name = rules[i];
const Rule* rule = state_->bindings_.LookupRule(rule_name);
Expand All @@ -259,3 +265,16 @@ void Cleaner::Reset() {
removed_.clear();
cleaned_.clear();
}

void Cleaner::LoadDyndeps() {
// Load dyndep files that exist, before they are cleaned.
for (vector<Edge*>::iterator e = state_->edges_.begin();
e != state_->edges_.end(); ++e) {
if (Node* dyndep = (*e)->dyndep_) {
// Capture and ignore errors loading the dyndep file.
// We clean as much of the graph as we know.
std::string err;
dyndep_loader_.LoadDyndeps(dyndep, &err);
}
}
}
5 changes: 5 additions & 0 deletions src/clean.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <string>

#include "build.h"
#include "dyndep.h"

using namespace std;

Expand Down Expand Up @@ -91,8 +92,12 @@ struct Cleaner {
void DoCleanRule(const Rule* rule);
void Reset();

/// Load dependencies from dyndep bindings.
void LoadDyndeps();

State* state_;
const BuildConfig& config_;
DyndepLoader dyndep_loader_;
set<string> removed_;
set<Node*> cleaned_;
int cleaned_files_count_;
Expand Down
49 changes: 49 additions & 0 deletions src/clean_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,55 @@ TEST_F(CleanTest, CleanDepFileOnCleanRule) {
EXPECT_EQ(2u, fs_.files_removed_.size());
}

TEST_F(CleanTest, CleanDyndep) {
// Verify that a dyndep file can be loaded to discover a new output
// to be cleaned.
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
"build out: cat in || dd\n"
" dyndep = dd\n"
));
fs_.Create("in", "");
fs_.Create("dd",
"ninja_dyndep_version = 1\n"
"build out | out.imp: dyndep\n"
);
fs_.Create("out", "");
fs_.Create("out.imp", "");

Cleaner cleaner(&state_, config_, &fs_);

ASSERT_EQ(0, cleaner.cleaned_files_count());
EXPECT_EQ(0, cleaner.CleanAll());
EXPECT_EQ(2, cleaner.cleaned_files_count());
EXPECT_EQ(2u, fs_.files_removed_.size());

string err;
EXPECT_EQ(0, fs_.Stat("out", &err));
EXPECT_EQ(0, fs_.Stat("out.imp", &err));
}

TEST_F(CleanTest, CleanDyndepMissing) {
// Verify that a missing dyndep file is tolerated.
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
"build out: cat in || dd\n"
" dyndep = dd\n"
));
fs_.Create("in", "");
fs_.Create("out", "");
fs_.Create("out.imp", "");

Cleaner cleaner(&state_, config_, &fs_);

ASSERT_EQ(0, cleaner.cleaned_files_count());
EXPECT_EQ(0, cleaner.CleanAll());
EXPECT_EQ(1, cleaner.cleaned_files_count());
EXPECT_EQ(1u, fs_.files_removed_.size());

string err;
EXPECT_EQ(0, fs_.Stat("out", &err));
EXPECT_EQ(1, fs_.Stat("out.imp", &err));
}

TEST_F(CleanTest, CleanRspFile) {
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
"rule cc\n"
Expand Down

0 comments on commit a3cbb4d

Please sign in to comment.