From eb0962c4ef25d35c887daf4adebcb331c52e3493 Mon Sep 17 00:00:00 2001 From: speak-agent Date: Fri, 11 Sep 2026 21:24:09 +0800 Subject: [PATCH] The Web leg of examples/portable is a boundary, and the linker says where it is `openkal-emscripten 0.1.0` is in the index, so the Web line now resolves. It does not build, and that is the mechanism rather than a gap. Measured, with the dependency resolved and every translation unit compiled: wasm-ld: error: obj/main.o: undefined symbol: kal_process_spawn wasm-ld: error: obj/main.o: undefined symbol: kal_process_wait wasm-ld: error: obj/main.o: undefined symbol: kal_process_close wasm-ld: error: obj/main.o: undefined symbol: kal_task_start wasm-ld: error: obj/main.o: undefined symbol: kal_task_join wasm-ld: error: obj/main.o: undefined symbol: kal_task_wait wasm-ld: error: obj/main.o: undefined symbol: kal_task_wake Seven names, each one this program uses and this platform does not have. There is no fork, no exec and no second address space under Emscripten, so `openkal.process`, `openkal.exec` and `openkal.space` are absent from that implementation -- and this program uses two of the three. THE CRITERION WAS WRONG AND THE MEASUREMENT IS WHAT SAID SO. The design record asked for this example to build "for all five platforms it names". It cannot, and neither way of making it could is acceptable: `#ifdef`-ing the one file in this ecosystem that exists to contain no platform awareness, or having `openkal-emscripten` provide operations it cannot perform, which is the shape clause 6.2 forbids -- present and always failing, which the caller cannot tell from a condition. So the line stays and the example is better for it. A program about portability that also shows where portability stops is worth more than one that stops at four platforms and says nothing about the fifth. The README and the manifest carry the linker's own output as the evidence, and note that `openkal.task` is a second question with the same answer here: the four `kal_task_*` names resolve under that implementation's `threads` feature, and the three `kal_process_*` names never will. The other three legs are measured and unchanged: host `0 observations that did not hold`, and both Android ABIs build over `openkal-linux` unchanged. --- examples/portable/README.md | 42 ++++++++++++++++++++++++++++++------- examples/portable/mcpp.toml | 19 +++++++++++++---- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/examples/portable/README.md b/examples/portable/README.md index 1b4ecef..8f78416 100644 --- a/examples/portable/README.md +++ b/examples/portable/README.md @@ -35,7 +35,7 @@ different ways: | macOS | `cfg(os = "macos")` | `openkal-macos` | | iOS, both simulator arches | `cfg(os = "ios")` | `openkal-macos`, unchanged | | Windows | `cfg(windows)` | `openkal-windows` | -| Web (Emscripten) | `cfg(os = "emscripten")` | `openkal-emscripten` | +| Web (Emscripten) | `cfg(os = "emscripten")` | `openkal-emscripten`, which provides twelve of fifteen | **Android needs no line of its own**, because `aarch64-linux-android` has `os = "linux"`: the kernel IS Linux, bionic is a C library above it, and an @@ -48,12 +48,40 @@ same call numbers, the same calling convention — and what differs between macO and iOS is the SDK and the deployment-target flag, which belong to the build tool. So one `cfg` line selects the macOS implementation for all three iOS rows. -**The Web needed new software.** Emscripten has no kernel to issue a call to, -so an implementation there cannot be written beneath a C library and has to sit -above one. `openkal-emscripten` provides twelve of the fifteen interfaces; this -program uses eight, all of which are among them. A program that used -`openkal.process` would fail at link naming the symbol, which is how a partial -surface reports itself. +**The Web needed new software, and this program does not fit on it.** +Emscripten has no kernel to issue a call to, so an implementation there cannot +be written beneath a C library and has to sit above one. `openkal-emscripten` +is that implementation, and it provides twelve of the fifteen interfaces: there +is no fork, no exec and no second address space on this platform, so +`openkal.process`, `openkal.exec` and `openkal.space` are absent. This program +uses `openkal.process` and `openkal.task`. + +So the Web line is here to show the BOUNDARY, and the boundary is a link error. +Measured: + +``` +$ mcpp build --target wasm32-emscripten +wasm-ld: error: obj/main.o: undefined symbol: kal_process_spawn +wasm-ld: error: obj/main.o: undefined symbol: kal_process_wait +wasm-ld: error: obj/main.o: undefined symbol: kal_process_close +wasm-ld: error: obj/main.o: undefined symbol: kal_task_start +wasm-ld: error: obj/main.o: undefined symbol: kal_task_join +wasm-ld: error: obj/main.o: undefined symbol: kal_task_wait +wasm-ld: error: obj/main.o: undefined symbol: kal_task_wake +``` + +Seven names, each one the program used and the platform does not have. That is +clause 6.2's second time and it is the mechanism rather than a defect: the +dependency RESOLVED, the compile succeeded, and the report arrived at the +earliest moment the information existed. An implementation that had provided +those seven so that they returned an error would have produced a program that +links, runs, and fails somewhere a reader cannot connect to a missing facility. + +`openkal.task` is a second question on this platform and has the same answer +here. It is carried by `openkal-emscripten`'s `threads` feature, because +`-pthread` selects a different C library build and memory model; with that +feature the four `kal_task_*` names above resolve. The three `kal_process_*` +names never will. ## The version pins here are a claim, and they were wrong diff --git a/examples/portable/mcpp.toml b/examples/portable/mcpp.toml index 4c98ed7..9300648 100644 --- a/examples/portable/mcpp.toml +++ b/examples/portable/mcpp.toml @@ -66,9 +66,20 @@ openkal-macos = "0.9.0" # ABOVE one, which clause 2 permits. `openkal-emscripten` is that # implementation. # -# It provides twelve of the fifteen interfaces. This program uses eight, all of -# which are among them; a program that used `openkal.process` would fail at -# LINK naming the symbol, which is clause 6.2's second time and is how a -# partial surface reports itself. +# IT PROVIDES TWELVE OF THE FIFTEEN INTERFACES, AND THIS PROGRAM DOES NOT FIT +# ON IT. There is no fork, no exec and no second address space on this +# platform, so `openkal.process`, `openkal.exec` and `openkal.space` are +# absent -- and this program uses `openkal.process` and `openkal.task`. +# +# The line stays, because what it demonstrates is the BOUNDARY. Measured: +# +# wasm-ld: error: obj/main.o: undefined symbol: kal_process_spawn +# ... and six more, one per name the program used and the platform lacks +# +# The dependency resolved and the compile succeeded; the report arrived at the +# earliest moment the information existed, which is clause 6.2's second time. +# An implementation that had provided those names so that they returned an +# error would have produced a program that links, runs, and fails where a +# reader cannot connect it to a missing facility. See the README. [target.'cfg(os = "emscripten")'.dependencies] openkal-emscripten = "0.1.0"