From 81f69d913f91a2d6e92f311e411a1047650f4c18 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Sat, 25 Jul 2026 16:37:39 +1000 Subject: [PATCH] G-099 active: suite_tcl86 born on the G-104 contract - sources pinned, staging live, derivation started Activation gated on the G-112 rename core + G-104 contract (both achieved today); score re-run recorded. First increment: - suite_tcl86/: sources.config (source + self-description records - lists and describes itself via 'make.tcl buildsuite list/info' with no make.tcl edits), suite.tcl fork (folder-derived naming, {tcl tclthread tclvfs} requireds, build86.zig recipe file), build86.zig pending-derivation skeleton (staging succeeds, recipe fails with a clear message), build.zig.zon with real zig-fetch hashes, README with the DERIVATION record. - Thread 2.8 selection: thread-2-8-branch @ e14fa771ae (tagged thread-2-8-13, 2.8.13); configure.ac TCL_MAJOR_VERSION==8 guard confirms the pairing. - 8.6 source records in BOTH flows: dev refs (core-8-6-branch -> tcl86, thread-2-8-branch, tclvfs trunk 1.4.2-era) + zon per-checkin pins (tcl 1d1d5cbd91 = 8.6.18 era). - First staging run through 'make.tcl buildsuite build suite_tcl86' (a real driver run through the G-104 surface): checkouts staged from the shared hermetic store, TCL_PATCH_LEVEL 8.6.18 read from the tree. - makefile.vc derivation findings recorded incl. two Context corrections: 8.6.18 DOES generate tclUuid.h; zlib is prebuilt-import in stock nmake (zig-only recipe will compile compat/zlib statically). Core-test census + baseline deliberately pending until a built tclsh86 exists (recorded in Progress). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com --- GOALS.md | 2 +- goals/G-099-suite-tcl86-buildsuite.md | 51 +++- src/buildsuites/AGENTS.md | 3 + src/buildsuites/suite_tcl86/README.md | 101 +++++++ src/buildsuites/suite_tcl86/build.zig.zon | 42 +++ src/buildsuites/suite_tcl86/build86.zig | 20 ++ src/buildsuites/suite_tcl86/sources.config | 40 +++ src/buildsuites/suite_tcl86/suite.tcl | 324 +++++++++++++++++++++ 8 files changed, 581 insertions(+), 2 deletions(-) create mode 100644 src/buildsuites/suite_tcl86/README.md create mode 100644 src/buildsuites/suite_tcl86/build.zig.zon create mode 100644 src/buildsuites/suite_tcl86/build86.zig create mode 100644 src/buildsuites/suite_tcl86/sources.config create mode 100644 src/buildsuites/suite_tcl86/suite.tcl diff --git a/GOALS.md b/GOALS.md index b8307b0c..b12b948f 100644 --- a/GOALS.md +++ b/GOALS.md @@ -346,7 +346,7 @@ Detail: goals/G-089-scriptlib-kits-and-modes.md Scope: src/modules/shellfilter-999999.0a1.0.tm (stack placement, insert_transform, junctions); src/modules/shellthread-999999.0a1.0.tm (worker park/adoption/termination); src/tests/modules/ (new characterization suites); README.md ('very unripe parts' note) Detail: goals/G-090-shellfilter-shellthread-audit.md -### G-099 [proposed] suite_tcl86: zig buildsuite for core-8-6-branch (runtime, thread, tclvfs, core-test gate) +### G-099 [active] suite_tcl86: zig buildsuite for core-8-6-branch (runtime, thread, tclvfs, core-test gate) Scope: src/buildsuites/suite_tcl86/ (new: suite.tcl driver, 8.6 zig recipe + helper modules, expected_test_failures baseline); src/buildsuites/_build/ (untracked sources/outputs via existing globs); bin/tools/ (pinned zig as consumed); PUNK_FOSSIL_STORE / ~/.punkshell/fossils (hermetic clone store shared with suite_tcl90) Detail: goals/G-099-suite-tcl86-buildsuite.md diff --git a/goals/G-099-suite-tcl86-buildsuite.md b/goals/G-099-suite-tcl86-buildsuite.md index 15add7bd..617159f8 100644 --- a/goals/G-099-suite-tcl86-buildsuite.md +++ b/goals/G-099-suite-tcl86-buildsuite.md @@ -1,6 +1,6 @@ # G-099 suite_tcl86: zig buildsuite for core-8-6-branch (runtime, thread, tclvfs, core-test gate) -Status: proposed +Status: active Scope: src/buildsuites/suite_tcl86/ (new: suite.tcl driver, 8.6 zig recipe + helper modules, expected_test_failures baseline); src/buildsuites/_build/ (untracked sources/outputs via existing globs); bin/tools/ (pinned zig as consumed); PUNK_FOSSIL_STORE / ~/.punkshell/fossils (hermetic clone store shared with suite_tcl90) Goal: a tracked suite_tcl86 buildsuite builds a Tcl 8.6 windows runtime from fossil core-8-6-branch sources using the pinned zig toolchain only (zig-only build policy; msys/mingw and MS toolchains remain test/validation-only), together with the core binary companions punkshell's Tcl 8 targets need - an 8.6-compatible thread branch and tclvfs - and gates the result against the 8.6 core testsuite via parsed all.tcl totals against a tracked, dispositioned expected-failure baseline, mirroring the suite_tcl90 gate mechanism. Acceptance: from the pinned zig and fetched core-8-6-branch sources (hermetic clone store, no MS toolchain) the suite produces a working tclsh86 executable and tcl86 dll with an installed lib tree the shell resolves without external Tcl installations (TCLLIBPATH/TCL_LIBRARY unset in all suite child invocations); an 8.6-compatible thread package and tclvfs build and load in that shell (versions recorded); suite.tcl test runs the 8.6 core testsuite, parses totals (exit codes not trusted), and gates against a tracked expected_test_failures baseline with every entry dispositioned with a reason - a full-run PASS deterministic across two consecutive runs is recorded in this file; an interactive-smoke record (script execution, package require checks) is captured here. @@ -51,8 +51,57 @@ invocation): its natural slot was before or alongside this goal so suite_tcl86 is born onto the chosen driver shape rather than ported later. +## Progress + +- 2026-07-25 activation + first increment (suite born on the settled driver + shape, satisfying the G-104 contract by construction): + - suite_tcl86/ created: sources.config (source records + G-104 + description/product/doc/zigpin self-description records), suite.tcl + (forked from suite_tcl90 per the duplication-with-a-note posture; + log/fail prefix derives from the folder name, required sources + {tcl tclthread tclvfs}, recipe file build86.zig, build steps default + {install}), build86.zig (deliberate pending-derivation skeleton - staging + succeeds, the recipe fails with a clear G-099 message), build.zig.zon + (real content-hashed pins fetched with the pinned zig 0.16.0), README.md + (deliverables, selections, DERIVATION record). + - THREAD 2.8 SELECTION: thread-2-8-branch, tip checkin e14fa771ae tagged + thread-2-8-13 (2.8.13, 2026-04-30); the checkout's configure.ac guards + TCL_MAJOR_VERSION == 8 (pairing confirmed from source). Dev flow rides the + branch; the zon pins the 2-8-13 checkin. + - 8.6 SOURCE RECORDS IN BOTH FLOWS: sources.config refs + (tcl core-8-6-branch -> dir tcl86; tclthread thread-2-8-branch; tclvfs + trunk - 1.4.2 era per the recorded tcl9-only forTcl9 decision) and + build.zig.zon per-checkin pins (tcl 1d1d5cbd91 = 8.6.18 era, thread + e14fa771ae, tclvfs 9954261983) with zig-fetch hashes. + - FIRST STAGING RUN through the G-104 surface ('make.tcl buildsuite build + suite_tcl86'): checkouts staged from the shared hermetic clone store into + _build/suite_tcl86 (TCL_PATCH_LEVEL "8.6.18" read from the staged tree), + recipe fails at the skeleton as designed (exit status propagated through + the surface). 'buildsuite list/info' show the suite with its own records. + - RECIPE DERIVATION STARTED from the staged 8.6.18 win/makefile.vc - + findings recorded in suite_tcl86/README.md DERIVATION, including two + Context-assessment corrections: (a) 8.6.18 DOES generate tclUuid.h + (makefile.vc 797-802 - the "no tclUuid.h" note was outdated); (b) the + zlib arrangement is PREBUILT zdll.lib/zlib1.dll copies (not compiled) - + the zig-only recipe compiles compat/zlib statically instead (decision + recorded). TCLOBJS composition, in-tree libtommath, TCL_BROKEN_MAINARGS + in win/tclAppInit.c, dde 1.4.6 / registry 1.3.5 versions recorded. +- Remains for acceptance: author build86.zig (COREOBJS/PLATFORMOBJS + defines, + static zlib, tommath, manifest/rc step, entry-point handling), thread 2.8 + + tclvfs build wiring, install-tree layout + hermetic resolution proof, + suite.tcl test -> test-gate with parsed totals, FIRST CORE-TEST CENSUS and + the dispositioned expected_test_failures.txt baseline (file deliberately not + created until the census exists), two-consecutive-run deterministic PASS + record, interactive-smoke record. + ## Notes +- Activation freshness 2026-07-25: goals_xref.tcl score G-099 re-run at the + proposed->active flip (gate honoured: activated only after the G-112 rename + core and G-104 self-description contract landed - both achieved earlier + today). Top pairs G-100/G-105/G-101/G-116/G-108 all already linked or + recorded (G-108 via the archive re-bridge Related line below); remaining + unlinked hits are term noise - no new relationships. - 2026-07-21 (user): SEQUENCING CONFIRMED - G-097 (achieved 2026-07-21) then G-103 (achieved 2026-07-22 - see goals/archive/G-103-runtime-kit-family.md) precede this arc - BOTH LANDED, the arc is unblocked; the suite_tcl86 fork is taken after the kit-family assembly steps exist in suite_tcl90 so the 8.6 suite is born expressing family products (and G-101 inherits a concrete diff --git a/src/buildsuites/AGENTS.md b/src/buildsuites/AGENTS.md index e0bf5f64..5423959e 100644 --- a/src/buildsuites/AGENTS.md +++ b/src/buildsuites/AGENTS.md @@ -40,3 +40,6 @@ this project's `src/` tree. - `suite_tcl90/` - Tcl 9.0 suite (its README.md carries lineage/detail; no child AGENTS.md yet) +- `suite_tcl86/` - Tcl 8.6 suite, G-099 arc (recipe derivation in progress - + its README.md carries the deliverables, source selections and the + makefile.vc DERIVATION record; no child AGENTS.md yet) diff --git a/src/buildsuites/suite_tcl86/README.md b/src/buildsuites/suite_tcl86/README.md new file mode 100644 index 00000000..ba4bb7d8 --- /dev/null +++ b/src/buildsuites/suite_tcl86/README.md @@ -0,0 +1,101 @@ +# suite_tcl86 - zig buildsuite for Tcl core-8-6-branch (G-099) + +Builds a Tcl 8.6 windows runtime from fossil core-8-6-branch sources with the +pinned zig toolchain only (zig-only build policy; msys/mingw and MS toolchains +remain test/validation-only), together with the core binary companions +punkshell's Tcl 8 targets need - thread 2.8 and tclvfs - gated against the 8.6 +core testsuite. Forked from `suite_tcl90` (the shape reference); shared +scaffolding stays duplicated-with-a-note until this second consumer makes the +right factoring obvious (G-099 Context). + +STATUS: recipe derivation IN PROGRESS. `suite.tcl build` stages the source +checkouts (useful on its own - the derivation studies the staged +`tcl86/win/makefile.vc`) and then fails at the `build86.zig` skeleton with a +clear pending message. Progress ledger: `goals/G-099-suite-tcl86-buildsuite.md`. + +## Deliverables (per the G-099 acceptance) + +- `tclsh86.exe` + tcl86 dll + installed lib tree the shell resolves without + external Tcl installations (TCLLIBPATH/TCL_LIBRARY unset in all suite child + invocations). NO zipfs in 8.6 - no self-contained szip runtime is possible; + this suite delivers exe + dll + on-disk lib tree only (kit containment is + G-101 territory). +- thread (thread-2-8-branch) and tclvfs (trunk) built and loading in that shell. +- `suite.tcl test` runs the 8.6 core testsuite, parses totals (exit codes not + trusted), and gates against a tracked `expected_test_failures.txt` baseline - + the FIRST CENSUS is pending (the 9.0.5 census does not transfer; machine + traits dispositioned there will likely reappear under 8.6 test names). + +## Sources (both flows carry the same identity) + +- Dev flow: `sources.config` (live refs; `suite.tcl build` stages checkouts + from the hermetic clone store shared with suite_tcl90). +- No-tclsh flow: `build.zig.zon` (content-hashed per-checkin pins, recorded + from this suite's first commit; the bootstrap `build.zig` driver lands with + the recipe). + +Selections (2026-07-25, staged and verified): + +- tcl: `core-8-6-branch` - tip checkin 1d1d5cbd91 = **8.6.18** era + (TCL_PATCH_LEVEL "8.6.18" in the staged tree). +- thread: `thread-2-8-branch` - tip checkin e14fa771ae, tagged + **thread-2-8-13** (2.8.13, 2026-04-30). 8.6 pairs with the 2.8 line; the + checkout's configure.ac guards `TCL_MAJOR_VERSION == 8` (trunk/3.x targets + Tcl 9). Thread ships TEA + `win/makefile.vc` build surfaces. +- tclvfs: `trunk` - tip checkin 9954261983 (1.4.2 era). The `forTcl9` branch + (1.5.0) is tcl9-only (user decision 2026-07-22, recorded in suite_tcl90's + sources.config). + +## DERIVATION (build86.zig from the staged 8.6.18 win/makefile.vc) + +Recorded findings from the staged tree (assess-not-assume items from the G-099 +Context, verified 2026-07-25): + +- `TCLOBJS = COREOBJS + ZLIBOBJS + TOMMATHOBJS + PLATFORMOBJS` + (makefile.vc:218/323/390/412) - the object inventory the recipe expresses. +- **zlib divergence (key)**: 8.6's makefile.vc does NOT compile zlib - it + copies PREBUILT `compat/zlib/win{32,win64,win64-arm}/zdll.lib` + `zlib1.dll` + (makefile.vc:548-559) and links the import lib (`ZLIBOBJS = zdll.lib`). The + zig-only build compiles `compat/zlib` sources instead (suite_tcl90's + build_zlib helper pattern) - decision: compile zlib STATICALLY into the tcl86 + dll, eliminating the shipped `zlib1.dll` (record the deviation from stock + layout in the recipe; stock nmake builds ship zlib1.dll beside the dll). +- libtommath: in-tree at `$(ROOT)/libtommath` with `TOMMATHOBJS` compiled into + the core (same in-core model as 9.0; tree paths/versions differ - + build_libtommath helper reusable with dir adjustments). +- `tclUuid.h`: 8.6.18 DOES generate it (makefile.vc:797-802, + `manifest.uuid` -> `tclUuid.h` via tclUuid.h.in) - the G-099 Context's + "no tclUuid.h" assessment was outdated; the 9.0 recipe's generation step + carries over with the 8.6 input paths. +- Entry points: `TCL_BROKEN_MAINARGS` handling lives in `win/tclAppInit.c` + (8 occurrences; generic/tclMain.c has none) - the mingw-class argv handling + for zig cc lands there, distinct from the 9.0.5 mingw-unicode-entry work. +- Bundled extensions built by makefile.vc: `dde 1.4.6`, `registry 1.3.5` + (dlls or static per OPTS; the 9.1-era statics probe showed Dde 1.5b0 - the + 8.6 line is older). Decide inclusion when the recipe lands (punk86-class + kits historically carry them). +- No `generic/tclZipfs.c` (confirmed): no zipfs, no script-library zip + embedding - the install step lays the `library/` tree on disk + (`lib/tcl8.6/...`), and `init.tcl` resolution rides `TCL_LIBRARY`-free + relative discovery from the exe path. +- rules.vc/makefile.vc are the config authority (1066 + 1883 lines staged); + versions derive from `library/init.tcl` + `generic/tcl.h` + (TCL_PATCH_LEVEL "8.6.18") - version-derived output names (tcl86t.dll + naming class, tclsh86 vs tclsh8.6 spellings) settle with the recipe. + +Remaining derivation work (tracked in G-099 Progress): express COREOBJS/ +PLATFORMOBJS source lists + defines in build86.zig (build905.zig + +build_common.zig as the shape reference), decide static-vs-dll core linkage +for the punk86-class consumers, port the manifest/rc resource step, wire +thread 2.8 + tclvfs builds (TEA-style configure products generated +recipe-side as in 9.0), then the core-test gate + first census. + +## Flows + +- FOSSIL DEV FLOW: `tclsh suite.tcl build|test|clean` (or via the make.tcl + surface: `tclsh src/make.tcl buildsuite build suite_tcl86 ?driver-args?`). +- NO-TCLSH FLOW: `zig build stage|bootstrap` - lands with the recipe; + `build.zig.zon` pins are already recorded. + +The suite self-description contract (records in `sources.config` read by +`make.tcl buildsuite list/info`) is documented in `src/buildsuites/README.md`. diff --git a/src/buildsuites/suite_tcl86/build.zig.zon b/src/buildsuites/suite_tcl86/build.zig.zon new file mode 100644 index 00000000..483263e2 --- /dev/null +++ b/src/buildsuites/suite_tcl86/build.zig.zon @@ -0,0 +1,42 @@ +//build.zig.zon - suite_tcl86 pinned source manifest (G-099). +// +//The CONTENT-HASHED tweak surface for the no-tclsh bootstrap flow (G-102 shape - +//see suite_tcl90/build.zig.zon for the mechanism documentation: per-checkin +//tarball urls + zig package hashes; 'zig fetch ' prints a hash, branch-tip +//urls are deliberately NOT used - the pin IS the provenance record). +// +//The bootstrap build.zig driver lands with the recipe (build86.zig is a +//pending-derivation skeleton); these records pin the 8.6 sources from the +//suite's FIRST COMMIT so both flows carry the same source identity +//(sources.config = live dev-flow refs on the same repositories/branches). +//Hashes below were computed with the pinned zig 0.16.0 ('zig fetch') on +//2026-07-25. +.{ + .name = .suite_tcl86, + .version = "0.0.1", + .fingerprint = 0x9fe14fa771ae8617, + .minimum_zig_version = "0.16.0", + .dependencies = .{ + //tcl core-8-6-branch checkout 1d1d5cbd91 2026-07-14 (8.6.17+ maintenance era) + .tcl = .{ + .url = "https://core.tcl-lang.org/tcl/tarball/1d1d5cbd91ebdb4a91246e9d63b8763622179c2d0d744a7e75d7d6580a70514a/tcl.tar.gz", + .hash = "N-V-__8AAA0mDwKkYPpxjZfpjor-2EFvJY-hcGnmmhaPDwbM", + .lazy = true, + }, + //thread thread-2-8-branch checkout e14fa771ae 2026-04-30 (tagged thread-2-8-13; 2.8.13 - + //the 8.6-compatible thread line; trunk/3.x targets Tcl 9. Selection: goals G-099) + .tclthread = .{ + .url = "https://core.tcl-lang.org/thread/tarball/e14fa771ae2e4bdca37a3afb4d4fe65b30fb41e544fec6104b070a47929a5310/thread.tar.gz", + .hash = "N-V-__8AAHbmFACk7qBbJWoGQonF60vKEbOCuMbsEXkJN2lf", + .lazy = true, + }, + //tclvfs trunk checkout 9954261983 2020-02-25 (1.4.2 era - 8.6 suites keep trunk; + //the forTcl9 branch (1.5.0) is tcl9-only, user decision 2026-07-22) + .tclvfs = .{ + .url = "https://core.tcl-lang.org/tclvfs/tarball/995426198338747be626b38cb267eb3dd81fc4258c59e64aec6b91376a26935d/tclvfs.tar.gz", + .hash = "N-V-__8AAIaeDQBJ9V3M96hpQSxemxghwLBG8fB1s0rqh4SQ", + .lazy = true, + }, + }, + .paths = .{""}, +} diff --git a/src/buildsuites/suite_tcl86/build86.zig b/src/buildsuites/suite_tcl86/build86.zig new file mode 100644 index 00000000..b6a6c4b4 --- /dev/null +++ b/src/buildsuites/suite_tcl86/build86.zig @@ -0,0 +1,20 @@ +//build86.zig - suite_tcl86 zig recipe (G-099) - DERIVATION IN PROGRESS. +// +//This is a deliberate pending-state skeleton: 'suite.tcl build' stages the +//core-8-6-branch / thread-2-8-branch / tclvfs-trunk sources (useful on its own - +//the checkout carries win/makefile.vc, the derivation source of truth) and then +//fails HERE with a clear message instead of pretending to build. +// +//Derivation record (what this recipe must express, from 8.6's win/makefile.vc): +//see README.md section DERIVATION. The 9.0.5 recipe (suite_tcl90/build905.zig + +//build_common.zig + build_zlib/build_libtommath/build_tclvfs/build_tclthread +//helper modules) is the shape reference; the G-099 Context records the known +//8.6 differences to verify rather than assume (bundled zlib/libtommath +//arrangements, no tclUuid.h, makefile.vc-derived manifest/rc generation, +//TCL_BROKEN_MAINARGS-era entry points, no zipfs). +const std = @import("std"); + +pub fn build(b: *std.Build) void { + _ = b; + @compileError("suite_tcl86 recipe derivation in progress (G-099) - sources are staged; see suite_tcl86/README.md DERIVATION for the makefile.vc-derived plan and goals/G-099-suite-tcl86-buildsuite.md for progress"); +} diff --git a/src/buildsuites/suite_tcl86/sources.config b/src/buildsuites/suite_tcl86/sources.config new file mode 100644 index 00000000..5fd461cb --- /dev/null +++ b/src/buildsuites/suite_tcl86/sources.config @@ -0,0 +1,40 @@ +# sources.config - suite_tcl86 source-pull declarations for the FOSSIL DEV FLOW +# (live checkouts driven by suite.tcl). This is the tweak surface for retargeting +# that flow at different repositories/branches/tags. Forked from suite_tcl90 +# (G-099); build.zig.zon is the equivalent PINNED surface for the no-tclsh flow +# (records present from this suite's first commit - the bootstrap build.zig +# driver lands with the recipe). +# +# Read by suite.tcl as plain line records - the file is parsed, never executed. +# Record grammar (whitespace separated, one record per line, # comments and +# blanks ignored) - the G-104 self-description contract is documented in +# src/buildsuites/README.md: +# +# source +# description one line - the list/info one-liner for this suite +# product repeatable - what a full build produces +# doc repeatable - suite-relative doc pointers +# zigpin projectroot-relative pinned zig executable +# +# dir names are RECIPE-COUPLED: build86.zig references them by relative path +# (e.g "../tcl86") - keep dir names unless you also adjust the recipe. +# +# 8.6-arc notes (G-099): +# - tcl rides core-8-6-branch (the live 8.6 maintenance line; 8.6.17+ era). +# Override per-run with 'suite.tcl build -tclbranch '. +# - thread rides thread-2-8-branch: 8.6 pairs with thread 2.8 (trunk/3.x +# targets Tcl 9). Branch tip is the thread-2-8-13-tagged checkin +# (2.8.13, 2026-04-30) - selection recorded in goals G-099. +# - tclvfs keeps TRUNK (1.4.2 era): the forTcl9 branch (1.5.0) is for tcl9 +# suites only (user decision 2026-07-22, recorded in suite_tcl90). + +description Zig-built Tcl 8.6 windows runtime (core-8-6-branch): tclsh86 + tcl86 dll + installed lib tree, thread 2.8 + tclvfs, core-test gate (G-099 arc - recipe derivation in progress) +product tclsh86 executable + tcl86 dll with installed lib tree (no zipfs in 8.6 - no self-contained szip runtime; kit containment is G-101 territory) +product 8.6-compatible thread (thread-2-8-branch, 2.8.13 era) and tclvfs (trunk, 1.4.2 era) built and loadable in that shell +product core testsuite gate vs a tracked expected_test_failures baseline (parsed all.tcl totals; first census pending - see README) +doc README.md +zigpin bin/tools/zig-x86_64-windows-0.16.0/zig.exe + +source tcl fossil https://core.tcl-lang.org/tcl core-8-6-branch tcl86 +source tclthread fossil https://core.tcl-lang.org/thread thread-2-8-branch tclthread +source tclvfs fossil https://core.tcl-lang.org/tclvfs trunk tclvfs diff --git a/src/buildsuites/suite_tcl86/suite.tcl b/src/buildsuites/suite_tcl86/suite.tcl new file mode 100644 index 00000000..5c94e8c3 --- /dev/null +++ b/src/buildsuites/suite_tcl86/suite.tcl @@ -0,0 +1,324 @@ +#!/usr/bin/env tclsh +#suite_tcl86 dev driver (G-099) - forked from suite_tcl90 (G-096/G-102 shape; +#duplication-with-a-note is the recorded starting posture - shared scaffolding is +#factored out only when this second consumer makes the right shape obvious). +#Stages the tracked zig recipe into ../_build/suite_tcl86, arranges sources from +#LIVE fossil checkouts, and delegates the build/test pipeline to the staged zig +#recipe's steps. +# +#RECIPE STATUS (G-099): build86.zig is a pending-derivation skeleton - it fails +#with a clear message after source staging succeeds. Staging alone is useful: it +#materializes the core-8-6-branch checkout (win/makefile.vc etc) the derivation +#studies. See README.md DERIVATION. +# +#This is the FOSSIL DEV FLOW - convenient live-branch work against checkouts. The +#equivalent no-tclsh flow ('zig build stage|bootstrap' fetching the build.zig.zon +#pins) lands with the recipe; the zon pins are recorded from this suite's first +#commit. +# +#Usage: tclsh suite.tcl build ?options? +# tclsh suite.tcl test ?-testargs {tcltest args}? +# tclsh suite.tcl clean +#Options: +# -zig zig executable (default: $env(PUNK_ZIG), else the sources.config +# zigpin, else 'zig' on PATH) +# -optimize Debug|ReleaseSafe|ReleaseFast|ReleaseSmall (default ReleaseFast) +# -tclbranch override the 'tcl' ref from sources.config for this run +# (default: core-8-6-branch) +# -refresh <0|1> pull clones + fossil update existing source checkouts (default 0) +# -repofolder fossil clone store (default ~/.punkshell/fossils; env PUNK_FOSSIL_STORE) +# -seedfossils read-only seed collection for missing clones (default ~/.fossils; "" disables) +# -all <0|1> with 'clean': reserved (the clone store lives outside the stage) +# -steps zig build steps. 'build' default: {install} (grows with the +# recipe: thread/tclvfs installs, smoke, per G-099). +# 'test' default: {test-gate} (the 8.6 core suite gate vs the +# tracked expected_test_failures baseline - pending first census). +# -zigargs extra args appended to the zig build invocation +# +#The build area lives entirely under src/buildsuites/_build (VCS-ignored). Fossil +#clones live in the punkshell-owned machine-level store ~/.punkshell/fossils +#(shared with suite_tcl90 - tcl/tclthread/tclvfs clone names are common). +#Checkouts use FOSSIL_HOME= so the user's global fossil config db records +#nothing. 'clean' wipes the stage; the store lives outside it. + +set suiteroot [file dirname [file normalize [info script]]] +set suitename [file tail $suiteroot] +#stage derived from the suite FOLDER name so a copied tree (copy-and-tweak workflow, +#see sources.config) stages into its own _build/ - copies stay isolated. +set stage [file normalize [file join $suiteroot .. _build $suitename]] +set builddir [file join $stage build] + +proc log {msg} {puts stdout "$::suitename: $msg"; flush stdout} +proc fail {msg} {puts stderr "$::suitename ERROR: $msg"; flush stderr; exit 1} + +proc run {args} { + #stream output; abort on nonzero exit + log "run: $args" + if {[catch {exec {*}$args >@stdout 2>@stderr} err opts]} { + set code [dict get $opts -errorcode] + if {[lindex $code 0] eq "CHILDSTATUS"} { + fail "command failed (exit [lindex $code 2]): $args" + } + fail "command failed: $args\n$err" + } +} + +#-- sources.config load --------------------------------------------------- +#Declared in sources.config (the copy-and-tweak surface for the LIVE-checkout dev +#flow - see its header; build.zig.zon is the equivalent PINNED surface for the +#no-tclsh flow). Parsed as line records - never executed. +#Record grammar incl. the G-104 self-description records: see +#src/buildsuites/README.md ('make.tcl buildsuite list/info' reads the same records). +proc load_sources_config {path} { + set config [dict create sources [dict create] description "" products [list] docs [list] zigpin ""] + set f [open $path r]; set data [read $f]; close $f + set ln 0 + foreach line [split $data \n] { + incr ln + set line [string trim $line] + if {$line eq "" || [string index $line 0] eq "#"} {continue} + if {[catch {llength $line} len]} { + fail "sources.config line $ln: not a well-formed record: $line" + } + switch -- [lindex $line 0] { + source { + if {$len != 6} { + fail "sources.config line $ln: expected 'source ' - got: $line" + } + lassign $line -> name kind url ref dir + if {$kind ni {fossil git}} { + fail "sources.config line $ln: unknown kind '$kind' (expected fossil|git)" + } + dict set config sources $name [dict create kind $kind url $url ref $ref dir $dir] + } + description { + dict set config description [join [lrange $line 1 end] " "] + } + product { + dict lappend config products [join [lrange $line 1 end] " "] + } + doc { + dict lappend config docs [lindex $line 1] + } + zigpin { + dict set config zigpin [lindex $line 1] + } + default { + fail "sources.config line $ln: unknown record type '[lindex $line 0]' (expected source|description|product|doc|zigpin)" + } + } + } + return $config +} +set suiteconfig [load_sources_config [file join $suiteroot sources.config]] +set sources [dict get $suiteconfig sources] + +#-- options --------------------------------------------------------------- +set action [lindex $argv 0] +if {$action ni {build test clean}} { + puts stderr "usage: tclsh suite.tcl build|test|clean ?options? (see header)" + exit 2 +} +array set opt { + -optimize ReleaseFast + -tclbranch {} + -refresh 0 + -steps {install} + -testargs {} + -zigargs {} + -repofolder {} + -all 0 +} +set explicitopts {} +set opt(-seedfossils) [file normalize [file join $env(HOME) .fossils]] +#zig resolution: -zig option > PUNK_ZIG env > the sources.config zigpin record +#(projectroot-relative; single source of truth shared with 'make.tcl buildsuite +#info') > 'zig' on PATH. The recipe targets the pinned zig 0.16 API (as +#suite_tcl90 - see its README Lineage). +if {[dict get $suiteconfig zigpin] ne ""} { + set pinned_zig [file normalize [file join $suiteroot .. .. .. [dict get $suiteconfig zigpin]]] +} else { + set pinned_zig [file normalize [file join $suiteroot .. .. .. bin tools zig-x86_64-windows-0.16.0 zig.exe]] +} +if {[info exists env(PUNK_ZIG)]} { + set opt(-zig) $env(PUNK_ZIG) +} elseif {[file exists $pinned_zig]} { + set opt(-zig) $pinned_zig +} else { + set opt(-zig) "zig" +} +foreach {k v} [lrange $argv 1 end] { + if {![info exists opt($k)]} {fail "unknown option '$k'"} + set opt($k) $v + lappend explicitopts $k +} + +#suite-owned clone store resolution: -repofolder > PUNK_FOSSIL_STORE > ~/.punkshell/fossils +#(shared with suite_tcl90 - see its suite.tcl for the rationale record) +if {$opt(-repofolder) ne ""} { + set fossildir [file normalize $opt(-repofolder)] +} elseif {[info exists env(PUNK_FOSSIL_STORE)] && $env(PUNK_FOSSIL_STORE) ne ""} { + set fossildir [file normalize $env(PUNK_FOSSIL_STORE)] +} else { + if {[info exists env(HOME)] && $env(HOME) ne ""} { + set homedir $env(HOME) + } elseif {[info exists env(USERPROFILE)] && $env(USERPROFILE) ne ""} { + set homedir $env(USERPROFILE) + } elseif {![catch {file home} h]} { + set homedir $h + } else { + fail "cannot determine home directory for the default fossil store (set PUNK_FOSSIL_STORE or -repofolder)" + } + set fossildir [file join [file normalize $homedir] .punkshell fossils] +} + +#Hermetic child shells: the suite-built tclsh must not see the user's machine-level +#package paths (TCLLIBPATH/TCL_LIBRARY misdirect installer paths and risk +#false-positive smokes). The zig recipe additionally scrubs these per built-shell +#Run step (suite_tcl90 G-102 convention, kept for the 8.6 recipe). +foreach ev {TCLLIBPATH TCL_LIBRARY TK_LIBRARY} { + if {[info exists env($ev)]} { + log "unsetting inherited \$env($ev) for hermetic child shells" + unset env($ev) + } +} + +proc run_zig_steps {steps {extraopts {}}} { + #drive the STAGED recipe (cwd = staged build dir, per-zig-version cache, + #forward-slash prefix - suite_tcl90 parity) + global opt builddir stage + if {![file exists [file join $builddir build86.zig]]} { + fail "no staged recipe at $builddir - run 'suite.tcl build' first" + } + set zigv [exec $opt(-zig) version] + log "zig: $opt(-zig) ($zigv)" + #Per-zig-version local cache: object caches must never be shared across zig + #versions (suite_tcl90-observed stale/duplicate artifacts in the link). + set cachedir ".zig-cache-[string map {+ _ / _ : _} $zigv]" + set savedpwd [pwd] + cd $builddir + run $opt(-zig) build --build-file build86.zig --cache-dir $cachedir --prefix [file join $stage out] -Doptimize=$opt(-optimize) {*}$extraopts {*}$steps + cd $savedpwd +} + +if {$action eq "clean"} { + log "removing $stage (the clone store at $fossildir is untouched)" + file delete -force $stage + exit 0 +} + +if {$action eq "test"} { + #Delegates to the recipe's test steps. Default step: test-gate (8.6 core + #testsuite gated on parsed totals vs the tracked expected_test_failures + #baseline - pending the first census; the 9.0.5 census does not transfer). + #-j1: independent zig steps must not run timing-sensitive suites in parallel. + set extraopts {-j1} + if {[llength $opt(-testargs)]} { + lappend extraopts -Dtestargs=$opt(-testargs) + } + lappend extraopts {*}$opt(-zigargs) + set teststeps [expr {"-steps" in $explicitopts ? $opt(-steps) : {test-gate}}] + run_zig_steps $teststeps $extraopts + log "test steps done ([join $teststeps {, }])" + exit 0 +} + +#-- action: build ---------------------------------------------------------- + +#-- fossil environment ---------------------------------------------------- +#Checkout registrations go to a stage-local config db, not the user's global one +#(fossil scratchpad registry pollution guard). Clones are still shared. +file mkdir $stage +set env(FOSSIL_HOME) $stage +file mkdir $fossildir + +proc fossil_source {name url branch dir} { + #ensure /.fossil exists (read-only seed copy, else network clone) and + #open it at branch in dir + global fossildir opt + set repo [file join $fossildir $name.fossil] + if {![file exists $repo]} { + set seeded 0 + if {$opt(-seedfossils) ne ""} { + set seed [file join $opt(-seedfossils) $name.fossil] + if {[file exists $seed]} { + log "seeding $name.fossil into the suite store from $seed (read-only copy)" + file copy $seed $repo + #the seed may be stale - freshen OUR copy (the seed is never written) + run fossil pull -R $repo + set seeded 1 + } + } + if {!$seeded} { + log "cloning $url -> $repo" + run fossil clone $url $repo + } + } elseif {$opt(-refresh)} { + log "refreshing $name.fossil (pull)" + run fossil pull -R $repo + } + if {![file exists [file join $dir _FOSSIL_]] && ![file exists [file join $dir .fslckout]]} { + file mkdir $dir + set savedpwd [pwd] + cd $dir + #--nested: the stage lives inside the punkshell checkout tree + run fossil open $repo $branch --nested + cd $savedpwd + } elseif {$opt(-refresh)} { + set savedpwd [pwd] + cd $dir + run fossil pull -R $repo + run fossil update $branch + cd $savedpwd + } + #provenance: materialize manifest.uuid regardless of the upstream repo's + #versioned 'manifest' setting (suite_tcl90 convention - local checkout-scoped + #setting 'u' generates manifest.uuid immediately and keeps it current). + set savedpwd [pwd] + cd $dir + run fossil settings manifest u + cd $savedpwd +} + +#-- stage the recipe ------------------------------------------------------ +#Per-item sync (not a wholesale delete of the build dir): zig cache dirs live in +#the build dir and are kept (per-zig-version; windows can hold transient locks on +#recently-used cache trees). +log "staging recipe -> $builddir" +file mkdir $builddir +foreach item {build86.zig} { + file delete -force [file join $builddir $item] + file copy [file join $suiteroot $item] $builddir +} + +#-- sources --------------------------------------------------------------- +foreach required {tcl tclthread tclvfs} { + if {![dict exists $sources $required]} { + fail "sources.config: missing required source record '$required'" + } +} + +dict for {name s} $sources { + set ref [dict get $s ref] + if {$name eq "tcl" && $opt(-tclbranch) ne ""} { + set ref $opt(-tclbranch) ;#per-run CLI override of the declared tcl ref + } + switch -- [dict get $s kind] { + fossil {fossil_source $name [dict get $s url] $ref [file join $stage [dict get $s dir]]} + } +} + +#zlib/libtommath: 8.6 compiles the tcl tree's own vendored copies in place +#(tcl86/compat/zlib, tcl86/libtommath) - arrangement differs from 9.0 (see README +#DERIVATION); nothing extra to stage. + +#-- version facts for the final log ---------------------------------------- +set f [open [file join $stage tcl86 manifest.uuid] r]; set uuid [read $f]; close $f +set f [open [file join $stage tcl86 generic tcl.h] r]; set tclh [read $f]; close $f +if {![regexp {#\s*define\s+TCL_PATCH_LEVEL\s+"([^"]+)"} $tclh -> patchlevel]} {fail "TCL_PATCH_LEVEL not found in tcl.h"} +log "sources: tcl $patchlevel (checkout [string range $uuid 0 11]...)" + +#-- build (staged recipe steps) ------------------------------------------- +run_zig_steps $opt(-steps) $opt(-zigargs) + +log "PASS - built $patchlevel (checkout [string range $uuid 0 11]...) -> $stage/out"