Skip to content

Commit ffe0a96

Browse files
committed
fix: build cache must invalidate when --target changes
The P0 fast-path build cache (target/.build_cache) only checked source file and mcpp.toml timestamps. When `mcpp build --target x86_64-linux-musl` was followed by a plain `mcpp build`, the fast-path reused the musl build.ninja — producing no GNU binary. Fix: store the user's --target value as a third line in .build_cache. try_fast_build() now compares the cached target against the current request and falls back to a full rebuild on mismatch. Also fix the test: detect installed GNU gcc dynamically and pin it in [toolchain].linux so the default build uses GNU, not musl auto-install.
1 parent 7ad0e93 commit ffe0a96

2 files changed

Lines changed: 17 additions & 18 deletions

File tree

src/cli.cppm

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2039,21 +2039,24 @@ constexpr std::string_view kBuildCacheFile = "target/.build_cache";
20392039

20402040
void write_build_cache(const std::filesystem::path& projectRoot,
20412041
const std::filesystem::path& outputDir,
2042-
const std::string& ninjaProgram) {
2042+
const std::string& ninjaProgram,
2043+
const std::string& targetTriple) {
20432044
auto path = projectRoot / kBuildCacheFile;
20442045
std::error_code ec;
20452046
std::filesystem::create_directories(path.parent_path(), ec);
20462047
std::ofstream f(path, std::ios::trunc);
20472048
if (f) {
20482049
f << outputDir.string() << '\n';
20492050
f << ninjaProgram << '\n';
2051+
f << targetTriple << '\n';
20502052
}
20512053
}
20522054

20532055
// Compile a prepared BuildContext. Shared between `mcpp build` and `mcpp run`
20542056
// so the latter doesn't call prepare_build twice (and re-print the toolchain
20552057
// resolution banner).
2056-
int run_build_plan(BuildContext& ctx, bool verbose, bool no_cache) {
2058+
int run_build_plan(BuildContext& ctx, bool verbose, bool no_cache,
2059+
std::string_view targetOverride = "") {
20572060
if (no_cache) {
20582061
std::error_code ec;
20592062
std::filesystem::remove_all(ctx.outputDir, ec);
@@ -2106,7 +2109,8 @@ int run_build_plan(BuildContext& ctx, bool verbose, bool no_cache) {
21062109

21072110
// P0: save build cache for fast-path on next invocation.
21082111
if (!no_cache && !r->ninjaProgram.empty()) {
2109-
write_build_cache(ctx.projectRoot, ctx.outputDir, r->ninjaProgram);
2112+
write_build_cache(ctx.projectRoot, ctx.outputDir, r->ninjaProgram,
2113+
std::string(targetOverride));
21102114
}
21112115

21122116
mcpp::ui::finished("release", r->elapsed);
@@ -2125,17 +2129,24 @@ int run_build_plan(BuildContext& ctx, bool verbose, bool no_cache) {
21252129
// Try to fast-path: if build.ninja is newer than all inputs, just run ninja.
21262130
// Returns exit code on fast-path, or nullopt if full rebuild needed.
21272131
std::optional<int> try_fast_build(const std::filesystem::path& projectRoot,
2128-
bool verbose, bool no_cache) {
2132+
bool verbose, bool no_cache,
2133+
std::string_view currentTarget = "") {
21292134
if (no_cache) return std::nullopt;
21302135

21312136
auto cachePath = projectRoot / kBuildCacheFile;
21322137
std::error_code ec;
21332138
if (!std::filesystem::exists(cachePath, ec)) return std::nullopt;
21342139

21352140
std::ifstream f(cachePath);
2136-
std::string outputDirStr, ninjaProgram;
2141+
std::string outputDirStr, ninjaProgram, cachedTarget;
21372142
if (!std::getline(f, outputDirStr) || outputDirStr.empty()) return std::nullopt;
21382143
if (!std::getline(f, ninjaProgram) || ninjaProgram.empty()) return std::nullopt;
2144+
std::getline(f, cachedTarget); // may be empty for old cache files
2145+
2146+
// Reject cache if target triple changed (e.g. previous build used
2147+
// --target x86_64-linux-musl but this one is a default build).
2148+
if (cachedTarget != currentTarget) return std::nullopt;
2149+
21392150
std::filesystem::path outputDir(outputDirStr);
21402151

21412152
auto ninjaPath = outputDir / "build.ninja";
@@ -2214,7 +2225,7 @@ int cmd_build(const mcpplibs::cmdline::ParsedArgs& parsed) {
22142225
auto ctx = prepare_build(print_fp, /*includeDevDeps=*/false, /*extraTargets=*/{}, ov);
22152226
if (!ctx) { std::println(stderr, "error: {}", ctx.error()); return 2; }
22162227

2217-
return run_build_plan(*ctx, verbose, no_cache);
2228+
return run_build_plan(*ctx, verbose, no_cache, ov.target_triple);
22182229
}
22192230

22202231
int cmd_run(const mcpplibs::cmdline::ParsedArgs& parsed,

tests/e2e/28_target_static.sh

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,6 @@ if [[ -d "$XPKGS/xim-x-gcc" ]]; then
2828
GNU_GCC_VER=$(ls "$XPKGS/xim-x-gcc" 2>/dev/null | sort -V | tail -1)
2929
fi
3030

31-
# Diagnostic: show what we detected
32-
echo "DIAG: MCPP_HOME=${MCPP_HOME:-<unset>}"
33-
echo "DIAG: XPKGS=$XPKGS"
34-
echo "DIAG: GNU_GCC_VER=${GNU_GCC_VER:-<empty>}"
35-
echo "DIAG: xim-x-gcc contents: $(ls "$XPKGS/xim-x-gcc" 2>&1 || echo 'N/A')"
36-
echo "DIAG: config.toml toolchain line: $(grep -i toolchain "${MCPP_HOME:-$HOME/.mcpp}/config.toml" 2>/dev/null || echo 'none')"
37-
3831
TMP=$(mktemp -d)
3932
trap "rm -rf $TMP" EXIT
4033

@@ -64,9 +57,6 @@ linkage = "static"
6457
EOF
6558
fi
6659

67-
echo "DIAG: mcpp.toml:"
68-
cat mcpp.toml
69-
7060
"$MCPP" build --target x86_64-linux-musl > build.log 2>&1 || {
7161
cat build.log; echo "build failed"; exit 1; }
7262

@@ -96,8 +86,6 @@ fi
9686
if [[ -n "$GNU_GCC_VER" ]]; then
9787
"$MCPP" build > build-gnu.log 2>&1 || {
9888
cat build-gnu.log; echo "default GNU build broke after musl build"; exit 1; }
99-
echo "DIAG: target/ tree after GNU build:"
100-
find target -type f -name staticapp 2>&1
10189
gnu_binary=$(find target -type d -name x86_64-linux-musl -prune -o -type f -name staticapp -print | head -1)
10290
[[ -n "$gnu_binary" ]] || { echo "default GNU binary missing"; exit 1; }
10391
else

0 commit comments

Comments
 (0)