fix(csrc): 交叉门禁改用 clang --target,去掉会卡死的 apt 下载 + 修两处假通过

## 卡死真因(这次可观测了)

上一版加了 `timeout` 硬超时后,日志终于能看出卡在哪:

    15:47:33  Fetched 12.5 MB in 1s (9972 kB/s)      ← update 很快
    15:47:38  Get:2 gcc-13-aarch64-linux-gnu-base 51.9 kB
    15:47:39  Get:3 cpp-13-aarch64-linux-gnu 10.8 MB   ← 下到这儿卡住
    15:50:37  ##[error]apt-get install 超时/失败(180s)

**根因:为了跑一道 `-fsyntax-only` 的语法门禁,去下载 10MB+ 的交叉 GCC 工具链,
在 runner 上拉不动。**

## 改法:用 clang 自带的交叉前端

这道门禁只做 `-fsyntax-only`(不链接、不运行)。clang 支持
`--target=aarch64-linux-gnu`,会**真的切到 aarch64 目标**:

    $ clang -fsyntax-only arch2.c          → error: "not aarch64 target"
    $ clang --target=aarch64-linux-gnu ... → 通过(__aarch64__ 生效)

指针宽度、endianness、C 扩展支持都按目标架构算 —— 足以暴露本门禁要抓的
那类问题。而 clang 在 ubuntu-latest 镜像里**已预装**(实测确认,只列出
`gcc-aarch64-linux-gnu` 一项需要安装)。

优先级:`CC_ARM64`(显式)> `clang --target` > `aarch64-linux-gnu-gcc` > SKIP

## 顺带修掉两处**本来就存在**的假通过

这两处不是本轮引入的,是新写的存在性校验暴露出来的:

### ① `cmd | head` 吞掉编译器退出码

    for src in ...; do
        if ! $CC ... -fsyntax-only $src 2>&1 | head -20; then ok=0; fi
    done

管道退出码是 `head` 的(恒 0)。实测:`CC_ARM64=nonexistent-xyz make csrc-cross`
竟然输出「0 告警、编译通过 ✓」—— 编译器根本没执行。

修法:改用 `${PIPESTATUS[0]}`,取编译器的真实退出码。

### ② `PIPESTATUS` 需要 bash,Make 默认是 dash

`/bin/sh` 在 Debian/Ubuntu 上是 dash,不支持 `PIPESTATUS`(报 Bad substitution)。
必须显式 `SHELL := /bin/bash`,否则上面的修法静默失效。

### 风险自证(三条路径实测)

| 场景 | 结果 |
|---|---|
| 正常(clang-target) | ✅ 0 告警、编译通过 ✓ |
| `CC_ARM64` 指向不存在的命令 | ✅ `[FAIL] CC_ARM64=nonexistent-xyz 不存在` → Error 1 |
| 真的写坏 C 源码 | ✅ 编译器报错 + `[FAIL] arm64 交叉编译失败` → Error 1 |

## CI 侧

- 安装步骤不再要求 `gcc-aarch64-linux-gnu` ⇒ **依赖已预装,直接跳过 apt-get,完全不碰网络**
- 工具链确认步骤只校验 `cmake` + `clang`
- `[SKIP]` 拦截、`timeout` 硬超时、去 `-qq` 全部保留(对付将来别的原因导致的卡死)
This commit is contained in:
JianFeeeee
2026-10-22 23:55:54 +08:00
parent 16bb794a43
commit 7fdec0670f
2 changed files with 61 additions and 14 deletions

View File

@ -192,13 +192,21 @@ jobs:
timeout-minutes: 5
run: |
set -uo pipefail
# ★ 不再需要 gcc-aarch64-linux-gnu(2026-10-22)。
#
# 实测:装它要从源拉 10MB+ 的 cpp-13 等依赖,在 runner 上卡住超时
# (15:47:39 开始下 cpp-13-aarch64,180s 后仍未完成)。
# 而 csrc-cross 只需要 `-fsyntax-only`,clang 自带交叉前端即可:
# `clang --target=aarch64-linux-gnu` 会真的切到 aarch64 目标
# (__aarch64__ 宏生效、指针宽度按该架构算),足以暴露本门禁要抓的
# 架构问题。Makefile 的 csrc-cross 已按
# CC_ARM64 > clang --target > aarch64-gcc > SKIP 的优先级挑选。
need=""
command -v cmake >/dev/null || need="$need cmake"
command -v clang >/dev/null || need="$need clang"
command -v aarch64-linux-gnu-gcc >/dev/null || need="$need gcc-aarch64-linux-gnu"
command -v cmake >/dev/null || need="$need cmake"
command -v clang >/dev/null || need="$need clang"
if [ -z "$need" ]; then
echo "✅ 三件套已存在,跳过 apt-get:$(command -v cmake clang aarch64-linux-gnu-gcc | tr '\n' ' ')"
echo "✅ 依赖已存在,跳过 apt-get:$(command -v cmake clang | tr '\n' ' ')"
exit 0
fi
@ -239,7 +247,7 @@ jobs:
run: |
set -euo pipefail
miss=""
for t in cmake clang aarch64-linux-gnu-gcc; do
for t in cmake clang; do
if command -v "$t" >/dev/null 2>&1; then
echo " ✅ $t: $(command -v "$t")"
else