From fab3e5a04b271fa23400d58a838940f87300bc64 Mon Sep 17 00:00:00 2001 From: Dieter Baron Date: Sat, 25 May 2024 14:01:03 +0200 Subject: [PATCH] Fix include dependency tracking. --- src/File.cc | 8 ++++++-- src/File.h | 2 +- src/Filename.cc | 15 +++++++++++++-- src/Filename.h | 4 ++++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/File.cc b/src/File.cc index 19a0190..c0c47e3 100644 --- a/src/File.cc +++ b/src/File.cc @@ -207,8 +207,11 @@ void File::parse(const std::filesystem::path& filename) { case Tokenizer::TokenType::INCLUDE: { auto name = tokenizer.expect(Tokenizer::TokenType::WORD, Tokenizer::Skip::SPACE); - includes.insert(name.string()); - tokenizers.emplace_back(name.string()); + auto include_filename = Filename(Filename::Type::SOURCE, name.string()); + auto result = ResolveResult(); + include_filename.resolve(ResolveContext(*this, result)); + includes.insert(include_filename); + tokenizers.emplace_back(include_filename.full_name().string()); break; } @@ -295,6 +298,7 @@ void File::parse_subninja(Tokenizer& tokenizer) { void File::add_generator_build(std::vector& ninja_outputs, std::vector& ninja_inputs) const { // NOLINT(misc-no-recursion) ninja_outputs.emplace_back(Filename::Type::BUILD, build_filename.string()); + ninja_inputs.insert(ninja_inputs.end(), includes.begin(), includes.end()); ninja_inputs.emplace_back(Filename::Type::COMPLETE, source_filename.string()); for (const auto& file: subfiles) { file->add_generator_build(ninja_outputs, ninja_inputs); diff --git a/src/File.h b/src/File.h index c5e1151..d03acd9 100644 --- a/src/File.h +++ b/src/File.h @@ -83,7 +83,7 @@ class File: public Scope { std::filesystem::path build_filename; std::unordered_set outputs; - std::set includes; + std::set includes; std::map rules; std::map pools; std::vector builds; diff --git a/src/Filename.cc b/src/Filename.cc index d4d6c9c..1248ac9 100644 --- a/src/Filename.cc +++ b/src/Filename.cc @@ -52,7 +52,9 @@ void Filename::resolve(const ResolveContext& context) { switch (type) { case Type::BUILD: - prefix = file->build_directory; + if (prefix.empty()) { + prefix = file->build_directory; + } break; case Type::COMPLETE: @@ -60,7 +62,9 @@ void Filename::resolve(const ResolveContext& context) { break; case Type::SOURCE: - prefix = file->source_directory; + if (prefix.empty()) { + prefix = file->source_directory; + } if (!std::filesystem::exists(full_name())) { throw Exception("source file '" + full_name().string() + "' does not exist"); } @@ -80,6 +84,13 @@ std::filesystem::path Filename::full_name() const { } } +bool Filename::operator<(const Filename& other) const { + if (type != other.type) { + return type < other.type; + } + return name < other.name; +} + std::ostream& operator<<(std::ostream& stream, const Filename& file_name) { stream << file_name.full_name().generic_string(); return stream; diff --git a/src/Filename.h b/src/Filename.h index 14280ec..f7f523e 100644 --- a/src/Filename.h +++ b/src/Filename.h @@ -55,6 +55,10 @@ class Filename { [[nodiscard]] std::filesystem::path full_name() const; + // TODO: consider prefix? + bool operator<(const Filename& other) const; + bool operator==(const Filename& other) const {return type == other.type && name == other.name;} + Type type{Type::UNKNOWN}; std::string name; std::filesystem::path prefix;