You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

19 KiB

G-140 Linux lib-tier emission: cross-built tcllibc (zig cc -target) for the punk9linux payload

Status: achieved 2026-07-30 Scope: src/buildsuites/suite_tcl90/ (critcl_zig.config linux target section; build905.zig cross-target library-artifacts lane; tools as touched); src/runtime/libpackages.toml + src/runtime/vendorlib_vfs.toml (linux-x86_64 artifact + kit-vfs declarations); src/vfs/punk9linux.vfs/lib_tcl9 (hand-dropped tcllibc + stray tcllibc2.0 - retirement targets); punkbin artifact repo (external, c:/repo/jn/punkbin - new lib/linux-x86_64 target folder); bin/packages/linux-x86_64/ (tier target as materialized); WSL verification (testsupport/wslprobe.tcl patterns + a punkbin linux-x86_64 Tcl 9 runtime as the smoke interpreter) Goal: the punkbin lib tier serves a linux-x86_64 tcllibc built by the existing windows suite - critcl driving zig cc with an explicit linux target (stubs linkage: no cross-built Tcl runtime and no linux build host required) - emitted through the established G-138 machinery (generation-tagged immutable zip, embedded class=library record whose target is linux-x86_64 and whose build_host_platform records the actual build host), verified functional under the local WSL with an existing linux Tcl 9 runtime, and consumed by punk9linux.vfs through the established G-139 declaration path - retiring the last provenance-less accelerator hand-drops (tcllibc + the stray-named tcllibc2.0) so every accelerator in every kit payload is artifact-fed and self-describing. Acceptance: a documented suite_tcl90 invocation produces lib/linux-x86_64/tcllibc-tcl9-r.zip from a critcl build driving zig cc via an explicit linux target section in critcl_zig.config (the win32-x86_64-zig pin pattern; no linux host in the build path), with the embedded record carrying target = linux-x86_64, build_host_platform = the actual build host, and the G-138 provenance set (checkout uuids, critcl version, zig version, optimize mode, driving-shell patchlevel); the contained shared library classifies as ELF x86-64 by a host-side structural check (the G-133 classifier or equivalent, recorded here); re-emission over an unchanged build is byte-identical; the libc/triple decision (dynamic glibc with a pinned version floor vs musl-dynamic - the .so must dlopen into existing glibc-dynamic linux tclsh builds without mixing libcs) is made and recorded here with rationale, explicitly feeding the G-105 decision item rather than re-deciding it later; a WSL (or native linux) smoke on the MATERIALIZED artifact tree under a linux-x86_64 Tcl 9 runtime (e.g. the punkbin tclkit-902 artifact) proves package require md5 engages the critcl accelerator from the tree (evidence recorded here); consumption lands via libpackages.toml (target linux-x86_64) and a vendorlib_vfs.toml entry switching punk9linux.vfs/lib_tcl9 with supersedes/replace retiring the hand-dropped tcllibc and tcllibc2.0; a punkshell902 bake ships the artifact-fed tree with its embedded record present in the kit payload, and a WSL run of the baked kit loading md5 with the accelerator engaged is recorded; publication to the real punkbin repo remains a deliberate user step (build_sha1sums.tcl already handles arbitrary lib/ folders); the tcl8-generation question is dispositioned (no linux tcl8 kit exists - recorded as out of the committed set, with the mechanism staying package-generic and generation-generic by construction).

Context

Flagged at the G-139 achieved flip (2026-07-30): punk9linux.vfs kept its linux-built tcllibc + tcllibc2.0 sibling folders through the switchover because the win32-x86_64 artifacts cannot serve a linux kit - they are now the last accelerator hand-drops in any kit payload, carrying the same no-provenance profile the retired win32 trees had (and a stray versioned folder name besides). The pure-Tcl side is already artifact-fed: punk9linux.vfs receives the allplatforms tcllib2.0 artifact like every other declared kit.

