| 640 | }; |
| 641 | |
| 642 | bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path, |
| 643 | string* err) { |
| 644 | METRIC_RECORD("depfile load"); |
| 645 | // Read depfile content. Treat a missing depfile as empty. |
| 646 | string content; |
| 647 | switch (disk_interface_->ReadFile(path, &content, err)) { |
| 648 | case DiskInterface::Okay: |
| 649 | break; |
| 650 | case DiskInterface::NotFound: |
| 651 | err->clear(); |
| 652 | break; |
| 653 | case DiskInterface::OtherError: |
| 654 | *err = "loading '" + path + "': " + *err; |
| 655 | return false; |
| 656 | } |
| 657 | // On a missing depfile: return false and empty *err. |
| 658 | Node* first_output = edge->outputs_[0]; |
| 659 | if (content.empty()) { |
| 660 | explanations_.Record(first_output, "depfile '%s' is missing", path.c_str()); |
| 661 | return false; |
| 662 | } |
| 663 | |
| 664 | DepfileParser depfile(depfile_parser_options_ |
| 665 | ? *depfile_parser_options_ |
| 666 | : DepfileParserOptions()); |
| 667 | string depfile_err; |
| 668 | if (!depfile.Parse(&content, &depfile_err)) { |
| 669 | *err = path + ": " + depfile_err; |
| 670 | return false; |
| 671 | } |
| 672 | |
| 673 | if (depfile.outs_.empty()) { |
| 674 | *err = path + ": no outputs declared"; |
| 675 | return false; |
| 676 | } |
| 677 | |
| 678 | uint64_t unused; |
| 679 | std::vector<StringPiece>::iterator primary_out = depfile.outs_.begin(); |
| 680 | CanonicalizePath(const_cast<char*>(primary_out->str_), &primary_out->len_, |
| 681 | &unused); |
| 682 | |
| 683 | // Check that this depfile matches the edge's output, if not return false to |
| 684 | // mark the edge as dirty. |
| 685 | StringPiece opath = StringPiece(first_output->path()); |
| 686 | if (opath != *primary_out) { |
| 687 | explanations_.Record(first_output, |
| 688 | "expected depfile '%s' to mention '%s', got '%s'", |
| 689 | path.c_str(), first_output->path().c_str(), |
| 690 | primary_out->AsString().c_str()); |
| 691 | return false; |
| 692 | } |
| 693 | |
| 694 | // Ensure that all mentioned outputs are outputs of the edge. |
| 695 | for (std::vector<StringPiece>::iterator o = depfile.outs_.begin(); |
| 696 | o != depfile.outs_.end(); ++o) { |
| 697 | matches m(o); |
| 698 | if (std::find_if(edge->outputs_.begin(), edge->outputs_.end(), m) == edge->outputs_.end()) { |
| 699 | *err = path + ": depfile mentions '" + o->AsString() + "' as an output, but no such output was declared"; |
nothing calls this directly
no test coverage detected