From c1699fe9b5238392c8fe565935c2bfcf1e125953 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 22 Jun 2026 03:34:11 +0800 Subject: [PATCH 1/2] fix(build): self-heal stale build.ninja on 'missing and no known rule' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a dependency package under the registry is reinstalled/moved but keeps the same version string, the build fingerprint (which does not yet cover registry dep state) is unchanged, so the cached build.ninja is reused. Ninja then aborts with 'missing and no known rule to make it' and the build hard-fails, forcing the user to run `mcpp clean` by hand. Add that signature to is_stale_ninja_failure so try_fast_build drops to a full graph regeneration (same invocation) instead of failing — the stale graph is rewritten against the current dep state and the build proceeds. (Folding registry dep state into the fingerprint to avoid the regen entirely is a larger follow-up; see .agents/docs/2026-06-22 §T-j.) --- src/build/execute.cppm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/build/execute.cppm b/src/build/execute.cppm index 6073065..784548a 100644 --- a/src/build/execute.cppm +++ b/src/build/execute.cppm @@ -155,7 +155,14 @@ bool is_stale_ninja_failure(std::string_view output) { return output.find("loading 'build.ninja'") != std::string_view::npos || output.find("loading build.ninja") != std::string_view::npos || output.find("unknown target") != std::string_view::npos - || output.find("manifest 'build.ninja' still dirty") != std::string_view::npos; + || output.find("manifest 'build.ninja' still dirty") != std::string_view::npos + // A cached build.ninja can reference an input (e.g. a dependency + // source under the registry) that moved or was reinstalled since the + // graph was generated — the build fingerprint does not yet cover + // registry dep state, so the stale graph is reused. Ninja then aborts + // with this signature. Treat it as stale → drop to a full regen + // instead of hard-failing and forcing the user to `mcpp clean`. + || output.find("missing and no known rule to make") != std::string_view::npos; } // Compile a prepared BuildContext. Shared between `mcpp build` and `mcpp run` From 7fb33bc609808f9dddd86b254db1d14c5b876153 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 22 Jun 2026 03:34:11 +0800 Subject: [PATCH 2/2] chore: bump version 0.0.57 -> 0.0.58 Release carrying the follow-up batch: scanner raw-string fix (#138), first-run progress (#139), toolchain effective-resolution (#140), doctor runtime-dep check (#141), and the build.ninja self-heal above. --- mcpp.toml | 2 +- src/toolchain/fingerprint.cppm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mcpp.toml b/mcpp.toml index e199bf4..6d35463 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,6 +1,6 @@ [package] name = "mcpp" -version = "0.0.57" +version = "0.0.58" description = "Modern C++ build & package management tool" license = "Apache-2.0" authors = ["mcpp-community"] diff --git a/src/toolchain/fingerprint.cppm b/src/toolchain/fingerprint.cppm index 1dd4d04..e65f553 100644 --- a/src/toolchain/fingerprint.cppm +++ b/src/toolchain/fingerprint.cppm @@ -18,7 +18,7 @@ import mcpp.toolchain.detect; export namespace mcpp::toolchain { -inline constexpr std::string_view MCPP_VERSION = "0.0.57"; +inline constexpr std::string_view MCPP_VERSION = "0.0.58"; struct FingerprintInputs { Toolchain toolchain;