Why this does not wait for G-105: tcllibc is a stubs-linked extension - critcl bundles its own Tcl headers and links nothing from a Tcl runtime, so cross-compiling the .so needs only zig cc -target plus a critcl config section; the installer/critcl DRIVER runs under the existing suite-built windows shell. G-105's committed content (cross-built tclsh, WSL core-testsuite baseline, per-target out prefixes, the general triple<->canon mapping) is not on this goal's path; the smoke interpreter is an EXISTING linux runtime punkbin already hosts.

Approach

  • Extend, don't fork: the emission tool is already package-generic and records tier separately from build_host_platform (the G-138 record shape anticipated cross-emission); the new work is the critcl_zig.config linux section, a build905.zig lane invoking critcl with the linux -target and emitting via the same tools/library_artifacts.tcl, and the WSL smoke.
  • Triple direction (decided in the work, recorded here): dynamic glibc with a conservative version floor (e.g. x86_64-linux-gnu.2.17-class) - the .so must dlopen into existing glibc-dynamic linux tclsh builds (tclkit-902 is the concrete consumer); a musl-libc .so inside a glibc process mixes libcs. This mirrors and feeds G-105's recorded dynamic-libc analysis.
  • Verification split: structural host-side (ELF class check, determinism) vs functional WSL-side (materialized-tree accel smoke; baked-kit smoke) - the wslprobe staging patterns apply (native-FS staging, never operate on the checkout from inside WSL).
  • Consumption is pure G-139 idiom: declare, fetch (the tier gains its first linux-x86_64 target folder), vfslibs supersedes/replace, cross-target bake per G-122 (punkshell902 already bakes target-keyed from windows).

Alternatives considered

  • Wait for G-105 and build tcllibc natively on the cross-built linux tclsh - rejected as a dependency: stubs linkage makes the cross .so independently buildable now; G-105 remains the runtime arc and gains this goal's libc decision as prior art.
  • Adopt the existing hand-dropped linux tcllibc as a third-party-class artifact (G-123 ingest posture) - rejected: the copies are provenance-less local builds of unknown vintage; the suite path exists and gives the same provenance story as every other lib-tier artifact.
  • Ship the win32 tcllibc record shape with a linux dll only (single-file swap) - rejected: the zip carries the whole installed-shape folder; a fresh critcl build against the pinned tcllib checkout is the honest unit.

