Skip to content

Commit 9448897

Browse files
committed
fix(diag): the freestanding import std message pointed at a package that does not exist
It ended with a copy-pasteable [dependencies] mcpplibs.std.freestanding = "0.1" and no such package is published. Following the advice fails at the very next command with "package not found", which sends the reader off to debug their index instead of their code. Now it points at what a bare-metal project actually has — the module its board package exports, named concretely — and describes a freestanding subset package as a shape rather than a line to paste, saying plainly that none is published yet. The concrete line comes back when one ships. Every suggestion in a diagnostic is a promise; this one had not been checked against reality before being written.
1 parent c6f332d commit 9448897

4 files changed

Lines changed: 49 additions & 10 deletions

File tree

.agents/docs/2026-08-19-baremetal-phase3-usable-plan.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,3 +413,27 @@ deps = { "xim:picolibc-riscv@1.8.12", "xim:qemu-riscv@9.2.4-1" },
413413
#### 兼容性:类型化 API 没有语言内的特性探测(见 §3.2 的补记)
414414

415415
包侧无解 ⇒ 补在引擎侧的编译失败诊断上,对**以后每一次**类型化 API 新增都生效。
416+
417+
### 11.3 ⚠️ 我在第二阶段留下了一条**指向不存在的包**的诊断
418+
419+
W6 的 `import std` 诊断里写着可以直接粘贴的:
420+
421+
```toml
422+
[dependencies]
423+
mcpplibs.std.freestanding = "0.1"
424+
```
425+
426+
**这个包没有发布,而且本阶段也不该顺手发**(E-STD-1/E-STD-2 各自是 M 规模:
427+
`-nostdinc++` 之下 libc++ 的头一个都用不了,子集要自己实现;而且往 `namespace std`
428+
里加声明本身就是另一个问题)。
429+
430+
⇒ 用户照着诊断粘完,下一条命令报「package not found」。**一条修不好问题的诊断,
431+
比一条只解释不给命令的诊断更糟** —— 它让读者接下来几分钟在怀疑自己的索引坏了。
432+
433+
已改成指向**今天确实存在**的东西(板级包导出的模块,点名 `mcpplibs.riscv_virt_rt`),
434+
并把子集包描述成一个**形态**而不是一行可粘贴的依赖,末尾明说「还没有这样的包」。
435+
**E-STD 仍然开着;它发布时要把这条诊断改回具体的一行。**
436+
437+
⚠️ 一般化:**诊断里的每一条建议都是一个承诺**,而承诺是要被兑现的。写「加这一行」
438+
之前必须先确认那一行今天能跑通 —— 这条和 [[issue427-absence-treated-as-contradiction]]
439+
里那条错误建议是同一形状。

docs/05-mcpp-toml.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,7 @@ that has none.
931931
|---|---|
932932
| Link line | `-nostdlib -nostartfiles -static`, and nothing hosted — no crt files, no dynamic linker, no C++ runtime. The linker is addressed by **absolute path** (`-fuse-ld=<payload>/bin/ld.lld`), because `-fuse-ld=lld` resolves through `PATH` and finds GNU ld on any machine with binutils earlier on it. |
933933
| ISA flags | `-march` / `-mabi` / `-mcmodel` come from the target table, so `--target <triple>` alone is enough to produce a correct object file. |
934-
| `import std` | **Unavailable.** `std` is one module over the entire library — threads, filesystem and iostreams included — so there is no subset of it to build without an OS. The freestanding subset package replaces it, and mcpp's diagnostic names it. |
934+
| `import std` | **Unavailable.** `std` is one module over the entire library — threads, filesystem and iostreams included — so there is no subset of it to build without an OS. What a firmware imports instead is the module its **board package** exports, which is where the target's C library is already wrapped. |
935935
| Entry point | `int main()` works **as long as something supplies a `crt0`** — a board package normally does, and then a firmware's entry point is an ordinary `main` whose return value reaches the host through semihosting. Only a zero-libc board needs an explicit target whose `main` points at the file carrying `_start`. |
936936

