From 0e5077497e37220f7c75c68feaface093ef32082 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Thu, 22 Oct 2026 23:59:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(csrc):=20clang=20=E4=BA=A4=E5=8F=89?= =?UTF-8?q?=E9=9C=80=E8=A6=81=20aarch64=20libc=20=E5=A4=B4=20=E2=80=94?= =?UTF-8?q?=E2=80=94=20=E5=8F=AA=E8=A3=85=201.7MB=20=E5=A4=B4=E5=8C=85?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E8=A3=85=2010MB=20=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## CI 实测暴露的下一层问题 上一版让 clang 做交叉编译后,安装步骤成功且**完全跳过 apt**(cmake/clang 都在 镜像里),但 `make check-csrc` 红在: In file included from /usr/lib/llvm-18/lib/clang/18/include/stdint.h:52: /usr/include/stdint.h:26:10: fatal error: 'bits/libc-header-start.h' file not found 真因:`clang --target=aarch64-linux-gnu` 切换的是**目标架构**,但系统头 仍按**宿主**(amd64)找 —— `bits/libc-header-start.h` 是 amd64 的布局, aarch64 目标下不该用。本地能过是本机装了完整交叉 GCC,带来了 `/usr/aarch64-linux-gnu/include`。 ## 试过但走不通的两条路(记录以免重复踩) | 尝试 | 结果 | |---|---| | `-nostdinc` + clang 内建头 | ❌ clang 内建**不含 `string.h`**(那是 libc 的) | | `-ffreestanding -nostdlibinc` | ❌ 同上,代码实际用了 `strlen`/`memcpy` | ## 采用:只装 libc 头,不装编译器 libc6-dev-arm64-cross 1.7 MB(+ libc6-arm64-cross、linux-libc-dev-arm64-cross) gcc-aarch64-linux-gnu 含 cpp-13(10.8MB)+ gcc-16 等,实测下载卡死 既然只需要**头文件**(不做链接、不跑代码),就不该拉整个交叉 GCC。 装上头后 clang 就能完成 `-fsyntax-only`。 ### Makefile 配合 `csrc-cross` 的 clang-target 模式现在自动探测并注入 aarch64 头路径: for d in /usr/aarch64-linux-gnu/include /usr/include/aarch64-linux-gnu; do [ -d "$d" ] && ARM64_SYSINC="$ARM64_SYSINC -isystem $d" done 探测改用**真实头文件**(`#include `)而非空 main,这样 "clang 版本支持 --target" 与 "aarch64 头是否齐备" 两个条件一起验; 缺头时明确 SKIP 并说清装哪个包(`libc6-dev-arm64-cross`)。 ## 本地实测 | 验证 | 结果 | |---|---| | 有 aarch64 头时 | ✅ clang-target 通过(0 告警) | | `make check-csrc` 全门禁 | ✅ 全部通过,0 SKIP | | YAML 可解析 | ✅ | | 上一版三条失败路径(编译器不存在/真写坏/正常) | ✅ 仍然正确(PIPESTATUS 修复未回退) | --- .github/workflows/ci.yml | 4 ++++ Makefile | 11 ++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ed4a233..cd6789b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -204,6 +204,10 @@ jobs: need="" command -v cmake >/dev/null || need="$need cmake" command -v clang >/dev/null || need="$need clang" + # aarch64 的 libc 头(1.7MB,仅头文件,**不含编译器**)。 + # 用它 + 已预装的 clang 交叉前端,替代 10MB+ 的完整交叉 GCC + # (实测那个会卡在下载 cpp-13-aarch64,180s 超时)。 + [ -d /usr/aarch64-linux-gnu/include ] || need="$need libc6-dev-arm64-cross" if [ -z "$need" ]; then echo "✅ 依赖已存在,跳过 apt-get:$(command -v cmake clang | tr '\n' ' ')" diff --git a/Makefile b/Makefile index 6b00f6b3..63970525 100644 --- a/Makefile +++ b/Makefile @@ -295,10 +295,15 @@ csrc-cross: echo " [SKIP] 无 clang、无 aarch64-linux-gnu-gcc(未装任何交叉前端)"; exit 0; \ fi; \ \ + ARM64_SYSINC=""; \ + for d in /usr/aarch64-linux-gnu/include /usr/include/aarch64-linux-gnu; do \ + [ -d "$$d" ] && ARM64_SYSINC="$$ARM64_SYSINC -isystem $$d"; \ + done; \ + \ if [ "$$MODE" = "clang-target" ]; then \ - printf 'int main(void){return 0;}\n' > /tmp/_archchk.c; \ - if ! clang --target=aarch64-linux-gnu -fsyntax-only /tmp/_archchk.c 2>/dev/null; then \ - echo " [SKIP] clang 不支持 --target=aarch64-linux-gnu(版本过旧)"; exit 0; \ + printf '#include \nint main(void){return 0;}\n' > /tmp/_archchk.c; \ + if ! clang --target=aarch64-linux-gnu $$ARM64_SYSINC -fsyntax-only /tmp/_archchk.c >/dev/null 2>&1; then \ + echo " [SKIP] clang 交叉前端不可用(缺 aarch64 libc 头,装 libc6-dev-arm64-cross 即可)"; exit 0; \ fi; \ fi; \ \