Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/build/ninja_backend.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,7 @@ std::string emit_ninja_string(const BuildPlan& plan) {
"-fdeps-file=$out -fdeps-target=$compile_target "
"-M -MM -MF $out.dep -E $in -o $compile_target\n");
} else {
// Clang path: clang-scan-deps produces P1689 JSON to stdout,
// then we redirect to $out. The -- separator passes the full
// compile command so clang-scan-deps knows the flags/sysroot.
// Clang path: clang-scan-deps produces P1689 JSON to stdout.
append(" command = $toolenv $scan_deps -format=p1689 -- "
"$cxx $cxxflags -c $in -o $compile_target > $out\n");
}
Expand Down
42 changes: 38 additions & 4 deletions src/cli.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -2106,7 +2106,8 @@ constexpr std::string_view kBuildCacheFile = "target/.build_cache";
void write_build_cache(const std::filesystem::path& projectRoot,
const std::filesystem::path& outputDir,
const std::string& ninjaProgram,
const std::string& targetTriple) {
const std::string& targetTriple,
const std::string& fingerprintHex = "") {
auto path = projectRoot / kBuildCacheFile;
std::error_code ec;
std::filesystem::create_directories(path.parent_path(), ec);
Expand All @@ -2115,6 +2116,7 @@ void write_build_cache(const std::filesystem::path& projectRoot,
f << outputDir.string() << '\n';
f << ninjaProgram << '\n';
f << targetTriple << '\n';
f << fingerprintHex << '\n';
}
}

Expand Down Expand Up @@ -2173,10 +2175,27 @@ int run_build_plan(BuildContext& ctx, bool verbose, bool no_cache,
}
}

// P1.5: warn if fingerprint changed from last build (explains full rebuild).
{
auto cachePath = ctx.projectRoot / kBuildCacheFile;
std::ifstream cf(cachePath);
std::string oldDir;
if (std::getline(cf, oldDir) && !oldDir.empty()) {
auto oldFp = std::filesystem::path(oldDir).filename().string();
auto newFp = ctx.outputDir.filename().string();
if (oldFp != newFp) {
mcpp::ui::warning(std::format(
"fingerprint changed ({} → {}), full rebuild",
oldFp, newFp));
}
}
}

// P0: save build cache for fast-path on next invocation.
if (!no_cache && !r->ninjaProgram.empty()) {
auto fpHex = ctx.outputDir.filename().string();
write_build_cache(ctx.projectRoot, ctx.outputDir, r->ninjaProgram,
std::string(targetOverride));
std::string(targetOverride), fpHex);
}

mcpp::ui::finished("release", r->elapsed);
Expand Down Expand Up @@ -2204,15 +2223,30 @@ std::optional<int> try_fast_build(const std::filesystem::path& projectRoot,
if (!std::filesystem::exists(cachePath, ec)) return std::nullopt;

std::ifstream f(cachePath);
std::string outputDirStr, ninjaProgram, cachedTarget;
std::string outputDirStr, ninjaProgram, cachedTarget, cachedFingerprint;
if (!std::getline(f, outputDirStr) || outputDirStr.empty()) return std::nullopt;
if (!std::getline(f, ninjaProgram) || ninjaProgram.empty()) return std::nullopt;
std::getline(f, cachedTarget); // may be empty for old cache files
std::getline(f, cachedTarget); // may be empty for old cache files
std::getline(f, cachedFingerprint); // may be empty for pre-0.0.15 caches

// Reject cache if target triple changed (e.g. previous build used
// --target x86_64-linux-musl but this one is a default build).
if (cachedTarget != currentTarget) return std::nullopt;

// P1: verify fingerprint matches the outputDir basename. If someone
// switched mcpp installations (different toolchain binary), the cached
// outputDir points to a stale fingerprint directory. Detect and reject.
if (!cachedFingerprint.empty()) {
std::filesystem::path outputDir(outputDirStr);
auto dirBasename = outputDir.filename().string();
if (dirBasename != cachedFingerprint) {
// Cache is inconsistent — invalidate it.
std::error_code ec2;
std::filesystem::remove(cachePath, ec2);
return std::nullopt;
}
}

std::filesystem::path outputDir(outputDirStr);

auto ninjaPath = outputDir / "build.ninja";
Expand Down
Loading