From 13c915106243abf819ca09a1e626fc0145faf458 Mon Sep 17 00:00:00 2001 From: speak-agent Date: Wed, 19 Aug 2026 12:57:36 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20std-freestanding=200.1.0=20?= =?UTF-8?q?=E2=80=94=20the=20freestanding=20subset=20of=20the=20standard?= =?UTF-8?q?=20library?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `import std;` is one module over the whole library, so there is no subset of IT to build without an OS — mcpp turns it off on a freestanding target and says so. But libc++'s HEADERS are almost entirely freestanding-capable already; what stops them is one per-target file, `__config_site`, which the toolchain ships only for its own host triple. Synthesising that file is this package's job. 103 of libc++'s 110 headers compile for riscv64-none-elf. The other 7 (generator, hazard_pointer, rcu, spanstream, stacktrace, stdfloat, text_encoding) fail on an x86_64 host with full libc++ and glibc too — they are headers libc++ has not implemented, so the freestanding loss at compile time is zero. The package's regeneration script prints that control group on every run. Verified running under qemu: array, span, optional, atomic, string_view, and ranges::sort with a projection. `xim:llvm` is an install-time dependency because that is where libc++'s headers live. Nothing is linked from it — the package includes them privately and exports a module — but without the payload there is nothing to include, and the failure would surface as "file not found" inside a module compile instead of as a missing dependency. Requires mcpp >= 2026.8.19.4: earlier versions do not put `-fno-exceptions` on a freestanding target, and `std::optional::value()` alone then pulls in `__cxa_throw` and three more symbols that cannot exist without an unwinder. --- pkgs/s/std-freestanding.lua | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 pkgs/s/std-freestanding.lua diff --git a/pkgs/s/std-freestanding.lua b/pkgs/s/std-freestanding.lua new file mode 100644 index 0000000..6a42ea7 --- /dev/null +++ b/pkgs/s/std-freestanding.lua @@ -0,0 +1,60 @@ +-- std-freestanding — the freestanding subset of the C++ standard library. +-- +-- Form A, and `deps` at the xpm PLATFORM level, for the same two reasons as +-- riscv-virt-rt: the package ships a `build.mcpp` (which mcpp looks for at the +-- package ROOT, so Form B would leave it one level down inside the tarball's +-- wrap directory and unfound), and mcpp materializes `[xlings] deps` for the +-- ROOT project only, so a consumer would otherwise get the package with +-- neither the target C library nor the toolchain whose payload carries +-- libc++'s headers. +-- +-- ⚠️ `xim:llvm` is a dependency because that is where libc++'s HEADERS live. +-- The package does not link anything from it — it privately includes the +-- headers and exports a module — but without the payload there is nothing to +-- include, and the failure would arrive as "file not found" deep inside a +-- module compile rather than as a missing dependency. +package = { + spec = "1", + namespace = "mcpplibs", + name = "std-freestanding", + description = "The freestanding subset of the C++ standard library as one module — import mcpplibs.std.freestanding", + licenses = {"Apache-2.0"}, + repo = "https://github.com/mcpplibs/std-freestanding", + type = "package", + + xpm = { + linux = { + deps = { "xim:picolibc-riscv@1.8.12", "xim:llvm" }, + ["0.1.0"] = { + url = { + GLOBAL = "https://github.com/mcpplibs/std-freestanding/archive/refs/tags/0.1.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/std-freestanding/releases/download/0.1.0/std-freestanding-0.1.0.tar.gz", + }, + sha256 = "b93b46d9267004eb409aa55fa8042173f93e71c68604969d54c1930baaf65abe", + }, + }, + macosx = { + deps = { "xim:picolibc-riscv@1.8.12", "xim:llvm" }, + ["0.1.0"] = { + url = { + GLOBAL = "https://github.com/mcpplibs/std-freestanding/archive/refs/tags/0.1.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/std-freestanding/releases/download/0.1.0/std-freestanding-0.1.0.tar.gz", + }, + sha256 = "b93b46d9267004eb409aa55fa8042173f93e71c68604969d54c1930baaf65abe", + }, + }, + windows = { + deps = { "xim:picolibc-riscv@1.8.12", "xim:llvm" }, + ["0.1.0"] = { + url = { + GLOBAL = "https://github.com/mcpplibs/std-freestanding/archive/refs/tags/0.1.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/std-freestanding/releases/download/0.1.0/std-freestanding-0.1.0.tar.gz", + }, + sha256 = "b93b46d9267004eb409aa55fa8042173f93e71c68604969d54c1930baaf65abe", + }, + }, + }, + + -- The package's own manifest, inside the tarball's wrap directory. + mcpp = "*/mcpp.toml", +} From 4f48c55ce5c006141b7abde6a1e24f01e9a28655 Mon Sep 17 00:00:00 2001 From: speak-agent Date: Wed, 19 Aug 2026 13:21:47 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20std-freestanding=200.2.0=20+=20risc?= =?UTF-8?q?v-virt-rt=200.3.0=20=E2=80=94=20the=20target=20owns=20its=20C?= =?UTF-8?q?=20library?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both packages declared `xim:picolibc-riscv@1.8.12`, and the standard-library subset also declared `xim:llvm`. That pinned a board package and an implementation-neutral library alike to one C library, one architecture, one toolchain and one version of each — none of which is a property of either. mcpp 2026.8.19.4 resolves the target's C library from the target's own row, the way it resolves the compiler: a hosted project never declared glibc, and a bare-metal one no longer declares picolibc. So: * std-freestanding 0.2.0 declares NOTHING. It asks mcpp where the toolchain's headers are, and the target's C headers are already on the compile line. * riscv-virt-rt 0.3.0 declares only the emulator, which is the one xim package that really is a board fact. Its linker line is bare names now, because the search path is there before it says anything. riscv-virt-rt 0.1.0 and 0.2.0 stay listed — published versions someone may have pinned. std-freestanding 0.1.0 is replaced rather than kept: it never reached this index, and it is wrong by construction. Both new versions require mcpp >= 2026.8.19.4. --- pkgs/r/riscv-virt-rt.lua | 41 ++++++++++++++++++++++-------- pkgs/s/std-freestanding.lua | 50 +++++++++++++++++-------------------- 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/pkgs/r/riscv-virt-rt.lua b/pkgs/r/riscv-virt-rt.lua index 6da525e..d339d82 100644 --- a/pkgs/r/riscv-virt-rt.lua +++ b/pkgs/r/riscv-virt-rt.lua @@ -9,13 +9,13 @@ -- link against nothing. Pointing at the manifest moves the root inside the -- wrap layer, where both the manifest and the program live. -- --- ⚠️ `deps` is at the xpm PLATFORM level, not in the mcpp segment. The two --- entries are xim packages (an emulator and a target sysroot), not mcpp --- packages, so they travel on xim's install-time dependency edge. This matters --- more than it looks: mcpp materializes `[xlings] deps` for the ROOT project --- only, so a consumer that just runs `mcpp add riscv-virt-rt` would otherwise --- get the board package with neither a libc nor an emulator, and find out at --- build.mcpp time. +-- ⚠️ `deps` names the EMULATOR and nothing else. The target's C library is not +-- here because it is not this package's: mcpp resolves it from the target's +-- own row, the way it resolves the compiler. What is left is the one xim +-- package that really is a board fact — how to run an image — and it is at the +-- xpm PLATFORM level because mcpp materializes `[xlings] deps` for the ROOT +-- project only, so a consumer running `mcpp add riscv-virt-rt` would otherwise +-- get a board package with no way to start it. package = { spec = "1", namespace = "mcpplibs", @@ -30,7 +30,7 @@ package = { -- published is a version someone may have pinned. xpm = { linux = { - deps = { "xim:picolibc-riscv@1.8.12", "xim:qemu-riscv@9.2.4-1" }, + deps = { "xim:qemu-riscv@9.2.4-1" }, ["0.1.0"] = { url = { GLOBAL = "https://github.com/mcpplibs/riscv-virt-rt/archive/refs/tags/0.1.0.tar.gz", @@ -45,9 +45,16 @@ package = { }, sha256 = "79f1dc4415a59ba828048eb8706322957723f8a6fd84bde3faba6a377e48242b", }, + ["0.3.0"] = { + url = { + GLOBAL = "https://github.com/mcpplibs/riscv-virt-rt/archive/refs/tags/0.3.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/riscv-virt-rt/releases/download/0.3.0/riscv-virt-rt-0.3.0.tar.gz", + }, + sha256 = "71fc43daa4903d4f3037c204bd2b3be9aea56371b123a4529cc8c0c8c9b7f525", + }, }, macosx = { - deps = { "xim:picolibc-riscv@1.8.12", "xim:qemu-riscv@9.2.4-1" }, + deps = { "xim:qemu-riscv@9.2.4-1" }, ["0.1.0"] = { url = { GLOBAL = "https://github.com/mcpplibs/riscv-virt-rt/archive/refs/tags/0.1.0.tar.gz", @@ -62,9 +69,16 @@ package = { }, sha256 = "79f1dc4415a59ba828048eb8706322957723f8a6fd84bde3faba6a377e48242b", }, + ["0.3.0"] = { + url = { + GLOBAL = "https://github.com/mcpplibs/riscv-virt-rt/archive/refs/tags/0.3.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/riscv-virt-rt/releases/download/0.3.0/riscv-virt-rt-0.3.0.tar.gz", + }, + sha256 = "71fc43daa4903d4f3037c204bd2b3be9aea56371b123a4529cc8c0c8c9b7f525", + }, }, windows = { - deps = { "xim:picolibc-riscv@1.8.12", "xim:qemu-riscv@9.2.4-1" }, + deps = { "xim:qemu-riscv@9.2.4-1" }, ["0.1.0"] = { url = { GLOBAL = "https://github.com/mcpplibs/riscv-virt-rt/archive/refs/tags/0.1.0.tar.gz", @@ -79,6 +93,13 @@ package = { }, sha256 = "79f1dc4415a59ba828048eb8706322957723f8a6fd84bde3faba6a377e48242b", }, + ["0.3.0"] = { + url = { + GLOBAL = "https://github.com/mcpplibs/riscv-virt-rt/archive/refs/tags/0.3.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/riscv-virt-rt/releases/download/0.3.0/riscv-virt-rt-0.3.0.tar.gz", + }, + sha256 = "71fc43daa4903d4f3037c204bd2b3be9aea56371b123a4529cc8c0c8c9b7f525", + }, }, }, diff --git a/pkgs/s/std-freestanding.lua b/pkgs/s/std-freestanding.lua index 6a42ea7..dc96c0d 100644 --- a/pkgs/s/std-freestanding.lua +++ b/pkgs/s/std-freestanding.lua @@ -1,18 +1,17 @@ -- std-freestanding — the freestanding subset of the C++ standard library. -- --- Form A, and `deps` at the xpm PLATFORM level, for the same two reasons as --- riscv-virt-rt: the package ships a `build.mcpp` (which mcpp looks for at the --- package ROOT, so Form B would leave it one level down inside the tarball's --- wrap directory and unfound), and mcpp materializes `[xlings] deps` for the --- ROOT project only, so a consumer would otherwise get the package with --- neither the target C library nor the toolchain whose payload carries --- libc++'s headers. +-- Form A because the package ships a `build.mcpp`, which mcpp looks for at the +-- package ROOT: Form B would leave it one level down inside the tarball's wrap +-- directory, unfound, and the package would resolve and compile and then link +-- against nothing. -- --- ⚠️ `xim:llvm` is a dependency because that is where libc++'s HEADERS live. --- The package does not link anything from it — it privately includes the --- headers and exports a module — but without the payload there is nothing to --- include, and the failure would arrive as "file not found" deep inside a --- module compile rather than as a missing dependency. +-- ⚠️ NO `deps`, and that is the design. This package needs libc++'s headers +-- and the target's C headers, and it gets both by ASKING mcpp +-- (`mcpp::toolchain_dir()`, and the target's libc which mcpp already puts on +-- the compile line) rather than by declaring who provides them. Declaring +-- pinned it to one standard-library implementation, one C library, one +-- architecture and one version of each — none of which it has any business +-- knowing about. package = { spec = "1", namespace = "mcpplibs", @@ -24,33 +23,30 @@ package = { xpm = { linux = { - deps = { "xim:picolibc-riscv@1.8.12", "xim:llvm" }, - ["0.1.0"] = { + ["0.2.0"] = { url = { - GLOBAL = "https://github.com/mcpplibs/std-freestanding/archive/refs/tags/0.1.0.tar.gz", - CN = "https://gitcode.com/mcpp-res/std-freestanding/releases/download/0.1.0/std-freestanding-0.1.0.tar.gz", + GLOBAL = "https://github.com/mcpplibs/std-freestanding/archive/refs/tags/0.2.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/std-freestanding/releases/download/0.2.0/std-freestanding-0.2.0.tar.gz", }, - sha256 = "b93b46d9267004eb409aa55fa8042173f93e71c68604969d54c1930baaf65abe", + sha256 = "c0026e6aa85d207b3dd00c3f2fe2674174c2e25d86a162f64fe70742420efb00", }, }, macosx = { - deps = { "xim:picolibc-riscv@1.8.12", "xim:llvm" }, - ["0.1.0"] = { + ["0.2.0"] = { url = { - GLOBAL = "https://github.com/mcpplibs/std-freestanding/archive/refs/tags/0.1.0.tar.gz", - CN = "https://gitcode.com/mcpp-res/std-freestanding/releases/download/0.1.0/std-freestanding-0.1.0.tar.gz", + GLOBAL = "https://github.com/mcpplibs/std-freestanding/archive/refs/tags/0.2.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/std-freestanding/releases/download/0.2.0/std-freestanding-0.2.0.tar.gz", }, - sha256 = "b93b46d9267004eb409aa55fa8042173f93e71c68604969d54c1930baaf65abe", + sha256 = "c0026e6aa85d207b3dd00c3f2fe2674174c2e25d86a162f64fe70742420efb00", }, }, windows = { - deps = { "xim:picolibc-riscv@1.8.12", "xim:llvm" }, - ["0.1.0"] = { + ["0.2.0"] = { url = { - GLOBAL = "https://github.com/mcpplibs/std-freestanding/archive/refs/tags/0.1.0.tar.gz", - CN = "https://gitcode.com/mcpp-res/std-freestanding/releases/download/0.1.0/std-freestanding-0.1.0.tar.gz", + GLOBAL = "https://github.com/mcpplibs/std-freestanding/archive/refs/tags/0.2.0.tar.gz", + CN = "https://gitcode.com/mcpp-res/std-freestanding/releases/download/0.2.0/std-freestanding-0.2.0.tar.gz", }, - sha256 = "b93b46d9267004eb409aa55fa8042173f93e71c68604969d54c1930baaf65abe", + sha256 = "c0026e6aa85d207b3dd00c3f2fe2674174c2e25d86a162f64fe70742420efb00", }, }, },