remove CanonicalizePath overloads, test for toplevel behaviour
authorScott Graham <scottmg@chromium.org>
Sun, 9 Nov 2014 06:49:21 +0000 (22:49 -0800)
committerScott Graham <scottmg@chromium.org>
Sun, 9 Nov 2014 06:49:21 +0000 (22:49 -0800)
src/build.cc
src/build_test.cc
src/canon_perftest.cc
src/graph.cc
src/includes_normalize-win32.cc
src/manifest_parser.cc
src/ninja.cc
src/util.cc
src/util.h
src/util_test.cc

index fb1cc74..a5f5fe8 100644 (file)
@@ -850,9 +850,11 @@ bool Builder::ExtractDeps(CommandRunner::Result* result,
     deps_nodes->reserve(deps.ins_.size());
     for (vector<StringPiece>::iterator i = deps.ins_.begin();
          i != deps.ins_.end(); ++i) {
-      if (!CanonicalizePath(const_cast<char*>(i->str_), &i->len_, err))
+      unsigned int slash_bits;
+      if (!CanonicalizePath(const_cast<char*>(i->str_), &i->len_, err,
+                            &slash_bits))
         return false;
-      deps_nodes->push_back(state_->GetNode(*i));
+      deps_nodes->push_back(state_->GetNode(*i, slash_bits));
     }
 
     if (disk_interface_->RemoveFile(depfile) < 0) {
index 5d6c4e9..f25dd5f 100644 (file)
@@ -937,6 +937,35 @@ TEST_F(BuildTest, RebuildOrderOnlyDeps) {
   ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]);
 }
 
