Skip to content

2026.8.24.5 — say what the env segment names, where it does not name a C library - #499

Merged
Sunrisepeak merged 2 commits into
mainfrom
fix/env-segment-names-what
Aug 24, 2026
Merged

2026.8.24.5 — say what the env segment names, where it does not name a C library#499
Sunrisepeak merged 2 commits into
mainfrom
fix/env-segment-names-what

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

x86_64-windows-gnu 之上一行写着 c-abi musl,读者两次在同一处停下来问「这个 gnu / musl 的矛盾还在吗」。

它不是矛盾:Windows 上 gnu 命名的是对象 ABI,对应的行是 c++-abi 而不是 c-abi

沉默作为诊断是对的,作为报告是不够的。 报告里没有一行叫 gnu,读者只能把它映到最像 C 库名字的那一行。而加警告是错的——它会在每一次合法的 MinGW 构建上出现,内容本身还是假的。

Target x86_64-windows-gnu → x86_64-w64-windows-gnu   (gnu names the object ABI, not a C library)

布尔是对事实的有损编码

envNamesCAbi 只回答「该段是不是 C 库」,足以压住错误的警告,却给不出正确的名字。换成 EnvAxis:

平台 命名什么 行为
linux gnu / musl C 库 可与图矛盾 → 警告
windows gnu / msvc 对象 ABI 不矛盾 → 报告加注
none elf 对象格式 同上

一个枚举,三个平台,零 #if

⚠️ 提示不出现在 C 库来自载荷时——那种情况下 C 库正是三元组选中的,gnu → ucrt 是可见的因果,加注就成了噪声。作用域与既有警告一致(if (!ts.cAbi.fromGraph())),不是巧合。

实测

--target x86_64-windows-gnu   加注,无警告
--target x86_64-linux         什么都不加(没作请求)
--target x86_64-linux-gnu     警告 + 可粘贴的改法

targetside 单元测试 41 → 45,含一条断言「载荷来源时不加注」的反例;93 通过 / 0 失败。docs/15 中英双份同步。

…a C library

`x86_64-windows-gnu` 之上一行写着 `c-abi musl`,读者两次在同一处停下来问
「这个 gnu / musl 的矛盾还在吗」。它不是矛盾:Windows 上 `gnu` 命名的是
**对象 ABI**,它对应的行是 `c++-abi`,不是 `c-abi`。

⭐ 沉默作为**诊断**是对的,作为**报告**是不够的。报告里没有一行叫 `gnu`,
于是读者把它映到最像 C 库名字的那一行。加警告则是错的 —— 它会在每一次
合法的 MinGW 构建上出现,而且说的内容本身是假的。

    Target x86_64-windows-gnu → x86_64-w64-windows-gnu   (gnu names the object ABI, not a C library)

── 布尔是对事实的有损编码 ──────────────────────────────

`envNamesCAbi` 只回答「该段是不是 C 库」,足以压住错误的警告,
却给不出正确的名字。换成 `EnvAxis { Unknown, CLibrary, ObjectAbi, ObjectFormat }`:

    linux    gnu / musl    C 库          ← 可以与图矛盾,报警告
    windows  gnu / msvc    对象 ABI      ← 不矛盾,报告加注
    none     elf           对象格式      ← 同上

一个枚举,三个平台,零 `#if`。

⚠️ **该提示不出现在 C 库来自载荷时。** 那种情况下 C 库正是三元组选中的 ——
三元组就是选中它的方式 —— `gnu → ucrt` 是可见的因果,加注就成了每次
普通 Windows 构建上的噪声。作用域与既有那条警告的作用域一致
(`if (!ts.cAbi.fromGraph()) return std::nullopt;`),这不是巧合。

实测三种情形互不干扰:

    --target x86_64-windows-gnu   加注,无警告
    --target x86_64-linux         什么都不加(没作请求)
    --target x86_64-linux-gnu     警告 + 可粘贴的改法

单元测试 targetside 41 → 45,含一条断言「载荷来源时不加注」的反例;
93 通过 / 0 失败。docs/15 中英双份同步。
复查时被问住两处,量了一遍,其中一处是我写错的。

**`musl 是 gnu ABI 吗?`** 不是,而且 `gnu` 也没在说 C 库。
对该次构建的产物实测:

    导入的库        ntdll、KERNEL32、SHELL32 —— 无 msvcrt,无 ucrtbase
    _Z… 符号        4507
    ?…  符号        0

第一行说明 `c-abi musl` 是老实的:MinGW 的 C 运行时一点没链进来。

**`libc++ 是 gnu?`** ⚠️ **不是,而我在上一版里写反了。** 我说
「`gnu` 对应的是 `c++-abi libc++` 那一行」,这是错的:`gnu` 选中的是
**Itanium C++ ABI**(那 4507 个 `_Z` 就是它),而 libc++ 是标准库的一个
实现,libstdc++ 是另一个,**两者都坐在同一套 ABI 上**。

⭐ 真相是它**不对应任何一行**,而这正是要点。五层记录的是每一层
**由谁供给**;`gnu` 命名的是这些**对象遵循哪套约定** —— 若干层必须一致的
横切事项,不是一层。于是提示改为命名那套 ABI 本身:

    (gnu selects the Itanium C++ ABI, not a C library)

`Itanium` 与 `MSVC` 不出现在任何一行里,因此不会像「the C++ ABI」那样
被误当成 `c++-abi` 那一层。这是把一个错误答案换成正确答案,
而不是把含糊换成含糊。

⚠️ **名词取自值而非仅取自轴。** `gnu` 与 `msvc` 同轴而选中相反的 ABI,
按轴取名会给 MSVC 构建打印「Itanium」—— 那不只是含糊,是假的。
新增测试断言这一点,并断言提示里的名字**不等于任何一层的实现名**,
否则同一种混淆会换个地方重现。

三处带着那句错话的文本(model.cppm 注释、docs/15 中英)一并改掉。
targetside 单元测试 45 → 47,93 通过 / 0 失败。
@Sunrisepeak
Sunrisepeak merged commit 52dd503 into main Aug 24, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants