From 077375c6e6352e49b60813f934fcaeddbe4dc896 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sat, 10 Oct 2026 07:18:01 +0900 Subject: [PATCH 1/2] test: read a build program's output directory from resolution.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mcpp 2026.10.10.1 gives each configuration and package its own build-program output directory (`target/.build-mcpp/out//`) and records it as the root package's `outDir` in resolution.json (mcpp#778, design 2026-10-10 §4). The checks that named `target/.build-mcpp/out` read it through tests/out-dir.sh, which falls back to that path for an engine that records none, so the collection measures the same on 2026.10.1.3. --- .github/workflows/ci.yml | 52 +++++++++---------- .../check-apk-libraries.sh | 5 +- tests/apk-consumer/check-apk-features.sh | 2 +- tests/metal-consumer/check-metal.sh | 2 +- tests/out-dir.sh | 19 +++++++ 5 files changed, 50 insertions(+), 30 deletions(-) create mode 100755 tests/out-dir.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 624208e..3942e92 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -253,9 +253,9 @@ jobs: # from one that does not; without the guard this is # `namespace default {` and the generated file does not parse. grep -q '^namespace default_ {' \ - target/.build-mcpp/out/spirv/shader_app.shaders.cppm \ + $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/shader_app.shaders.cppm \ || { echo "FAIL: the keyword directory did not get its trailing underscore" - grep -n namespace target/.build-mcpp/out/spirv/shader_app.shaders.cppm + grep -n namespace $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/shader_app.shaders.cppm exit 1; } # The point of the surface: a consumer names no generated file. if grep -rn 'scale_comp\.h\|\.inc"' src/; then @@ -271,10 +271,10 @@ jobs: # manifest directory's leaf -- which is what this rule did before mcpp # 2026.9.7.1 gave build programs `mcpp::package_name()` -- would write # `spirv_module_consumer.shaders.cppm` and this test would find no file. - iface=target/.build-mcpp/out/spirv/shader_app.shaders.cppm + iface=$(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/shader_app.shaders.cppm test -f "$iface" || { echo "FAIL: no module interface at $iface" - find target/.build-mcpp/out/spirv -name '*.cppm' -print + find $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv -name '*.cppm' -print exit 1; } grep -q '^export module shader_app.shaders;' "$iface" # The interface must name no standard-library type: one that does @@ -300,7 +300,7 @@ jobs: tar -xzf shaderc.tar.gz rm -rf target MCPP_GLSLC="$PWD/shaderc-2026.3/bin/glslc" "$MCPP" build - test -f target/.build-mcpp/out/spirv/scale_comp.inc + test -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/scale_comp.inc MCPP_GLSLC="$PWD/shaderc-2026.3/bin/glslc" "$MCPP" run | tee run-glslc.log grep -q '^magic=07230203' run-glslc.log rm -rf shaderc.tar.gz shaderc-2026.3 @@ -339,7 +339,7 @@ jobs: # TWO declarations, and the directory is in the second one's name. # A build that collapsed them would also produce a working binary, so # the criterion is the generated names rather than the run. - d=target/.build-mcpp/out/spirv + d=$(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv find "$d" -name '*.h' | sort | sed 's/^/ /' grep -rq 'scale_comp_spv' "$d" || { echo "FAIL: the top-level shader lost its declaration"; exit 1; } @@ -385,7 +385,7 @@ jobs: grep -q '^all ok' run.log # Neither artefact is written by hand. test ! -f include/island_interface.kernels.h - d=target/.build-mcpp/out/island + d=$(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/island grep -q 'extern "C" {' "$d/island_interface.kernels.h" # THE MODULE NAME AND THE NAMESPACE ARE ONE IDENTIFIER PATH, which is # the rule docs/42 states for both lanes and the one this generator @@ -515,7 +515,7 @@ jobs: - name: the same boundary and the same names, from the half the build selected working-directory: tests/island-interface run: | - d=target/.build-mcpp/out/island + d=$(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/island cp "$d/island_interface.kernels.cppm" /tmp/device-leg.cppm rm -rf target "$MCPP" build --no-accel > cpu.log 2>&1 || { @@ -538,7 +538,7 @@ jobs: - name: reorganising a root that does not supply the shape renames nothing working-directory: tests/island-interface run: | - d=target/.build-mcpp/out/island + d=$(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/island cp "$d/island_interface.kernels.cppm" /tmp/before-move.cppm mkdir -p src/cpu/deep && mv src/cpu/ops.c src/cpu/deep/ops.c rm -rf target @@ -562,7 +562,7 @@ jobs: - name: a new island file reaches the boundary with nothing else touched working-directory: tests/island-interface run: | - d=target/.build-mcpp/out/island + d=$(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/island rm -rf target && "$MCPP" build > base.log 2>&1 before=$(grep -c '^using ::' "$d/island_interface.kernels.cppm") mkdir -p src/kernels/audio @@ -781,16 +781,16 @@ jobs: grep -q '^all ok' run.log # The bytes are a section, so the compiler never saw a C array: the # payload is a bare `.spv` and an `.S` names it with `.incbin`. - test -f target/.build-mcpp/out/spirv/scale_comp.spv - test -f target/.build-mcpp/out/spirv/spirv_object_storage.shaders.payload.S - grep -q '\.incbin' target/.build-mcpp/out/spirv/spirv_object_storage.shaders.payload.S - if ls target/.build-mcpp/out/spirv/*.inc >/dev/null 2>&1; then + test -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/scale_comp.spv + test -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/spirv_object_storage.shaders.payload.S + grep -q '\.incbin' $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/spirv_object_storage.shaders.payload.S + if ls $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/*.inc >/dev/null 2>&1; then echo "FAIL: object storage still produced a C initialiser list" exit 1 fi # `pCode` wants four-byte alignment and a section directive alone does # not promise it. - grep -q '\.balign 4' target/.build-mcpp/out/spirv/spirv_object_storage.shaders.payload.S + grep -q '\.balign 4' $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/spirv_object_storage.shaders.payload.S echo "ok: the payload is a section, not generated source" - name: rules-spirv with sidecar storage @@ -800,7 +800,7 @@ jobs: "$MCPP" run | tee run.log grep -q '^magic=07230203' run.log grep -q '^all ok' run.log - test -f target/.build-mcpp/out/spirv/scale_comp.spv + test -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/scale_comp.spv # THE REVERSE LEG, AND IT IS THE POINT OF THIS STORAGE. The accessor # opens a path relative to the working directory, so the program finds # its shaders from the package root and must not from anywhere else. @@ -1001,7 +1001,7 @@ jobs: exit 1 fi grep -q '^export module slang_consumer.shaders;' \ - target/.build-mcpp/out/slang/slang_consumer.shaders.cppm + $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/slang/slang_consumer.shaders.cppm echo "ok: a Slang shader reached through the same surface as a GLSL one" # THE NEGATIVE LEG. A `per_file` key that names no shader must refuse the @@ -1034,7 +1034,7 @@ jobs: "$MCPP" run | tee run.log grep -q '^magic=07230203' run.log grep -q '^all ok' run.log - test -f target/.build-mcpp/out/slang/scale.spv + test -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/slang/scale.spv if grep -q 'source-embed' target/*/*/build.ninja; then echo "FAIL: sidecar storage still asked slangc to embed"; exit 1 fi @@ -1115,7 +1115,7 @@ jobs: # `key_kind::relative_path` and `element::word32` -- and `head -1` # picked one by directory order, so the check was asserting about a # file nothing chose. - mapfile -t headers < <(find target/.build-mcpp/out -name '*.h' | sort) + mapfile -t headers < <(find $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh") -name '*.h' | sort) [ "${#headers[@]}" -gt 0 ] || { echo "FAIL: no generated header"; exit 1; } echo "checking ${#headers[@]} generated header(s)" for h in "${headers[@]}"; do @@ -1424,7 +1424,7 @@ jobs: working-directory: tests/hip-consumer run: | "$MCPP" build - test -f target/.build-mcpp/out/saxpy.hip.o + test -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/saxpy.hip.o "$MCPP" build --no-accel "$MCPP" run --no-accel | tee run.log grep -q '^12 24 36 48' run.log @@ -1437,8 +1437,8 @@ jobs: working-directory: tests/sycl-consumer run: | "$MCPP" build - test -f target/.build-mcpp/out/saxpy.sycl.o - test -f target/.build-mcpp/out/sycl_device_link.o + test -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/saxpy.sycl.o + test -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/sycl_device_link.o "$MCPP" build --no-accel "$MCPP" run --no-accel | tee run.log grep -q '^12 24 36 48' run.log @@ -1536,9 +1536,9 @@ jobs: working-directory: tests/multi-rule-consumer run: | "$MCPP" build - test -f target/.build-mcpp/out/saxpy.cu.o - test -f target/.build-mcpp/out/spirv/scale_comp.h - test ! -f target/.build-mcpp/out/scale.cu.o + test -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/saxpy.cu.o + test -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/spirv/scale_comp.h + test ! -f $(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/scale.cu.o "$MCPP" run --no-accel | tee run.log grep -q '^magic=(no shader in this build)' run.log grep -q '^12 24 36 48' run.log @@ -1980,7 +1980,7 @@ jobs: "$MCPP" run | tee run.log grep -q '^out\[0\]=6 out\[1\]=12 out\[2\]=18 out\[3\]=24' run.log grep -q '^all ok' run.log - d=target/.build-mcpp/out/island + d=$(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/island # The namespace is the path from the layout root to the file, so this # is the assertion a separator mistake fails. grep -q '^export namespace island_interface::kernels {' \ diff --git a/tests/apk-consumer-libraries/check-apk-libraries.sh b/tests/apk-consumer-libraries/check-apk-libraries.sh index d0fc01f..bb22e94 100755 --- a/tests/apk-consumer-libraries/check-apk-libraries.sh +++ b/tests/apk-consumer-libraries/check-apk-libraries.sh @@ -110,8 +110,9 @@ grep -q "android.permission.VIBRATE" libs-perm1.log || fail "the library's permi grep -q "android.permission.WAKE_LOCK" libs-perm1.log || fail "the archive's permission was not merged" libs-perm1.log grep -q "android.permission.CAMERA" libs-perm1.log && fail "the permission the application removed is in the package" libs-perm1.log grep -q 'org.mcpp.apklibs.lib.FLAVOUR' libs-xml1.log || fail "the library's meta-data was not merged" libs-xml1.log -grep -q 'tools' target/.build-mcpp/out/dist-apk/AndroidManifest.xml \ - && fail "the merged manifest still carries a tools: attribute" target/.build-mcpp/out/dist-apk/AndroidManifest.xml +merged="$(sh "$(dirname "$0")/../out-dir.sh")/dist-apk/AndroidManifest.xml" +grep -q 'tools' "$merged" \ + && fail "the merged manifest still carries a tools: attribute" "$merged" echo "ok: the manifest merges the library's and the archive's permissions and meta-data, drops the removed one, and keeps no tools: attribute" "$JAR" tf "$apk" > libs-list1.log diff --git a/tests/apk-consumer/check-apk-features.sh b/tests/apk-consumer/check-apk-features.sh index b87eabd..c157b45 100755 --- a/tests/apk-consumer/check-apk-features.sh +++ b/tests/apk-consumer/check-apk-features.sh @@ -35,7 +35,7 @@ rm -rf target unset APK_CONSUMER_TEMPLATE APK_CONSUMER_LEVEL1 || true "$MCPP" build --target "$TARGET" > build-a.log 2>&1 || fail "build failed" build-a.log "$MCPP" pack --format apk --target "$TARGET" > pack-a.log 2>&1 || fail "pack failed" pack-a.log -MANIFEST=target/.build-mcpp/out/dist-apk/AndroidManifest.xml +MANIFEST="$(sh "$(dirname "$0")/../out-dir.sh")/dist-apk/AndroidManifest.xml" cmp fixtures/expected-manifest-level0-0.8.0.xml "$MANIFEST" \ || fail "level 0's manifest is not byte-identical to 0.8.0's" "$MANIFEST" fixtures/expected-manifest-level0-0.8.0.xml echo "ok: level 0 with no template renders 0.8.0's manifest byte-for-byte" diff --git a/tests/metal-consumer/check-metal.sh b/tests/metal-consumer/check-metal.sh index eedf37c..83b4d28 100755 --- a/tests/metal-consumer/check-metal.sh +++ b/tests/metal-consumer/check-metal.sh @@ -45,7 +45,7 @@ reading metal-version "$(xcrun --sdk macosx metal --version 2>&1 | head -1)" # ── 1. three libraries beside the program ───────────────────────────────── echo "== 1. the shaders compile to Metal libraries the program finds ==" "$MCPP" build > metal-build.log 2>&1 || fail "mcpp build failed" metal-build.log -gen=target/.build-mcpp/out/metal +gen="$(sh "$(dirname "$0")/../out-dir.sh")/metal" for name in scale tint tint_red; do [ -f "$gen/$name.air" ] || fail "no $gen/$name.air" metal-build.log [ -f "$gen/$name.metallib" ] || fail "no $gen/$name.metallib" metal-build.log diff --git a/tests/out-dir.sh b/tests/out-dir.sh new file mode 100755 index 0000000..0cdf6c8 --- /dev/null +++ b/tests/out-dir.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# Where `mcpp::out_dir()` pointed in the newest build of the package in the +# current directory. mcpp 2026.10.10.1 and later give each configuration its own +# output directory and record it as the root package's `outDir` in +# resolution.json; earlier engines use target/.build-mcpp/out. +r=$(ls -t target/*/*/resolution.json 2>/dev/null | head -1) +if [ -n "$r" ]; then + py=$(command -v python3 || command -v python) + d=$("$py" -c 'import json, sys +for p in json.load(open(sys.argv[1])).get("graph", {}).get("packages", []): + if p.get("root"): + print(p.get("outDir", "")) + break' "$r" 2>/dev/null) + if [ -n "$d" ]; then + echo "$d" + exit 0 + fi +fi +echo "target/.build-mcpp/out" From 723c482cda36b418d1fa0941d3de269d004f5a42 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sat, 10 Oct 2026 08:31:30 +0900 Subject: [PATCH 2/2] test: the island checks read the outDir of the configuration they just built --no-accel is another configuration with its own output directory, so the output directory is read after each build. --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3942e92..a2b49ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -523,6 +523,8 @@ jobs: "$MCPP" run --no-accel | tee cpurun.log grep -q '^out\[0\]=6 out\[1\]=12 out\[2\]=18 out\[3\]=24' cpurun.log grep -q '^all ok' cpurun.log + # The CPU leg is another configuration, with its own output directory. + d=$(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/island diff /tmp/device-leg.cppm "$d/island_interface.kernels.cppm" || { echo "FAIL: the qualified names differ between the two legs"; exit 1; } echo "ok: the CPU leg reaches the same qualified names" @@ -562,8 +564,8 @@ jobs: - name: a new island file reaches the boundary with nothing else touched working-directory: tests/island-interface run: | - d=$(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/island rm -rf target && "$MCPP" build > base.log 2>&1 + d=$(sh "$GITHUB_WORKSPACE/tests/out-dir.sh")/island before=$(grep -c '^using ::' "$d/island_interface.kernels.cppm") mkdir -p src/kernels/audio printf 'MCPP_EXPORT_C\nint island_fft(float* out, unsigned n) { (void)out; (void)n; return 0; }\n' \