937937
**A minimal firmware**

docs/zh/05-mcpp-toml.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ cd blinky && mcpp run
827827
|---|---|
828828
| 链接线 | `-nostdlib -nostartfiles -static`,且不带任何 hosted 的东西 —— 没有 crt 文件、没有动态链接器、没有 C++ 运行时。链接器用**绝对路径**寻址(`-fuse-ld=<载荷>/bin/ld.lld`),因为 `-fuse-ld=lld``PATH` 解析,在任何 binutils 排前面的机器上都会找到 GNU ld。 |
829829
| ISA flag | `-march` / `-mabi` / `-mcmodel` 来自 target 表,所以只写 `--target <triple>` 就足以产出正确的目标文件。 |
830-
| `import std` | **不可用。** `std` 是覆盖整个库的一个模块 —— 线程、文件系统、iostreams 全在内 —— 没有 OS 就没有它的子集可编。freestanding 子集包取代它,mcpp 的诊断会点名|
830+
| `import std` | **不可用。** `std` 是覆盖整个库的一个模块 —— 线程、文件系统、iostreams 全在内 —— 没有 OS 就没有它的子集可编。固件真正 import 的是**板级包导出的模块**,目标的 C 库已经在那里包好了|
831831
| 入口点 | **只要有人提供 `crt0`,`int main()` 就能用** —— 板级支持包通常就提供它,于是固件的入口就是普通的 `main`,它的返回值经 semihosting 传回宿主。**只有零 libc 的板子**才需要显式声明 target 并把 `main` 指向携带 `_start` 的那个文件。 |
832832

833833
**一个最小固件**

src/build/prepare.cppm

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5273,9 +5273,18 @@ prepare_build(bool print_fingerprint,
52735273
// no subset of it to build without an OS. Saying "provides no std
52745274
// module source" sends the reader to look for a broken payload.
52755275
//
5276-
// Naming the replacement is the whole value of the diagnostic: the
5277-
// freestanding subset is an ordinary package, so the fix is one line in
5278-
// the manifest rather than a toolchain investigation.
5276+
// ⚠️ It used to end with a copy-pasteable
5277+
//
5278+
// [dependencies]
5279+
// mcpplibs.std.freestanding = "0.1"
5280+
//
5281+
// and that package is NOT published. A diagnostic whose suggested fix
5282+
// fails at the next command is worse than one that explains and stops:
5283+
// the reader spends the next minutes deciding whether their index is
5284+
// broken. Point at what a bare-metal project actually has today — the
5285+
// board package it already depends on exports a module — and describe
5286+
// the subset package as a shape rather than as a line to paste.
5287+
// Restore the concrete line when such a package ships.
52795288
if (auto ft = mcpp::toolchain::triple::parse(tc->targetTriple);
52805289
ft && ft->is_freestanding())
52815290
{
@@ -5286,13 +5295,19 @@ prepare_build(bool print_fingerprint,
52865295
"filesystem, iostreams\n"
52875296
" included), so there is no subset of it to build without "
52885297
"an OS underneath.\n"
5289-
" Use the freestanding subset instead:\n"
52905298
"\n"
5291-
" [dependencies]\n"
5292-
" mcpplibs.std.freestanding = \"0.1\"\n"
5299+
" What a bare-metal project uses instead:\n"
5300+
" * the module its BOARD package exports — that is where "
5301+
"the target's\n"
5302+
" C library is already wrapped (riscv-virt-rt exports "
5303+
"`mcpplibs.riscv_virt_rt`);\n"
5304+
" * or a freestanding subset package, which is an "
5305+
"ordinary dependency\n"
5306+
" providing the header-only parts of the library that "
5307+
"need no OS.\n"
52935308
"\n"
5294-
" then `import mcpplibs.std.freestanding;` in place of "
5295-
"`import std;`.",
5309+
" No such subset package is published yet, so there is no "
5310+
"line to paste here.",
52965311
tc->targetTriple));
52975312
}
52985313
return std::unexpected(std::format(

0 commit comments

Comments
 (0)