13 KiB
G-130 32-bit windows runtimes from the buildsuites, both Tcl generations
Status: proposed Scope: src/buildsuites/suite_tcl90/ and src/buildsuites/suite_tcl86/ (the win32-ix86 target invocation and any recipe or flag divergence 32-bit forces); src/buildsuites/ (target dimension as settled by G-105 - no per-target tree copies); bin/runtime/win32-ix86/ (output tier - already holds the third-party comparison runtimes); punkbin per-target artifact layout with G-103 metadata carrying the target Goal: punkshell's own buildsuites produce current 32-bit windows (win32-ix86) runtimes for BOTH Tcl generations from source with the pinned zig toolchain, so a machine that is old, firewalled or sandboxed - and that carries tcl8-only or tcl9-only binary modules which must be dropped in - can be served whichever generation its modules need from one supplier we control, instead of depending on third-party builds that no single source keeps current for both majors. Acceptance: suite_tcl86 and suite_tcl90 each produce a win32-ix86 runtime through the documented target invocation, without disturbing the native build and without a per-target copy of the suite tree; each artifact runs on windows executing a script and resolving its bundled companions (thread and tclvfs for the 8.6 runtime, thread for the 9 runtime), with tcl_platform(pointerSize) 4 recorded; each loads a 32-bit BINARY EXTENSION - the motivating capability - verified against a real one rather than a stub (twapi 4.7.2 as shipped in bin/runtime/win32-ix86/tclsh8.6.10-luck-zip.exe is a 32-bit dll already in the tree for the 8.6 side; the 9-side extension is named at activation); each suite's core-testsuite run is recorded here against its own 32-bit baseline with every divergence from the corresponding 64-bit baseline dispositioned; any pointer-size or ABI assumption the 32-bit target exposes in the suite recipes is recorded; and the artifacts land in bin/runtime/win32-ix86/ and publish with G-103 metadata whose target names the 32-bit platform, so 'punk-runtime.cmd list -platform win32-ix86' shows them beside the third-party runtimes they are intended to replace.
Context
The motivation is not architectural completeness, it is supply. Old, firewalled or sandboxed systems - industrial ones especially - are where 32-bit still turns up, and those are exactly the machines that cannot go and fetch what they need. Such a system may carry binary Tcl modules built for only one major version, so the runtime has to match the modules rather than the other way round. There is no single supplier keeping current 32-bit windows Tcl available for BOTH majors, which means today the answer is assembled from third-party builds of differing vintage and provenance.
punkshell already builds Tcl from source with a pinned zig toolchain for both generations (suite_tcl90, suite_tcl86 - G-096/G-098/G-099/G-100, all achieved and archived), and G-105 establishes the target as an invocation dimension rather than a tree copy. 32-bit windows is the first target where the change is one of BITNESS rather than OS, which is what makes it worth its own goal: it exercises pointer-size and ABI assumptions that a linux-x86_64 cross does not.
Two third-party 32-bit runtimes now sit in bin/runtime/win32-ix86/ and serve as the
comparison baseline for what a suite-built pair would replace:
tclsh8.6.10-luck-zip.exe (Lean Undroidwish Construction Kit, Tcl 8.6.10, zipfs backport,
38 bundled packages) and tclsh9.1b0-tclsfe.exe (apnadkarni/tcl-sfe, Tcl 9.1b0). Between
them they demonstrate the shape is achievable; neither is ours, and neither is current for
the other's generation.
Approach
- Treat 32-bit windows as one more value of G-105's target dimension, not a suite fork. If it cannot be expressed that way, that is a finding about the dimension's design and belongs back in G-105 before this goal proceeds.
- Build BOTH generations before declaring the goal met. A single-generation result does not serve the motivating case, which is precisely that the machine's modules dictate the generation.
- Gate on loading a real 32-bit binary extension. Producing a runtime that starts is not the outcome; producing one that can accept the drop-in modules those systems carry is.
- Compare against the third-party specimens rather than only against a self-consistent baseline - they are the status quo this replaces.
Alternatives considered
- Keep sourcing 32-bit windows Tcl from third parties - rejected as the status quo the goal exists to end: no single supplier is current for both majors, and provenance for a locked-down deployment target is exactly where third-party binaries are weakest (G-026/G-063 direction).
- Build 32-bit for one generation only (whichever is easier) - rejected: the motivating systems are those whose existing binary modules force the choice of generation, so a one-generation answer leaves half of them unserved.
- Defer until FreeBSD and other targets land - rejected on the developer's sequencing (recorded 2026-07-27): this should slot in before or around the FreeBSD work, because the bitness axis is likelier to surface recipe assumptions than another OS on the same bitness, and finding those early is cheaper.
Notes
- Depends on: G-105 - the target-as-invocation-dimension mechanism and the punkshell-platform-dir vs zig-triple naming mapping. This goal is a consumer of that decision and a second exercise of it after linux.
- Related: G-101 - which container a suite-built 8.6 runtime can be wrapped into is decided there, not here. THIS GOAL PRODUCES RUNTIMES, NOT KITS: kit/container type is deliberately out of Scope, so a 32-bit runtime that is not yet wrappable still satisfies it. The two meet when G-101's decision lands.
- G-103 (achieved 2026-07-22 - see goals/archive/G-103-runtime-kit-family.md) defines the artifact-metadata contract the Scope and Acceptance above name: a published runtime's record carries its target, which for this goal must name the 32-bit platform.
- Related: G-123 (achieved 2026-07-31 - see
goals/archive/G-123-thirdparty-runtime-tiers.md) - the artifacts publish through
the runtime-tier mechanism, and
punk-runtime.cmd list -platform win32-ix86is where a user would see suite-built runtimes appear beside the third-party ones. - Related: G-129 (achieved 2026-07-27 - see goals/archive/G-129-kitboot-mountpoint-derivation.md)
- the third-party 8.6 specimen in this tier is what exposed punkshell's kit-boot mount-point assumption. That is a boot-path concern and separate from producing the runtime, but both goals use the same two specimens, now wrapped as the active verification kits punkluck86 + punk91ix86.
- Related: G-018 (superseded) - plain zig-built tclsh kits carrying no punk infrastructure; the same "punkshell as a Tcl supplier, not only a shell" direction this goal serves.
punk::platform::localalready reportswin32-ix86correctly from a 32-bit interpreter (verified 2026-07-27 on both third-party runtimes), andmake.tcl checkderiveshost=win32-ix86 target=win32-ix86 store=bin/runtime/win32-ix86when driven by one. No platform-canon work is required; the tier name the store already uses is the canonical one.- G-133 (archived) is what lets this goal's first-party 32-bit runtimes/packages grow the win32-ix86 verification kits' payloads without advisory noise: binaries under platform-discriminated subdirs (win32-ix86/ etc) are exempt from the bake's arch scan, and the kits' smoke-require declarations (punkluck86 Thread; punk91ix86 Thread iocp) probe resolution inside the built 32-bit artifacts - see goals/archive/G-133-bake-payload-consistency-checks.md.
- G-154 (achieved 2026-08-02, archived) produced win32-ix86 parser dlls from the tclparser_punk fork and runtime-verified them under this goal's verification kits (punkluck86 8.6.10 + punk91ix86 9.1b0, WoW64) - a first-party 32-bit package candidate for this lane's payload growth; see goals/archive/G-154-tclparser-punk-zig-build.md.
- 2026-08-02 CRT MEASURED (dumpbin /dependents import tables, recorded from the G-153 planning session; G-153 achieved 2026-08-02 - goals/archive/G-153-metakit-punk-zig-port.md) - the floor statement this goal's artifacts inherit. All zig-built suite binaries (tclsh9.0.5*.exe family, tclsh905.exe, suite_tcl86 tclsh86ts.exe / tclsh86t.exe / tcl86t.dll) link the UCRT dynamically (api-ms-win-crt--l1-1-0 forwarders) plus classic OS dlls only (KERNEL32/USER32/ADVAPI32/NETAPI32/USERENV/ WS2_32 - no api-ms-win-core- sets in the static imports); bin/punkzip.exe (pure zig) imports ntdll + kernel32 only, no CRT at all; the third-party prebuilts this goal replaces (tclkit86bi.exe, tclkit-win64-dyn.exe, tclsh8.6.10-luck-zip.exe) link msvcrt.dll (old-mingw flavor); tclsh9.1b0-tclsfe.exe links UCRT PLUS VCRUNTIME140 (MSVC build - needs the full VC++ redist, a heavier deployment story than ours). CONSEQUENCE: Windows 10+ runs suite artifacts with zero prerequisites (UCRT inbox); Windows 7 SP1 / 8.x need the UCRT update KB2999226 (broadly distributed via Windows Update since 2015; app-local UCRT deployment exists but clashes with single-file kits); XP and Windows 2000 are structurally unreachable - UCRT never existed there and zig's bundled mingw-w64 is UCRT-flavored only (the msvcrt CRT flavor is a mingw-w64 build-time choice, not a zig flag). The msvcrt-era "runs on anything since 1998" property of the old tclkits is NOT reproducible by this goal's artifacts - a recorded trade-off, not an omission. Runtime GetProcAddress-based API use is invisible to import tables, so the floor's acceptance proof remains booting the built shell on a real minimum-version machine or VM.
- 2026-08-02 Windows 2000 placement (user question) + the measured nuance: Win2k sits below the same UCRT wall as XP for suite builds, and Tcl 8.6's own documented floor is XP-era (8.4/8.5 were the last Win2k-supported lines; punk modules need 8.6+ regardless). BUT the luck 8.6.10 specimen's static import surface was measured Win2k-clean: every kernel32 import is NT4/2000-era (no AttachConsole / GetNativeSystemInfo / GetModuleHandleEx / AddVectoredExceptionHandler / SetDllDirectory), msvcrt usage is VC6-era (__wgetmainargs startup; no _aligned_malloc, no _strtoi64) - so any genuine Win2k need is served by hosted third-party/period artifacts through the G-123 tier (provenance sidecars, consent gate), never by a suite lane; punkshell reaches such machines remotely. Unverified on real metal (loader-level evidence only).
- 2026-08-02 CPU baseline rider: zig's 32-bit x86 baseline cpu model is pentium4, so SSE2 is assumed by default codegen - excluding Pentium III / Athlon XP class hardware even on OS versions the floor above covers. Proposed lane baseline: SSE2 (matches Windows 8+ hardware requirements and near-all surviving Win7 machines); going below (-Dcpu=pentium3, x87 float paths) is possible in zig but untested and only worth opening if pre-SSE2 retro hardware becomes a stated punkshell goal - same archival bucket as Win2k. Record the chosen baseline in the G-103 metadata / runtime toml alongside the target when artifacts land.
- 2026-08-02 lane-mechanics inventory (verified in-tree; complements the G-105 dependency): build86.zig already takes b.standardTargetOptions so the -Dtarget axis exists at the zig level; the gaps are suite.tcl -target passthrough with target-keyed staging/output prefixes, per-target expected_test_failures baselines (+ a first 32-bit census - WoW64 runs the gates natively on the x64 host, so post-tclsh phases including tcllib/tklib installers and critcl run UNDER the built 32-bit shell itself, no WSL analog needed), a win32-ix86-zig section in critcl_zig.config (compile/link -target x86-windows-gnu; the critcl PATH-probe trap is why the explicit section must exist), punkres PE32-vs-PE32+ stamping verification before 32-bit kits are stamped (G-128, achieved 2026-07-29 - see goals/archive/G-128-portable-pe-resource-stamping.md - measured x64 only), arch-scan target-awareness for the kit era (an x64 dll in an ix86 kit is the defect - the inversion of the known zint case), a punkbin win32-ix86 folder at first publish (same motion as the recorded linux-arm64 note in G-105), and twapi-for-x86 as the 9-line kit payload open item (the 8.6 runtime is twapi-less already; this goal's own acceptance uses the luck-shipped twapi 4.7.2 32-bit dll as the load target). First-exe firewall consent applies per new artifact path as usual. G-153 (achieved 2026-08-02 - goals/archive/G-153-metakit-punk-zig-port.md) baked the ix86 axis into the metakit_punk port from day one and DELIVERED it: dual-arch tests green natively via WoW64, mk4-format x64<->ix86 interchange verified both directions, the ix86 Mk4tcl dll smoke-passing under the luck 8.6.10 shell, and the static-embed shell measured import-identical to stock tclsh86ts (this goal's C++-embed/no-new-imports prediction upgraded to a direct measurement) - the 8.6 kit-side consumer of this goal's runtimes once G-101 decides the container.