+#ifdef _WIN32
+TEST_F(BuildTest, DepFileCanonicalize) {
+  string err;
+  int orig_edges = state_.edges_.size();
+  ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
+"rule cc\n  command = cc $in\n  depfile = $out.d\n"
+"build gen/stuff/foo.o: cc foo.c\n"));
+  Edge* edge = state_.edges_.back();
+
+  fs_.Create("foo.c", "");
+  GetNode("bar.h")->MarkDirty();  // Mark bar.h as missing.
+  // Note, different slashes from manifest.
+  fs_.Create("gen/stuff/foo.o.d", "gen\\stuff\\foo.o: blah.h bar.h\n");
+  EXPECT_TRUE(builder_.AddTarget("gen/stuff/foo.o", &err));
+  ASSERT_EQ("", err);
+  ASSERT_EQ(1u, fs_.files_read_.size());
+  EXPECT_EQ("gen/stuff/foo.o.d", fs_.files_read_[0]);
+
+  // Expect three new edges: one generating foo.o, and two more from
+  // loading the depfile.
+  ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size());
+  // Expect our edge to now have three inputs: foo.c and two headers.
+  ASSERT_EQ(3u, edge->inputs_.size());
+
+  // Expect the command line we generate to only use the original input.
+  ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
+}
+#endif
+
 TEST_F(BuildTest, Phony) {
   string err;
   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
index 59bd18f..8defa91 100644 (file)
@@ -33,8 +33,9 @@ int main() {
   for (int j = 0; j < 5; ++j) {
     const int kNumRepetitions = 2000000;
     int64_t start = GetTimeMillis();
+    unsigned int slash_bits;
     for (int i = 0; i < kNumRepetitions; ++i) {
-      CanonicalizePath(buf, &len, &err);
+      CanonicalizePath(buf, &len, &err, &slash_bits);
     }
     int delta = (int)(GetTimeMillis() - start);
     times.push_back(delta);
index 5bc5c00..8666f50 100644 (file)
@@ -391,6 +391,11 @@ bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path,
     return false;
   }
 
+  unsigned int unused;
+  if (!CanonicalizePath(const_cast<char*>(depfile.out_.str_),
+                        &depfile.out_.len_, err, &unused))
+    return false;
+
   // Check that this depfile matches the edge's output.
   Node* first_output = edge->outputs_[0];
   StringPiece opath = StringPiece(first_output->path());
@@ -407,10 +412,12 @@ bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path,
   // Add all its in-edges.
   for (vector<StringPiece>::iterator i = depfile.ins_.begin();
        i != depfile.ins_.end(); ++i, ++implicit_dep) {
-    if (!CanonicalizePath(const_cast<char*>(i->str_), &i->len_, err))
+    unsigned int slash_bits;
+    if (!CanonicalizePath(const_cast<char*>(i->str_), &i->len_, err,
+                          &slash_bits))
       return false;
 
-    Node* node = state_->GetNode(*i);
+    Node* node = state_->GetNode(*i, slash_bits);
     *implicit_dep = node;
     node->AddOutEdge(edge);
     CreatePhonyInEdge(node);
index 0d230f8..7ea2813 100644 (file)
@@ -100,7 +100,8 @@ string IncludesNormalize::Normalize(const string& input,
   size_t len = input.size();
   strncpy(copy, input.c_str(), input.size() + 1);
   string err;
-  if (!CanonicalizePath(copy, &len, &err))
+  unsigned int slash_bits;
+  if (!CanonicalizePath(copy, &len, &err, &slash_bits))
     Warning("couldn't canonicalize '%s': %s\n", input.c_str(), err.c_str());
   StringPiece partially_fixed(copy, len);
 
index 81a191e..16214f1 100644 (file)
@@ -209,7 +209,8 @@ bool ManifestParser::ParseDefault(string* err) {
   do {
     string path = eval.Evaluate(env_);
     string path_err;
-    if (!CanonicalizePath(&path, &path_err))
+    unsigned int slash_bits;  // Unused because this only does lookup.
+    if (!CanonicalizePath(&path, &path_err, &slash_bits))
       return lexer_.Error(path_err, err);
     if (!state_->AddDefault(path, &path_err))
       return lexer_.Error(path_err, err);
index 4368fab..5831e26 100644 (file)
@@ -228,7 +228,8 @@ struct RealFileReader : public ManifestParser::FileReader {
 /// Returns true if the manifest was rebuilt.
 bool NinjaMain::RebuildManifest(const char* input_file, string* err) {
   string path = input_file;
-  if (!CanonicalizePath(&path, err))
+  unsigned int slash_bits;  // Unused because this path is only used for lookup.
+  if (!CanonicalizePath(&path, err, &slash_bits))
     return false;
   Node* node = state_.LookupNode(path);
   if (!node)
@@ -250,7 +251,8 @@ bool NinjaMain::RebuildManifest(const char* input_file, string* err) {
 
 Node* NinjaMain::CollectTarget(const char* cpath, string* err) {
   string path = cpath;
-  if (!CanonicalizePath(&path, err))
+  unsigned int slash_bits;  // Unused because this path is only used for lookup.
+  if (!CanonicalizePath(&path, err, &slash_bits))
     return NULL;
 
   // Special syntax: "foo.cc^" means "the first output of foo.cc".
index 9cf736e..cccf59c 100644 (file)
@@ -85,11 +85,6 @@ void Error(const char* msg, ...) {
   fprintf(stderr, "\n");
 }
 
-bool CanonicalizePath(string* path, string* err) {
-  unsigned int unused;
-  return CanonicalizePath(path, err, &unused);
-}
-
 bool CanonicalizePath(string* path, string* err, unsigned int* slash_bits) {
   METRIC_RECORD("canonicalize str");
   size_t len = path->size();
@@ -102,11 +97,6 @@ bool CanonicalizePath(string* path, string* err, unsigned int* slash_bits) {
   return true;
 }
 
-bool CanonicalizePath(char* path, size_t* len, string* err) {
-  unsigned int unused;
-  return CanonicalizePath(path, len, err, &unused);
-}
-
 unsigned int ShiftOverBit(int offset, unsigned int bits) {
   // e.g. for |offset| == 2:
   // | ... 9 8 7 6 5 4 3 2 1 0 |
index 36f31f3..cb0de09 100644 (file)
@@ -41,10 +41,6 @@ void Warning(const char* msg, ...);
 void Error(const char* msg, ...);
 
 /// Canonicalize a path like "foo/../bar.h" into just "bar.h".
-bool CanonicalizePath(string* path, string* err);
-
-bool CanonicalizePath(char* path, size_t* len, string* err);
-
 /// |slash_bits| has bits set starting from lowest for a backslash that was
 /// normalized to a forward slash. (only used on Windows)
 bool CanonicalizePath(string* path, string* err, unsigned int* slash_bits);
index d047d9c..82db6d2 100644 (file)
 
 #include "test.h"
 
+namespace {
+
+bool CanonicalizePath(string* path, string* err) {
+  unsigned int unused;
+  return ::CanonicalizePath(path, err, &unused);
+}
+
+}  // namespace
+
 TEST(CanonicalizePath, PathSamples) {
   string path;
   string err;
@@ -275,16 +284,17 @@ TEST(CanonicalizePath, NotNullTerminated) {
   string path;
   string err;
   size_t len;
+  unsigned int unused;
 
   path = "foo/. bar/.";
   len = strlen("foo/.");  // Canonicalize only the part before the space.
-  EXPECT_TRUE(CanonicalizePath(&path[0], &len, &err));
+  EXPECT_TRUE(CanonicalizePath(&path[0], &len, &err, &unused));
   EXPECT_EQ(strlen("foo"), len);
   EXPECT_EQ("foo/. bar/.", string(path));
 
   path = "foo/../file bar/.";
   len = strlen("foo/../file");
-  EXPECT_TRUE(CanonicalizePath(&path[0], &len, &err));
+  EXPECT_TRUE(CanonicalizePath(&path[0], &len, &err, &unused));
   EXPECT_EQ(strlen("file"), len);
   EXPECT_EQ("file ./file bar/.", string(path));
 }