Notes

  • Related: G-105 - the cross-target runtime arc; shares the zig -target axis and the dynamic-libc analysis. This goal deliberately lands first on a narrower lane and records the triple/floor decision as input to G-105's mapping and baseline work (not a dependency in either direction).
  • Related: G-116 - the tcltls battery would ride this same cross lane for any future linux emission of its packages.
  • Related: G-130 - target-family sibling (32-bit windows) on the same package-generic emission mechanism.
  • Related: G-060 - verification environments beyond WSL (qemu matrix) if the smoke ever needs a non-WSL linux.
  • Related: G-123 - punkbin server surfaces; the lib/linux-x86_64 folder is a new target row in the documented layout.
  • Related: G-004 / G-065 - posture: the retirement extends the no-committed-binaries payoff to the linux kit payload.
  • Anchors (archived): G-138 (the emission machinery and record schema - goals/archive/G-138-punkbin-library-artifact-tier.md), G-139 (the consumption idiom and the flip note that flagged this goal - goals/archive/G-139-punkbin-library-consumption.md), G-122 (target-keyed bake), G-102 (critcl -target pin finding), G-133 (achieved - the binary-arch classifier the Acceptance's host-side ELF check leans on - goals/archive/G-133-bake-payload-consistency-checks.md).
  • punk::platform survey item: linux-x86_64's record axes (tiers/buildsuite) reviewed at landing - a library cross-build does not flip the runtime buildsuite axis ('planned' per G-105); whether the lib tier axis needs a value update is settled in the work.
  • Related: G-127 - cross-target bake output goal; its acceptance names punk9linux.vfs migration to declarations and the linux punkshell902 kit's intended move to bin/kits/linux-x86_64/. This goal's punkshell902 bake rides today's output layout; G-127 owns relocating it.
  • Related: G-115 - vendorlib_vfs.toml successor surface (declarative .vfs composition); the consumption declarations here ride whichever surface is current, per the G-139 precedent.
  • Activation survey 2026-07-30: goals_xref score G-140 re-run at activation (user-directed, same day as drafting): two real overlaps beyond the drafting survey recorded above (G-127, G-115 - both vendorlib_vfs.toml / punk9linux.vfs surfaces); remaining unlinked pairs (G-023/G-016/G-022/ G-006/G-005) share only ubiquitous anchors, no contract relationship.
  • LIBC/TRIPLE DECISION (2026-07-30, the acceptance's recorded decision - feeds G-105's dynamic-libc analysis): dynamic glibc via zig triple x86_64-linux-gnu.2.17. Rationale: the concrete consumers (punkbin tclkit-902-Linux64-intel-dyn - verified ELF x86-64 with interpreter /lib64/ld-linux-x86-64.so.2, i.e. glibc-dynamic - and any suite-family linux runtime G-105 later produces) are glibc processes, so a musl .so would mix two libcs in one process (rejected); static-musl is not an option for a dlopen'd extension anyway. 2.17 is the conservative CentOS7-era floor: comfortably below every candidate consumer distro (WSL Ubuntu 22.04/24.04 = glibc 2.35/2.39, AlmaLinux 9 = 2.34) and present in the pinned zig 0.16.0's bundled glibc-stub list (verified via 'zig targets'). The floor rides ONLY the zig triple; the in-package platform folder stays glibc-agnostic (next note).
  • critcl cross-target mechanism (2026-07-30 finding): the config section's 'platform' value becomes critcl's targetplatform/actualtarget, which names BOTH the in-package shared-lib folder and teapot's 'Meta platform' on cross builds (TeapotPlatform upgrades to platform::identify - the glibc-versioned form - only when building natively). The generated loader resolves the folder via ::critcl::runtime::MapPlatform = platform::generic, so the folder must be 'linux-x86_64', NOT a glibc-versioned name. The retired hand-drop confirms the shape: folder linux-x86_64 with teapot 'Meta platform linux-glibc2.22-x86_64' (a native linux critcl 3.3 build, 2025-08-20 vintage). Our cross build records teapot 'Meta platform linux-x86_64' - truthful (any glibc >= floor), with the exact floor in the artifact record + this file.
  • Overlap survey 2026-07-30 (drafting): goals_xref paths src/buildsuites/suite_tcl90, src/vfs/punk9linux.vfs, src/runtime/libpackages.toml, src/runtime/vendorlib_vfs.toml, bin/packages, src/runtime/mapvfs.config - strongest live intersections G-105 (cross-target axis - carried above), G-123/G-116/G-130 (carried), G-108/G-110/G-131 (suite-tree co-location only, no contract relationship), G-004/G-065/G-025 (posture, carried or not applicable); no live goal owns the punk9linux tcllibc hand-drops.

Progress

  • 2026-07-30 activated (user-directed); emission side LANDED and verified:
    • critcl_zig.config linux-x86_64-zig section (zig cc -target x86_64-linux-gnu.2.17, sharedlibext .so, platform identifier linux-x86_64 - mechanism + libc decision notes above).
    • build905.zig tcllibc-linux step (in the default step lists, suite.tcl + -Dsteps parity): the native critcl invocation with -target linux-x86_64-zig, own cache/libdir outputs, installed to out/lib-linux-x86_64/tcllibc; gated by tools/elf_gate.tcl (new, self-contained: the G-133 classifier's ELF checks - magic, EI_CLASS 64, EI_DATA LSB, e_machine x86_64 - plus e_type ET_DYN; an empty tree fails). Gate PASS: linux-x86_64/tcllibc.so ELF64 LSB ET_DYN x86_64.
    • uuid finding: tcllib uuid.tcl's accelerator is WINDOWS-ONLY C (rpcrt4 UuidCreate behind a tcl_platform(platform)=="windows" guard evaluated in the critcl DRIVER) - first cross attempt failed on windows.h. The lane EXCLUDES uuid/uuid.tcl, reproducing upstream's own native-linux package shape (the guard is false there; uuid rides its pure-tcl path which uses the md5 accelerator). Installed shape verified identical to the hand-drop's (folder set + linux-x86_64/tcllibc.so + teapot 'Meta platform linux-x86_64').
    • library-artifacts emission extended with the third 5-tuple: emitted lib/linux-x86_64/tcllibc-tcl9-r1.zip (8 members, ~139KB) beside the native artifacts, per-tier sha1sums incl. the new linux-x86_64 tier. Record verified: target=linux-x86_64, build_host_platform= win32-x86_64, tcllib+critcl checkout uuids, critcl 3.3.1 (from the cross build's own teapot.txt), zig 0.16.0, ReleaseFast, driving_tcl_patchlevel 9.0.5; NO [tests] section (the G-107 evidence (achieved - goals/archive/G-107-buildsuite-library-tests.md) attaches to the win32 accelerators the tests exercised - the linux functional evidence is the WSL smoke below).
    • build_id seed fix (both suites' library_artifacts.tcl copies, kept byte-identical): the seed now includes the tier path (lib//) - same-named artifacts in different target tiers (the win32/linux tcllibc pair) previously would have shared an identity digest. Published r1 records keep their build_ids (immutable); local re-emissions at r1 now differ from published r1 bytes in that field - immaterial: revisions never re-publish.
    • Determinism VERIFIED: two direct back-to-back zig build library-artifacts runs over the unchanged build produced byte-identical zips for ALL THREE artifacts (linux e5e7bb0c... twice). Session-env finding EXTENDED: the zig Run cache keys the inherited env - beyond PATH (the recorded G-138 trap), suite.tcl itself sets FOSSIL_HOME, so a suite.tcl-driven emission and a direct zig build emission are DIFFERENT cache sessions; the first invocation in a new env re-runs critcl/installers and drifts the native (non-bit-reproducible) dll bytes and install mtimes. The linux ELF .so was observed BIT-STABLE across such re-runs (sha 96843110... constant) - windows PE non-reproducibility does not carry over; the zip-level drift across env changes comes from re-install mtimes. Publish discipline unchanged.
    • Documented invocation (also in the suite README "Linux cross lane" section): tclsh suite.tcl build (defaults) or explicit -steps including tcllibc-linux + library-artifacts.
  • 2026-07-30 consumption phase 1 + WSL MATERIALIZED-TREE SMOKE (the acceptance's functional evidence):
    • libpackages.toml gained [artifact.tcllibc-tcl9-linux] (name tcllibc-tcl9-r1.zip, target linux-x86_64). libfetch is target-generic; materialized via the PUNK_LIBFETCH_CONFIG seam (linux-only declarations) from a file:// mirror of the suite staging with -trust-server -> bin/packages/linux-x86_64/tcl9/tcllibc (fetched + sha1-verified + materialized; the published-r1-matching allplatforms/win32 tier copies deliberately untouched).
    • WSL smoke PASS (default distro Ubuntu 24.04, glibc 2.39; runtime bin/runtime/linux-x86_64/tclkit-902-Linux64-intel-dyn = Tcl 9.0.2): staged the materialized tcllibc + tcllib2.0 trees to WSL-native /tmp (wslprobe staging pattern - one-way copy-in, never operating on the checkout), auto_path with the staged lib prepended; package require md5 -> md5 2.0.9 from the staged tcllib2.0, tcllibc 2.0 loaded from .../lib/tcllibc/linux-x86_64/tcllibc.so (MapPlatform resolved the linux-x86_64 folder), accel(critcl)=1, md5 -hex correct (5EB63BBB...); self-gating assertions on all resolution paths passed (SMOKE-OK). Note: wholesale auto_path REPLACEMENT breaks the kit's own auto_load/tm chain (::tcl::UnknownHandler resolves via auto_index) - prepend + path assertions is the working pattern.
  • 2026-07-30 consumption phase 2: kit switchover + BAKE + BAKED-KIT WSL SMOKES:
    • vendorlib_vfs.toml [install.tcllibc_tcl9_linux]: source_root=packages, source linux-x86_64/tcl9/tcllibc, target punk9linux.vfs/lib_tcl9, replace=true + supersedes tcllibc2.0. vfslibs run: superseded 'tcllibc2.0' REMOVED, hand-dropped 'tcllibc' clean-slate REPLACED by the artifact-fed tree (embedded record present; .so byte-identical to the tier copy, sha 96843110...). The last provenance-less accelerator hand-drops in any kit payload are retired.
    • Selective bake punkshell902 (tclkit-902-Linux64-intel-dyn + punk9linux.vfs, metakit container): shipped bin/punkshell902. The bake's own G-133 payload binary-arch scan for target linux-x86_64: OK
      • 6 binary libraries scanned, 6 match target, 3 exempt under platform subdirs, 0 unclassifiable (our tcllibc.so among the scanned). G-122 cross-target handling engaged (icon N/A for non-PE, process sweep and smoke-require skipped as cross-target).
    • WSL baked-kit smoke A (default paths): './punkshell902 script ...' under the default WSL distro - md5 2.0.9 + tcllibc 2.0, accel(critcl)=1, correct digest; embedded record read from the kit payload's lib_tcl9/tcllibc/punkbin-artifact.toml and field-checked (name/target/build_id/build_host_platform). FINDING: the loaded .so was the RUNTIME's own bundled copy at lib/tcllibc2.0/ - the tclkit-902 runtime carries tcllibc inside its attached vfs under the stray-versioned folder name, which explains where the retired punk9linux tcllibc2.0 hand-drop name CAME from, and that copy wins default package-path precedence over the kit tree's lib_tcl9.
    • WSL baked-kit smoke B (pinned): fresh kit process, package forget + auto_path pinned to the kit's OWN lib_tcl9 - the artifact-fed /lib_tcl9/tcllibc/linux-x86_64/tcllibc.so LOADED (info loaded path assertion), accel(critcl)=1, md5 correct, md5 resolved from the kit tree (SMOKE-OK-PINNED). So the shipped artifact tree is proven functional from inside the baked kit, while the runtime's bundled copy shadows it on default paths - relevant when pairing the _basic runtime variant (no bundled batteries), where the kit tree is the only provider.
  • 2026-07-30 dispositions + reviews (acceptance items):
    • tcl8 generation: OUT of the committed set - no linux tcl8 kit exists (no mapvfs entry pairs a linux runtime with a tcl8 vfs). The mechanism stays package-generic and generation-generic by construction: suite_tcl86 shares the byte-identical library_artifacts.tcl (including the tier-in-build_id-seed change), and a future linux tcl8 lane would be the same config-section + critcl-step + 5-tuple pattern.
    • punk::platform axes review: NO value changes needed. linux-x86_64 already carries tiers {runtime lib} (the lib axis covers lib_tclX/ trees - now artifact-fed); buildsuite stays 'planned' - that axis describes RUNTIME production (G-105), which a library cross-build deliberately does not flip.
    • Publication: remains the deliberate user step. The emitted artifacts sit in suite staging out/library/punkbin/lib/linux-x86_64/ (zip + sidecar + per-tier sha1sums; revision r1 unbumped - nothing new published this goal). punkbin's build_sha1sums.tcl already handles arbitrary lib/ folders (G-138). After publication, the already-declared libpackages.toml entry serves plain canonical 'make.tcl libfetch' with no further edits.