From 8f6bba60e63e3444d676cade591cc44351ddb6c4 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Fri, 15 May 2026 20:33:22 +0800 Subject: [PATCH] test: add Clang incremental rebuild and BMI cache E2E tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 39_llvm_incremental.sh — verifies per-file dyndep with clang-scan-deps: touch one .cppm, only that file recompiles (not main.cpp) 40_llvm_bmi_cache.sh — verifies Clang BMI cache reuse: dependency package shows Cached on second build after target/ cleared --- tests/e2e/39_llvm_incremental.sh | 65 ++++++++++++++++++++++++++++++ tests/e2e/40_llvm_bmi_cache.sh | 69 ++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100755 tests/e2e/39_llvm_incremental.sh create mode 100755 tests/e2e/40_llvm_bmi_cache.sh diff --git a/tests/e2e/39_llvm_incremental.sh b/tests/e2e/39_llvm_incremental.sh new file mode 100755 index 0000000..d54a4e4 --- /dev/null +++ b/tests/e2e/39_llvm_incremental.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# 39_llvm_incremental.sh — Clang per-file incremental rebuild via clang-scan-deps dyndep. +set -e + +LLVM_ROOT="${HOME}/.mcpp/registry/data/xpkgs/xim-x-llvm/20.1.7" +if [[ ! -x "$LLVM_ROOT/bin/clang++" ]]; then + echo "SKIP: xlings llvm@20.1.7 is not installed" + exit 0 +fi +if [[ ! -f "$LLVM_ROOT/share/libc++/v1/std.cppm" ]]; then + echo "SKIP: xlings llvm@20.1.7 has no libc++ std.cppm" + exit 0 +fi + +TMP=$(mktemp -d) +trap "rm -rf $TMP" EXIT +export MCPP_HOME="$TMP/mcpp-home" +source "$(dirname "$0")/_inherit_toolchain.sh" + +mkdir -p "$TMP/proj/src" +cd "$TMP/proj" + +cat > mcpp.toml <<'EOF' +[package] +name = "llvm_inc" +version = "0.1.0" +[toolchain] +linux = "llvm@20.1.7" +EOF + +cat > src/greet.cppm <<'EOF' +export module llvm_inc.greet; +import std; +export std::string greet() { return "hello"; } +EOF + +cat > src/main.cpp <<'EOF' +import std; +import llvm_inc.greet; +int main() { std::println("{}", greet()); } +EOF + +# First build (full) +"$MCPP" build --no-cache > /dev/null 2>&1 + +# Second build (no-op) should be fast +out=$("$MCPP" build 2>&1) +[[ "$out" == *"Finished"* ]] || { echo "FAIL: no-op rebuild failed: $out"; exit 1; } + +# Touch greet.cppm only; rebuild should NOT recompile main.cpp +sleep 1 +touch src/greet.cppm +out=$("$MCPP" build --verbose 2>&1) +echo "$out" | grep -q "greet.cppm" || { echo "FAIL: greet.cppm not rebuilt: $out"; exit 1; } +# main.cpp should NOT appear in ninja output (it wasn't touched) +if echo "$out" | grep -q "MOD obj/main.o\|OBJ obj/main.o"; then + # Note: main.o MAY be relinked but should NOT be recompiled from source + # Check specifically for compilation (not linking) + if echo "$out" | grep -q "\-c.*main.cpp"; then + echo "FAIL: main.cpp was recompiled when only greet.cppm changed" + exit 1 + fi +fi + +echo "OK" diff --git a/tests/e2e/40_llvm_bmi_cache.sh b/tests/e2e/40_llvm_bmi_cache.sh new file mode 100755 index 0000000..5aadb5f --- /dev/null +++ b/tests/e2e/40_llvm_bmi_cache.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# 40_llvm_bmi_cache.sh — Clang BMI cache reuse for dependency packages. +set -e + +LLVM_ROOT="${HOME}/.mcpp/registry/data/xpkgs/xim-x-llvm/20.1.7" +if [[ ! -x "$LLVM_ROOT/bin/clang++" ]]; then + echo "SKIP: xlings llvm@20.1.7 is not installed" + exit 0 +fi +if [[ ! -f "$LLVM_ROOT/share/libc++/v1/std.cppm" ]]; then + echo "SKIP: xlings llvm@20.1.7 has no libc++ std.cppm" + exit 0 +fi + +TMP=$(mktemp -d) +trap "rm -rf $TMP" EXIT +export MCPP_HOME="$TMP/mcpp-home" +source "$(dirname "$0")/_inherit_toolchain.sh" + +# mcpplibs packages live in a separate registry namespace; inherit it so the +# index lookup for mcpplibs.cmdline succeeds in the isolated MCPP_HOME. +USER_MCPP="${HOME}/.mcpp" +if [[ -d "$USER_MCPP/registry/data/mcpplibs" ]]; then + mkdir -p "$MCPP_HOME/registry/data" + [[ -e "$MCPP_HOME/registry/data/mcpplibs" ]] \ + || ln -sf "$USER_MCPP/registry/data/mcpplibs" "$MCPP_HOME/registry/data/mcpplibs" +fi + +mkdir -p "$TMP/proj/src" +cd "$TMP/proj" + +cat > mcpp.toml <<'EOF' +[package] +name = "llvm_cache" +version = "0.1.0" +[toolchain] +linux = "llvm@20.1.7" +[dependencies] +"mcpplibs.cmdline" = "0.0.1" +EOF + +cat > src/main.cpp <<'EOF' +import std; +import mcpplibs.cmdline; +int main() { + std::println("cache test ok"); + return 0; +} +EOF + +# First build — should compile the dependency +out1=$("$MCPP" build --no-cache 2>&1) +echo "$out1" | grep -q "Compiling.*mcpplibs.cmdline" || { + # It's OK if it says "Cached" because global cache may exist + echo "$out1" | grep -q "Cached.*mcpplibs.cmdline" || { + echo "FAIL: mcpplibs.cmdline not mentioned in first build: $out1" + exit 1 + } +} + +# Second build (clean target, keep BMI cache) — dependency should be cached +rm -rf target +out2=$("$MCPP" build 2>&1) +echo "$out2" | grep -q "Cached.*mcpplibs.cmdline" || { + echo "FAIL: mcpplibs.cmdline not cached on second build: $out2" + exit 1 +} + +echo "OK"