Skip to content

Commit 25a51ac

Browse files
committed
ci: SPIR-V magic 的断言不能只点名 .h —— 规则会选编译器,两个编译器把声明拆得不一样
macOS 与 Windows 上图形示例的**构建都成功了**:规则供给了 `xim:shaderc@2026.3`、两个 着色器阶段都编译了、Vulkan 那一半也链接上了 loader 包。红的是我写的那条断言。 glslang 写出完整的 `const uint32_t ...[] = {...}`(magic 在 `.h` 里),glslc 写出初始 化列表、由规则在外面补声明(magic 在 `.inc` 里)。**一条只点名 `.h` 的断言,是一条 关于某一个编译器的断言** —— 正是这个 job 存在的理由所要抓的那种形状,只不过这次它抓到 的是自己。 顺带一个陷阱:改成 `grep -qs '<pat>' a.h a.inc` 是错的。**GNU grep 在被点名的文件不 存在时返回 2,即使它在前一个文件里匹配到了,也即使加了 `-s`** —— `-s` 压的是消息不是 状态。于是这条判据在「只产出 header」的那条路上永远失败,而失败原因与被测性质无关。 逐个文件测。 两条腿都实测过:glslang 路(只有 .h)通过;把 magic 改掉当场变红。
1 parent cc8992a commit 25a51ac

4 files changed

Lines changed: 78 additions & 9 deletions

File tree

.agents/docs/2026-09-07-heterogeneous-cross-platform-ecosystem.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,23 @@ install/config 形状,而那套形状是按 Linux 写的:
357357
顺带一条读数:两条腿的中心像素**逐字节相同**(`(124, 70, 62, 255)`),所以 CI 的反向
358358
腿从「CPU 腿跑起来了」加强成「两条腿报出同一个像素、不同的设备名」。
359359

360+
### 10.4c 图形示例在三个平台上都构建通过,而先红的是判据自己
361+
362+
macOS 与 Windows 上的构建都成功了 —— 规则供给了 `xim:shaderc@2026.3`,两个着色器阶段
363+
都编译了,Vulkan 那一半也链接上了 loader 包。**红的是我写的那条断言**:
364+
365+
target/.build-mcpp/out/spirv/triangle_vert.h carries no SPIR-V magic
366+
367+
因为规则会****编译器,而两个编译器把声明拆得不一样:glslang 写出完整的
368+
`const uint32_t ...[] = {...}`(magic 在 `.h` 里),glslc 写出初始化列表、由规则在外面
369+
补声明(magic 在 `.inc` 里)。**一条只点名 `.h` 的断言,是一条关于某一个编译器的断言**
370+
—— 正是这个 job 存在的理由所要抓的那种形状,只不过这次它抓到的是自己。
371+
372+
顺带一个可迁移的小陷阱:改成 `grep -qs '<pat>' a.h a.inc` 是错的。**GNU grep 在被
373+
点名的文件不存在时返回 2,即使它在前一个文件里匹配到了,也即使加了 `-s`** —— `-s` 压的
374+
是消息不是状态。于是这条判据在「只产出 header」的那条路上永远失败,而失败的原因与被测
375+
的性质无关。正确写法是逐个文件测。
376+
360377
### 10.5 一条留下的不一致,以及它什么时候消失
361378

362379
`mcpp:plugins` 0.2.5 里 `xim:shaderc` 在 macOS 与 Windows 上是**精确版本**,而

