Skip to content

Commit c683263

Browse files
committed
fix(build): a target side with no C library must not link one's startup files
A hosted target whose C-ABI layer is absent is a real shape: a program that calls the platform interface directly depends on the platform implementation and nothing above it. The driver does not know that. Told to emit for a hosted triple it supplies crt1.o, crti.o, the gcc startup objects and a dynamic linker, all of them the host machine's, and the hermetic link check reports them one by one: /usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o (outside the sandbox) /lib64/ld-linux-x86-64.so.2 (outside the sandbox) `-nostdlib` removes the startup objects; `-static` removes the interpreter, which is not a policy choice either -- a dynamic executable names an interpreter and lets a loader resolve its imports, and with no C library there is nothing to resolve. Measured end to end afterwards: openkal-linux with the standalone feature plus the five-function C surface builds a static ELF that runs and prints. Claude-Session: https://claude.ai/code/session_01Q4ucduLuSsETHYJ1RkGVVD
1 parent 8050833 commit c683263

2 files changed

Lines changed: 46 additions & 2 deletions

File tree

.agents/docs/2026-08-23-target-side-resolution-architecture.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,40 @@ Target x86_64-windows-gnu → x86_64-w64-windows-gnu
10051005

10061006
```toml
10071007
[dependencies]
1008-
openkal-linux = { git = "https://github.com/mcpplibs/openkal-linux", features = ["standalone"] }
1008+
openkal-linux = { git = "…/openkal-linux", features = ["standalone"] }
1009+
std-freestanding-nolibc = "^0.2.0" # ⭐ 见下
1010+
1011+
[target.x86_64-linux-gnu]
1012+
sysroot = ""
1013+
```
1014+
1015+
**实测(2026-08-24)必须补两处,而两处都是本形态的性质:**
1016+
1017+
其一,`std-freestanding-nolibc`。openkal-linux 自身要用 `memset`,而这一层之下没有 C 库:
1018+
1019+
```
1020+
ld.lld: error: undefined symbol: memset
1021+
```
1022+
1023+
这正是该包存在的理由 ——「a freestanding C++ library still needs 五个函数四个头」。
1024+
1025+
其二,mcpp 侧的链接行。驱动被指向一个 hosted 三元组时会自带 crt 启动件与动态加载器,而本形态
1026+
两者都不该有:
1027+
1028+
```
1029+
/usr/lib/gcc/x86_64-linux-gnu/13/crtbeginS.o (outside the sandbox)
1030+
/lib64/ld-linux-x86-64.so.2 (outside the sandbox)
1031+
```
1032+
1033+
⇒ 本轮实现:`c-abi` 缺席时链接行加 `-nostdlib -static`。理由不是策略而是性质 —— **没有 C 库
1034+
就没有它的启动件,也没有属于这个程序的解释器。**
1035+
1036+
实测结果:
1037+
1038+
```
1039+
Compiling openkal-linux / std-freestanding-nolibc v0.2.0
1040+
Finished dev
1041+
产物: ELF 64-bit LSB executable, x86-64 运行: raw openkal exit=0
10091042
```
10101043

10111044
| | |

src/build/flags.cppm

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,18 @@ CompileFlags compute_flags(const BuildPlan& plan) {
14591459
// does not have. The platform package supplies the entry point (its
14601460
// `standalone` feature says so); what the driver must be told is to
14611461
// stop supplying one of its own.
1462-
if (plan.targetSide.cAbi.absent()) graphLd += " -nostdlib";
1462+
//
1463+
// `-static` for the same reason, and it is not a policy choice. A
1464+
// dynamic executable names an interpreter in its program headers and
1465+
// the loader resolves its imports at run time; with no C library there
1466+
// is nothing to resolve and no interpreter that belongs to this
1467+
// program. Left off, the driver writes the HOST's:
1468+
//
1469+
// /lib64/ld-linux-x86-64.so.2 (outside the sandbox)
1470+
//
1471+
// — the one line that survived after `-nostdlib` removed the startup
1472+
// objects, measured.
1473+
if (plan.targetSide.cAbi.absent()) graphLd += " -nostdlib -static";
14631474
// Names a FAMILY; the driver picks the flavour from the target, which
14641475
// is the one part of the selection that is still ours to make.
14651476
//

0 commit comments

Comments
 (0)