From 369a202d6f83e5520b0352e935a6ad48b6aa2f8e Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Fri, 23 Oct 2026 00:04:19 +0800 Subject: [PATCH] =?UTF-8?q?fix(csrc):=20=E7=94=A8=20-nostdinc=20=E5=89=83?= =?UTF-8?q?=E6=8E=89=E5=AE=BF=E4=B8=BB=E5=A4=B4=EF=BC=8C=E4=BF=AE=20clang?= =?UTF-8?q?=20=E4=BA=A4=E5=8F=89=E7=9A=84=20stdint.h=20=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 上一版为什么还红 装了 `libc6-dev-arm64-cross`(1.7MB 头包)后,CI 报的错变成了: In file included from csrc/src/ha_codec.c:23: 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 注意路径:它找的是 **`/usr/include/stdint.h`(宿主 amd64 的)**,不是 aarch64 的那份。宿主 stdint.h 会 `#include `, 那是 amd64 的布局,aarch64 目标下必然找不到。 **只加 `-isystem` 指向 aarch64 头不够** —— 默认搜索路径里的 `/usr/include` 仍然优先。 ## 修法:`-nostdinc` 剃掉全部默认路径,再按序加回 ARM64_INC="-nostdinc -isystem $(clang -print-resource-dir)/include" for d in /usr/aarch64-linux-gnu/include /usr/include/aarch64-linux-gnu; do [ -d "$d" ] && ARM64_INC="$ARM64_INC -isystem $d" done 顺序:**clang 内建头 → aarch64 目标头**。`-nostdinc` 保证宿主 `/usr/include` 不再参与,宿主头泄漏这条路径被彻底断掉。 只对 clang-target 模式生效;explicit / cross-gcc 模式用编译器自带搜索路径, 不传这些(它们本来就知道自己的 sysroot 在哪)。 ## 本地五条路径实测 | 路径 | 结果 | |---|---| | ① clang-target(默认) | ✅ 0 告警通过 | | ② 显式 cross-gcc | ✅ 0 告警通过 | | ③ 显式指向不存在的编译器 | ✅ FAIL(Error 1) | | ④ **真的写坏 C 源码** | ✅ FAIL(Error 1) | | ⑤ 恢复后 | ✅ 通过 | | `make check-csrc` 全门禁 | ✅ 全部通过,0 SKIP | ③④ 是防止"假通过"的回归判据:③ 验 `command -v` 校验 + PIPESTATUS, ④ 验编译器真实退出码没被 `| head` 吞掉。 --- Makefile | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 63970525..f0fd39ef 100644 --- a/Makefile +++ b/Makefile @@ -273,6 +273,14 @@ csrc-fuzz: # # 优先级:CC_ARM64(显式指定) > clang --target > aarch64-linux-gnu-gcc > SKIP # +# ★ 宿主头泄漏陷阱(CI 实测):只加 -isystem 指向 aarch64 头还不够 —— +# 宿主 /usr/include/stdint.h 会先被找到,它再 include +# (amd64 布局),aarch64 目标下必然找不到: +# /usr/include/stdint.h:26: fatal error: 'bits/libc-header-start.h' file not found +# 所以 clang-target 模式必须 -nostdinc 剃掉全部默认路径,再按 +# 「clang 内建头 → aarch64 目标头」顺序加回(见下方 ARM64_INC)。 +# explicit / cross-gcc 模式用编译器自带搜索路径,不传这些。 +# # ★ 两个假通过陷阱(实测踩到,勿删): # 1. 显式 CC_ARM64 指向不存在的命令时,`cmd | head` 的退出码是 head 的(恒 0), # command-not-found(127) 被吞 ⇒ 门禁显示"通过"。所以循环里改用 PIPESTATUS[0], @@ -295,20 +303,22 @@ csrc-cross: echo " [SKIP] 无 clang、无 aarch64-linux-gnu-gcc(未装任何交叉前端)"; exit 0; \ fi; \ \ - ARM64_SYSINC=""; \ + ARM64_INC="-nostdinc -isystem $$(clang -print-resource-dir)/include"; \ for d in /usr/aarch64-linux-gnu/include /usr/include/aarch64-linux-gnu; do \ - [ -d "$$d" ] && ARM64_SYSINC="$$ARM64_SYSINC -isystem $$d"; \ + [ -d "$$d" ] && ARM64_INC="$$ARM64_INC -isystem $$d"; \ done; \ \ if [ "$$MODE" = "clang-target" ]; then \ 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 \ + if ! clang --target=aarch64-linux-gnu $$ARM64_INC -fsyntax-only /tmp/_archchk.c >/dev/null 2>&1; then \ echo " [SKIP] clang 交叉前端不可用(缺 aarch64 libc 头,装 libc6-dev-arm64-cross 即可)"; exit 0; \ fi; \ fi; \ \ + EXTRA_INC=""; \ + [ "$$MODE" = "clang-target" ] && EXTRA_INC="$$ARM64_INC"; \ for src in $(CSRC_SRCS); do \ - $$CC $(CSRC_CFLAGS) -Werror -fsyntax-only $$src 2>&1 | head -20; \ + $$CC $$EXTRA_INC $(CSRC_CFLAGS) -Werror -fsyntax-only $$src 2>&1 | head -20; \ rc=$${PIPESTATUS[0]}; \ if [ "$$rc" != "0" ]; then ok=0; fi; \ done; \