.github/workflows/ci-linux.yml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,23 @@ jobs:
294294
# compiled only the first source would leave the second header absent
295295
# and everything after this would still pass.
296296
for f in triangle_vert triangle_frag; do
297-
h="target/.build-mcpp/out/spirv/$f.h"
298-
test -f "$h" || { echo "missing $h"; exit 1; }
299-
grep -q '0x07230203' "$h" || { echo "$h carries no SPIR-V magic"; exit 1; }
297+
d="target/.build-mcpp/out/spirv"
298+
test -f "$d/$f.h" || { echo "missing $d/$f.h"; exit 1; }
299+
# Either file: which of the two carries the words is a property of
300+
# the shader compiler the rule chose, not of the shader. See the
301+
# cross-platform jobs, where that choice differs.
302+
# ONE FILE AT A TIME, because `grep -qs a b` exits 2 when `b`
303+
# does not exist -- even on a match in `a`, and even with `-s`,
304+
# which suppresses the message and not the status. Written as one
305+
# grep over both names, this criterion fails whenever the route
306+
# that produces only a header is taken, which is a failure about
307+
# the criterion and not about the shader.
308+
found=""
309+
for g in "$d/$f.h" "$d/$f.inc"; do
310+
[ -f "$g" ] && grep -q '0x07230203' "$g" && found=1
311+
done
312+
[ -n "$found" ] \
313+
|| { echo "$f carries no SPIR-V magic in either $f.h or $f.inc"; exit 1; }
300314
done
301315
icd=$(find "${MCPP_HOME:-$HOME/.mcpp}/registry/data/xpkgs/xim-x-mesa-lavapipe" \
302316
"$HOME/.xlings/data/xpkgs/xim-x-mesa-lavapipe" \

.github/workflows/ci-macos.yml

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,28 @@ jobs:
336336
# depend on step order, which is not a property anybody reads.
337337
"/tmp/mcpp-fresh" build --toolchain "llvm@${MCPP_LLVM_VER}"
338338
for f in triangle_vert triangle_frag; do
339-
h="target/.build-mcpp/out/spirv/$f.h"
340-
test -f "$h" || { echo "missing $h"; exit 1; }
341-
grep -q '0x07230203' "$h" || { echo "$h carries no SPIR-V magic"; exit 1; }
339+
d="target/.build-mcpp/out/spirv"
340+
test -f "$d/$f.h" || { echo "missing $d/$f.h"; exit 1; }
341+
# THE MAGIC IS NOT ALWAYS IN THE HEADER, AND THAT IS THE POINT OF
342+
# THIS JOB. The rule chooses the shader compiler this platform
343+
# publishes -- glslang on Linux, glslc here -- and the two split
344+
# the declaration differently: glslang writes a complete `const
345+
# uint32_t ...[] = {...}`, glslc an initialiser list the rule
346+
# declares around, so the words land in `<stem>.inc`. An assertion
347+
# naming only the header is an assertion about ONE compiler, which
348+
# is exactly the shape this step exists to catch.
349+
# ONE FILE AT A TIME, because `grep -qs a b` exits 2 when `b`
350+
# does not exist -- even on a match in `a`, and even with `-s`,
351+
# which suppresses the message and not the status. Written as one
352+
# grep over both names, this criterion fails whenever the route
353+
# that produces only a header is taken, which is a failure about
354+
# the criterion and not about the shader.
355+
found=""
356+
for g in "$d/$f.h" "$d/$f.inc"; do
357+
[ -f "$g" ] && grep -q '0x07230203' "$g" && found=1
358+
done
359+
[ -n "$found" ] \
360+
|| { echo "$f carries no SPIR-V magic in either $f.h or $f.inc"; exit 1; }
342361
done
343362
echo "ok: both shader stages compiled and the Vulkan half linked"
344363

.github/workflows/ci-windows.yml

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -431,9 +431,28 @@ jobs:
431431
# depend on step order, which is not a property anybody reads.
432432
"$MCPP_SELF" build --toolchain "llvm@20.1.7"
433433
for f in triangle_vert triangle_frag; do
434-
h="target/.build-mcpp/out/spirv/$f.h"
435-
test -f "$h" || { echo "missing $h"; exit 1; }
436-
grep -q '0x07230203' "$h" || { echo "$h carries no SPIR-V magic"; exit 1; }
434+
d="target/.build-mcpp/out/spirv"
435+
test -f "$d/$f.h" || { echo "missing $d/$f.h"; exit 1; }
436+
# THE MAGIC IS NOT ALWAYS IN THE HEADER, AND THAT IS THE POINT OF
437+
# THIS JOB. The rule chooses the shader compiler this platform
438+
# publishes -- glslang on Linux, glslc here -- and the two split
439+
# the declaration differently: glslang writes a complete `const
440+
# uint32_t ...[] = {...}`, glslc an initialiser list the rule
441+
# declares around, so the words land in `<stem>.inc`. An assertion
442+
# naming only the header is an assertion about ONE compiler, which
443+
# is exactly the shape this step exists to catch.
444+
# ONE FILE AT A TIME, because `grep -qs a b` exits 2 when `b`
445+
# does not exist -- even on a match in `a`, and even with `-s`,
446+
# which suppresses the message and not the status. Written as one
447+
# grep over both names, this criterion fails whenever the route
448+
# that produces only a header is taken, which is a failure about
449+
# the criterion and not about the shader.
450+
found=""
451+
for g in "$d/$f.h" "$d/$f.inc"; do
452+
[ -f "$g" ] && grep -q '0x07230203' "$g" && found=1
453+
done
454+
[ -n "$found" ] \
455+
|| { echo "$f carries no SPIR-V magic in either $f.h or $f.inc"; exit 1; }
437456
done
438457
echo "ok: both shader stages compiled and the Vulkan half linked"
439458

0 commit comments

Comments
 (0)