Compare commits
2 Commits
a20a64a2a1
...
f4031b209f
| Author | SHA1 | Date |
|---|---|---|
|
|
f4031b209f | 1 week ago |
|
|
f89bd58c31 | 1 week ago |
26 changed files with 2191 additions and 136 deletions
@ -1,57 +0,0 @@
|
||||
# G-100 suite_tcl86 dependency set: Tk 8.6 + tklib, tcllib with critcl accelerators, punkshell runtests on the 8.6 runtime |
||||
|
||||
Status: proposed |
||||
Scope: src/buildsuites/suite_tcl86/ (recipe extensions, driver steps); src/buildsuites/_build/ (tk/tklib/tcllib/critcl sources and outputs); bin/tools/ (pinned zig as consumed); src/tests/ (punkshell suites exercised against the suite-built 8.6 runtime) |
||||
Goal: suite_tcl86 builds/installs the remaining runtime pieces punkshell's Tcl 8 testing depends on - Tk from fossil core-8-6-branch loadable by the suite's 8.6 windows runtime together with a matching tklib (installer.tcl where it does more than a straight copy), and tcllib installed via its documented installer machinery WITH its critcl-built C accelerators (tcllibc; critcl driving zig cc, bootstrapped by the suite-built tclsh86 - no MS toolchain) - and punkshell's own runtests runs against the suite-built 8.6 runtime with Tk-dependent suites unskipped. |
||||
Acceptance: from the pinned zig and fetched sources the suite produces a Tk 8.6 the suite tclsh loads (package require Tk with a create/destroy-window verification recorded here) and a matching tklib whose packages resolve (a representative require recorded); a tcllib install via its installer whose accelerators load (package require tcllibc) with the accelerated-vs-pure comparison recorded; punkshell runtests runs against the suite 8.6 runtime and its census is recorded here against a same-day native/kit 8.6 baseline run (same include set), with every difference dispositioned - Tk-dependent suites run unskipped, and any 8.6-runtime-only failures are root-caused or baselined with reasons. |
||||
|
||||
## Context |
||||
|
||||
Mirror of G-098 (suite_tcl90 dependency set, achieved 2026-07-20) for the 8.6 arc. |
||||
Depends on G-099 (suite_tcl86 core buildsuite) - ACHIEVED 2026-07-26 (see |
||||
goals/archive/G-099-suite-tcl86-buildsuite.md); the 8.6 runtime (tclsh86ts/ |
||||
tclsh86t + tcl86t.dll + installed lib tree), thread 2.8.13, tclvfs 1.4.2 and |
||||
the core/thread/tclvfs test-gate this goal extends now exist, so the dependency |
||||
is met and G-100 is unblocked. |
||||
|
||||
8.6-specific expectations (verify at activation): |
||||
|
||||
- Tk core-8-6-branch pairs with the 8.6 runtime; the 9.0 build_tk zig module was |
||||
derived from tk9 makefile.vc object lists - the 8.6 lists/xlib arrangement differ, |
||||
so expect a re-derivation rather than reuse. |
||||
- tcllib trunk supports 8.5+; the same vendored critcl mechanism applies, with |
||||
critcl driven by the suite tclsh86. tcllibc built per-generation (the punk9wintk903 |
||||
vfs precedent carries tcl8/tcl9 tcllibc side by side under lib_tcl8/lib_tcl9). |
||||
- runtests under 8.6: no tcl::process, so -jobs child spawning falls back to |
||||
blocking execs which CONVOY on windows (documented) - run -singleproc 1 or accept |
||||
serialized child walls for the census run; record which mode produced the census. |
||||
- Census baseline: compare against the punk86-class kit runtime results on the same |
||||
day/include-set (forward-slash path conventions on 8.6 kits noted in project |
||||
memory) rather than against the 9.x census. |
||||
- The kit-child 'src' package_mode launch added to runtests for punk kits (G-098 |
||||
increment 7) applies to 8.6 punk kits too - a plain suite tclsh86 host takes the |
||||
native path. |
||||
|
||||
SEQUENCING: as for G-099 - proposed now, activation recommended after suite_tcl90's |
||||
G-096 (achieved 2026-07-20) remainder closed and punk905_beta trial concludes. |
||||
|
||||
## Notes |
||||
|
||||
- G-116 relationship (recorded 2026-07-24 after overlap review): G-116's zig-built |
||||
crypto-backend + static tcltls pattern (suite_tcl90) is the reference if the 8.6 |
||||
dependency set later grows a tls battery - the bi-family payload contract it |
||||
extends is generation-shaped, not 9-only. |
||||
- G-005 relationship: same zig toolchain-policy lineage as G-099's note - G-005 |
||||
owns the make.tcl-integrated vendored-extension build direction; the suites are |
||||
its arm's-length proving ground. |
||||
- G-099 (achieved, see goals/archive/G-099-suite-tcl86-buildsuite.md) delivered |
||||
the patterns this goal extends: the build86.zig recipe + build_tclthread86/ |
||||
build_tclvfs86 helpers (TEA-shape companion builds against the 8.6 stub lib), |
||||
the whole-tree library install + tm-module derivation, and the suite_tcl90 |
||||
G-107 (achieved - goals/archive/G-107-buildsuite-library-tests.md) policy-tier |
||||
test-gate (test_gate.tcl) - a Tk/tklib/tcllib gate follows the same shape. Two 8.6-specific traps recorded there carry forward: the |
||||
load-bearing MP_FIXED_CUTOFFS define and TCL_BROKEN_MAINARGS+console-subsystem |
||||
entry handling (build86.zig comments + README DERIVATION). Also inherited from |
||||
G-099 Notes: the G-106 powershell console-mode disableraw-via-server path is |
||||
only tcl9-verified - now that a twapi-less 8.6 runtime exists, run the G-106 |
||||
recipe against it (goals/archive/G-106-powershell-consolemode-fallback.md). |
||||
@ -0,0 +1,210 @@
|
||||
# G-100 suite_tcl86 dependency set: Tk 8.6 + tklib, tcllib with critcl accelerators, punkshell runtests on the 8.6 runtime |
||||
|
||||
Status: achieved 2026-07-26 |
||||
Scope: src/buildsuites/suite_tcl86/ (recipe extensions, driver steps); src/buildsuites/_build/ (tk/tklib/tcllib/critcl sources and outputs); bin/tools/ (pinned zig as consumed); src/tests/ (punkshell suites exercised against the suite-built 8.6 runtime) |
||||
Goal: suite_tcl86 builds/installs the remaining runtime pieces punkshell's Tcl 8 testing depends on - Tk from fossil core-8-6-branch loadable by the suite's 8.6 windows runtime together with a matching tklib (installer.tcl where it does more than a straight copy), and tcllib installed via its documented installer machinery WITH its critcl-built C accelerators (tcllibc; critcl driving zig cc, bootstrapped by the suite-built tclsh86 - no MS toolchain) - and punkshell's own runtests runs against the suite-built 8.6 runtime with Tk-dependent suites unskipped. |
||||
Acceptance: from the pinned zig and fetched sources the suite produces a Tk 8.6 the suite tclsh loads (package require Tk with a create/destroy-window verification recorded here) and a matching tklib whose packages resolve (a representative require recorded); a tcllib install via its installer whose accelerators load (package require tcllibc) with the accelerated-vs-pure comparison recorded; punkshell runtests runs against the suite 8.6 runtime and its census is recorded here against a same-day native/kit 8.6 baseline run (same include set), with every difference dispositioned - Tk-dependent suites run unskipped, and any 8.6-runtime-only failures are root-caused or baselined with reasons. |
||||
|
||||
## Context |
||||
|
||||
Mirror of G-098 (suite_tcl90 dependency set, achieved 2026-07-20) for the 8.6 arc. |
||||
Depends on G-099 (suite_tcl86 core buildsuite) - ACHIEVED 2026-07-26 (see |
||||
goals/archive/G-099-suite-tcl86-buildsuite.md); the 8.6 runtime (tclsh86ts/ |
||||
tclsh86t + tcl86t.dll + installed lib tree), thread 2.8.13, tclvfs 1.4.2 and |
||||
the core/thread/tclvfs test-gate this goal extends now exist, so the dependency |
||||
is met and G-100 is unblocked. |
||||
|
||||
8.6-specific expectations (verify at activation): |
||||
|
||||
- Tk core-8-6-branch pairs with the 8.6 runtime; the 9.0 build_tk zig module was |
||||
derived from tk9 makefile.vc object lists - the 8.6 lists/xlib arrangement differ, |
||||
so expect a re-derivation rather than reuse. |
||||
- tcllib trunk supports 8.5+; the same vendored critcl mechanism applies, with |
||||
critcl driven by the suite tclsh86. tcllibc built per-generation (the punk9wintk903 |
||||
vfs precedent carries tcl8/tcl9 tcllibc side by side under lib_tcl8/lib_tcl9). |
||||
- runtests under 8.6: no tcl::process, so -jobs child spawning falls back to |
||||
blocking execs which CONVOY on windows (documented) - run -singleproc 1 or accept |
||||
serialized child walls for the census run; record which mode produced the census. |
||||
- Census baseline: compare against the punk86-class kit runtime results on the same |
||||
day/include-set (forward-slash path conventions on 8.6 kits noted in project |
||||
memory) rather than against the 9.x census. |
||||
- The kit-child 'src' package_mode launch added to runtests for punk kits (G-098 |
||||
increment 7) applies to 8.6 punk kits too - a plain suite tclsh86 host takes the |
||||
native path. |
||||
|
||||
SEQUENCING: as for G-099 - proposed now, activation recommended after suite_tcl90's |
||||
G-096 (achieved 2026-07-20) remainder closed and punk905_beta trial concludes. |
||||
|
||||
## Progress |
||||
|
||||
### 2026-07-26 activation + increment 1 (dependency set built, census taken) |
||||
|
||||
- ACTIVATED by the user. Sources wired into both flows: `sources.config` gains |
||||
tk (`core-8-6-branch` -> dir `tk86`), tklib/tcllib (trunk) and critcl (git |
||||
3.3.1); `build.zig.zon` gains the matching pins - tk freshly `zig fetch`ed |
||||
(checkin 9986fdc267, 2025-03-17 = Tk 8.6.17), tklib/tcllib/critcl re-fetched |
||||
and verified BYTE-IDENTICAL to suite_tcl90's pins (generation-neutral |
||||
upstreams; what differs per suite is the shell running the installers and the |
||||
critcl target). suite.tcl gains git-source support + the new staging items; |
||||
the bootstrap driver's `source_dirs`/`recipe_items` match. |
||||
- TK 8.6 RE-DERIVED (`build_tk86/build_tk86.zig`) from the staged 8.6 |
||||
`win/makefile.vc` + `rules.vc`, not ported from the 9.0 module - the goal |
||||
Context's expectation held. Full derivation record in |
||||
`src/buildsuites/suite_tcl86/README.md`; the load-bearing differences: |
||||
no `tkPkgConfig.c` (so NO `CFG_*` defines at all), the |
||||
TCL_MAJOR_VERSION==8 naming arm (`tk86t.dll`, `lib/tk8.6`), the |
||||
`@TK_WIN_VERSION@` = `$(DOTVERSION).0.0` manifest substitution (not the |
||||
tcl-style releaselevel formula), and an 8.6 object inventory without |
||||
tkIcu/tkImgListFormat/tkImgSVGnano/tkWinGDI/tkWinIco/tkWinSysTray. Products: |
||||
`bin/tk86t.dll` + `lib/tk86t.lib` + the `lib/tk8.6` script library + |
||||
makefile-shaped `pkgIndex.tcl`. |
||||
- TK ACCEPTANCE EVIDENCE (repeatable - `tools/tk_smoke.tcl` runs in the `smoke` |
||||
step on every build, and a load-only check would pass with no usable display): |
||||
`tk_smoke OK: Tk 8.6.17 (Ttk 8.6.17) windowingsystem win32 screen 3840x2160 |
||||
depth 32 widgets Label/TButton/Toplevel create+map+destroy clean`. Both shells |
||||
load it: `pkg_smoke OK: Thread:2.8.13 vfs:1.4.2 registry:1.3.5 dde:1.4.6 |
||||
Tk:8.6.17` (static AND dynamic). |
||||
- TKLIB via its OWN installer (batch, packages-only, explicit `-pkg-path` so the |
||||
installer's tcl_pkgPath-derived default can never place files off-tree) -> |
||||
`lib/tklib0.9`. Representative require recorded: `pkg_smoke OK: tooltip:2.0.4` |
||||
- a Tk-DEPENDENT package resolving through the installer-generated aggregate |
||||
pkgIndex. |
||||
- TCLLIB 2.0 installed the same way (`md5:2.0.9 sha1:2.0.5 cmdline:1.5.3`), and |
||||
TCLLIBC built by critcl 3.3.1 driving `zig cc` under the suite-built 8.6 shell |
||||
(tracked `critcl_zig.config`, target pinned `win32-x86_64-zig` - critcl |
||||
otherwise probes PATH and falls back to its builtin msvc target). Accelerator |
||||
evidence, both on every build: `pkg_smoke OK: tcllibc:2.0 md5-critcl-accel:1` |
||||
and the new `tools/accel_bench.tcl` - |
||||
`accel_bench OK: sha1 over 4198400 bytes - critcl 5.9ms vs pure-tcl 2661.4ms |
||||
= 452.3x (digests identical, sha1 2.0.5, tcllibc 2.0)`. The bench loads BOTH |
||||
implementations via `::sha1::LoadAccelerator` and switches with |
||||
`::sha1::SwitchTo`, so the comparison is in-process and the digests are |
||||
compared rather than assumed. |
||||
- TEST TIERS extended on the G-107 policy pattern: `test-tcllib` / `test-tklib` |
||||
(record tier, inside `test-libraries`) and the OPT-IN `test-tk` (excluded from |
||||
`test-libraries`; `winDialog.test`/`winMsgbox.test` excluded by default - |
||||
their message-injection automation blocks on a human under a batch shell). |
||||
- HERMETIC-ENVIRONMENT FINDING (see Notes): `TCL<major>_<minor>_TM_PATH` was |
||||
never scrubbed, so the suite shells were silently preferring repo-built tm |
||||
modules over the tcllib the suite had just installed. Fixed in all three |
||||
scrub sites before the census was taken. |
||||
|
||||
#### punkshell runtests census (2026-07-26, both runs same day, same include set) |
||||
|
||||
Mode: DEFAULT single-process sequential (`-singleproc 1`; no `-jobs` - 8.6 has |
||||
no `tcl::process`, so parallel child spawning re-convoys on windows, per the |
||||
goal Context). Identical invocation for both runtimes, full source-tree suite, |
||||
no include filter: `<shell> src/tests/runtests.tcl -report json`. |
||||
|
||||
- BASELINE - native Tcl 8.6.17 (`C:/Users/sleek/AppData/Local/Apps/Tcl86`, |
||||
which carries Tk 8.6.17, Thread 2.8.12, tcllibc 2.0, twapi): 101 files, |
||||
Total 1003 / Passed 986 / Skipped 10 / Failed 7, 657s. Files failed: |
||||
`core/tcl/.../exec.test` (ERROR `invalid command name "tcl::build-info"` - a |
||||
9-era core test under an 8.6 shell), `modules/punk/ns/.../nslist.test` (4), |
||||
`modules/punk/ns/.../nsprimitives.test` (2 - the `:::odd` namespace-lookup |
||||
class), `modules/punkcheck/.../concurrency.test` (1). |
||||
- SUITE RUNTIME - `out/bin/tclsh86ts.exe` (8.6.18, this suite's static shell): |
||||
101 files, Total 1003 / Passed 987 / Skipped 10 / Failed 6, 601s. |
||||
- DIFFERENCE SET (authoritative, `scriptlib/developer/runtests_parity.tcl`): |
||||
exactly ONE - `punkcheck concurrency_two_writers_no_corruption` ERRORed in the |
||||
BASELINE run and PASSED on the suite runtime. Every other per-file status, |
||||
tally, failure identity, skip identity+reason and warning code is identical. |
||||
DISPOSITION: flake under full-suite load, not a runtime difference - the file |
||||
passes 6/6 in isolation on BOTH runtimes, twice each (verified same day). |
||||
ZERO suite-runtime-only failures; nothing needed baselining. |
||||
- TK-DEPENDENT SUITES RAN UNSKIPPED on the suite runtime: |
||||
`modules/punk/repl/testsuites/repl/consolebackends.test` 3/3 PASS (its |
||||
tkconsole backend drives a child repl on the suite-built Tk) and |
||||
`modules/opunk/console/testsuites/console/backends.test` 7 passed / 1 skipped. |
||||
That single skip is `backends_tkconsole_widget_size_and_eof`, whose |
||||
`tkavailable` constraint requires the `PUNK_TEST_TK` OPT-IN env var (not Tk |
||||
availability); it skips identically on the native baseline, and the opt-in's |
||||
own pre-existing quirk is recorded in G-098's increment 6 notes. |
||||
- Runtime-difference note (does not change any result): the suite runtime has no |
||||
twapi, so its runs open with `is_interactive cannot detect console ... without |
||||
twapi` and a `punk::du` slower-disk-operations warning that the native |
||||
baseline (twapi present) does not print. |
||||
|
||||
#### library test tiers - first censuses (2026-07-26, suite tclsh86ts.exe 8.6.18) |
||||
|
||||
Beyond the acceptance text; run because the goal Context asks the G-107 |
||||
policy-tier shape to follow for the new libraries. |
||||
|
||||
- thread (gate): 142 run / 126 passed / 16 skipped / 0 failed - GATE PASS |
||||
(baseline still empty; constraint-driven skips only). |
||||
- tklib (RECORD, new tier): 796 run / 684 passed / 112 skipped / 0 failed. Its |
||||
Tk-dependent suites exercise the suite-built Tk, and nothing failed. |
||||
- tcllib (RECORD, new tier): 64259 run / 61186 passed / 3032 skipped / 41 |
||||
failed - names in `out/testreports/tcllib.summary`. Dominant classes: |
||||
network-reaching suites (picoirc 20, httpd-proxy/cgi 4), installer/path |
||||
assumptions (install-2.1/2.2, find-sf-*/find-4.0, multi/multiop-5.2), plus |
||||
matrix-16.7/16.8, tar-add, uri-4.1, example-*, zipfile-encode-6.4/6.5. A |
||||
record tier is evidence, not a gate criterion - no baseline is tracked and the |
||||
step never fails the build on these. |
||||
- tclvfs (gate): the tcllib install CHANGED this suite's census - vfsFtp-1.1.. |
||||
1.3 sit behind an `ftp` constraint that needs tcllib's ftp package (absent at |
||||
the G-099 capture: 3 constraint skips), so they now RUN and reach the retired |
||||
`ftp://ftp.tcl.tk`, the same external-service class already baselined for |
||||
vfsUrl-1.2/2.1 (skips 8 -> 5 accordingly). `expected_test_failures_tclvfs.txt` |
||||
extended with the three names and the cause; re-run confirms GATE PASS |
||||
(51 run / 42 passed / 5 skipped / 4 failed, all baselined; vfsUrl-1.2 noted as |
||||
a stale entry - which members of the family fail is network-timing dependent, |
||||
so stale notes are expected and never fatal). |
||||
|
||||
Remains for acceptance: nothing - the four acceptance clauses (Tk loadable + |
||||
create/destroy verification, matching tklib with a representative require, |
||||
tcllib installed by its own machinery with loading accelerators and a recorded |
||||
accelerated-vs-pure comparison, and a dispositioned runtests census against a |
||||
same-day 8.6 baseline with Tk suites unskipped) are all recorded above. |
||||
|
||||
## Notes |
||||
|
||||
- Hermetic-environment finding 2026-07-26 (fixed here, exposure recorded for |
||||
suite_tcl90): `scrubTclEnv` cleared only TCLLIBPATH/TCL_LIBRARY/TK_LIBRARY, |
||||
but `tm.tcl` also seeds module roots from `env(TCL<major>_<minor>_TM_PATH)` |
||||
down through every lower minor. This machine points `TCL8_6_TM_PATH` at |
||||
`C:/repo/jn/shellspy/modules` among others, so suite shells preferred a |
||||
repo-built `sha1-2.0.4.tm` / `md5 2.0.8` over the tcllib 2.0.5 / 2.0.9 the |
||||
suite had just installed - a census through such a shell measures the machine. |
||||
Scrub list now covers `TCL8_0..8_7_TM_PATH` + `TCL9_0/9_1_TM_PATH` in the |
||||
per-step scrub (`build_common.zig` `tcl_env_vars`), `suite.tcl`'s |
||||
process-level unset and the bootstrap nested-build scrub. suite_tcl90 has the |
||||
same exposure via `TCL9_0_TM_PATH` and was deliberately left untouched (out of |
||||
this goal's scope) - worth a suite_tcl90-scoped fix. |
||||
- zig 0.16 trap (recorded while pinning): `zig fetch <url>` resolves a BUILD |
||||
ROOT before fetching, so it must be run from a directory containing a |
||||
`build.zig`; from anywhere else it dies with the misleading "no build.zig file |
||||
found, in the current directory or any parent directories". Also in the |
||||
`build.zig.zon` header. |
||||
- Activation freshness 2026-07-26: goals_xref.tcl score G-100 re-run at the |
||||
proposed->active flip (user-directed activation). Top pairs G-105 / G-101 / |
||||
G-116 / G-108 reviewed; the two that were only one-directional get the |
||||
back-pointers below, G-116 was already recorded here, and the remaining hits |
||||
are term noise - no new relationships. |
||||
- Related: G-105 (buildsuite cross-target) - it names this arc as a target- |
||||
dimension consumer; the tk/tklib/tcllib/critcl steps this goal adds must not |
||||
preclude a per-target dimension (no per-target tree copies, per-target out |
||||
prefixes). |
||||
- Related: G-101 (8.6 kit container strategy) - the downstream consumer of this |
||||
dependency set: whatever container it picks carries the Tk/tklib/tcllib/ |
||||
tcllibc payload this goal produces. |
||||
- Related: G-108 (debug buildsuite tier) - sibling suite-arc goal queued behind |
||||
this arc; its -dbg<n>/tcl::test variant pattern is suite_tcl90-scoped today. |
||||
- G-116 relationship (recorded 2026-07-24 after overlap review): G-116's zig-built |
||||
crypto-backend + static tcltls pattern (suite_tcl90) is the reference if the 8.6 |
||||
dependency set later grows a tls battery - the bi-family payload contract it |
||||
extends is generation-shaped, not 9-only. |
||||
- G-005 relationship: same zig toolchain-policy lineage as G-099's note - G-005 |
||||
owns the make.tcl-integrated vendored-extension build direction; the suites are |
||||
its arm's-length proving ground. |
||||
- G-099 (achieved, see goals/archive/G-099-suite-tcl86-buildsuite.md) delivered |
||||
the patterns this goal extends: the build86.zig recipe + build_tclthread86/ |
||||
build_tclvfs86 helpers (TEA-shape companion builds against the 8.6 stub lib), |
||||
the whole-tree library install + tm-module derivation, and the suite_tcl90 |
||||
G-107 (achieved - goals/archive/G-107-buildsuite-library-tests.md) policy-tier |
||||
test-gate (test_gate.tcl) - a Tk/tklib/tcllib gate follows the same shape. Two 8.6-specific traps recorded there carry forward: the |
||||
load-bearing MP_FIXED_CUTOFFS define and TCL_BROKEN_MAINARGS+console-subsystem |
||||
entry handling (build86.zig comments + README DERIVATION). Also inherited from |
||||
G-099 Notes: the G-106 powershell console-mode disableraw-via-server path is |
||||
only tcl9-verified - now that a twapi-less 8.6 runtime exists, run the G-106 |
||||
recipe against it (goals/archive/G-106-powershell-consolemode-fallback.md). |
||||
@ -0,0 +1,260 @@
|
||||
const std = @import("std"); |
||||
const common = @import("../build_common.zig"); |
||||
|
||||
//G-100: Tk 8.6 windows loadable extension (tk86t.dll) from stock core-8-6-branch |
||||
//sources, plus the tk script library installed to lib/tk8.6. |
||||
// |
||||
//DERIVED from the staged tk 8.6 win/makefile.vc + win/rules.vc - a re-derivation, |
||||
//not a port of the 9.0 build_tk.zig (the goal Context predicted this: the object |
||||
//lists and xlib arrangement differ). Differences from the 9.0 module, all |
||||
//makefile-authorised: |
||||
// - object inventory: 8.6 TKOBJS has no tkIcu / tkImgListFormat / tkImgSVGnano / |
||||
// tkPkgConfig, and no tkWinGDI / tkWinIco / tkWinSysTray. XLIBOBJS is the same |
||||
// 5-file emulation set but is a first-class makefile macro here (in 9.0 the |
||||
// xlib files had to be recovered by hand - the name-pattern extraction missed |
||||
// them). |
||||
// - NO tkPkgConfig.c in 8.6 -> no CFG_* configure-era defines at all (the 9.0 |
||||
// module carries a full CFG_{RUNTIME,INSTALL}_* set for it). |
||||
// - dll naming: rules.vc's TCL_MAJOR_VERSION==8 arm gives TKLIBNAME |
||||
// tk86t.dll (SUFX 't' survives while TCL_VERSION <= 86); the 9.0 arm produces |
||||
// the tcl9tk90.dll form. |
||||
// - wish.exe.manifest version: 8.6's makefile substitutes @TK_WIN_VERSION@ with |
||||
// $(DOTVERSION).0.0 = "8.6.0.0" - NOT the tcl-style |
||||
// <dotversion>.<releaselevel>.<patchlevel> formula the 9.0 tree uses. |
||||
// - pkgIndex: the 8.6 install-binaries text provides ONLY 'Tk' (no lowercase |
||||
// 'tk' alias) and guards with 'package vsatisfies [package provide Tcl] 8.6.0'. |
||||
// |
||||
//Kept from the 9.0 module (same reasons): |
||||
// - USE_TCL_STUBS/USE_TCLOO_STUBS + link against the suite's libtclstub86.a: |
||||
// that IS the stock arrangement (rules.vc sets USE_STUBS_DEFS for every |
||||
// project except tcl itself), and it keeps the dll unbound to a particular |
||||
// tcl dll name so both the static and dynamic suite shells can load it. |
||||
// - tkMain.c compiled twice (makefile: tkMain.obj + tkMain2.obj). The ansi copy |
||||
// gets explicit -UUNICODE/-U_UNICODE so a driver-side UNICODE default could |
||||
// never turn it into a duplicate UNICODE compile (G-096 finding; verified |
||||
// 2026-07-26 that the pinned zig cc defines neither for x86_64-windows-gnu, |
||||
// so the guard is belt-and-braces and the stock ANSI/TCHAR arrangement of the |
||||
// 8.6 core is matched exactly). |
||||
// - tkUuid.h generated into the build cache (tkWindow.c #includes it) and |
||||
// consumed via an include-dir overlay added FIRST - source trees are never |
||||
// written (G-102 convention). |
||||
|
||||
//win/makefile.vc TKOBJS, split by the directory each source actually lives in |
||||
//(verified against the staged tree - every name resolved to exactly one dir). |
||||
const generic_names = [_][]const u8{ |
||||
"tkConsole", "tk3d", "tkArgv", "tkAtom", "tkBind", |
||||
"tkBitmap", "tkBusy", "tkButton", "tkCanvArc", "tkCanvBmap", |
||||
"tkCanvImg", "tkCanvLine", "tkCanvPoly", "tkCanvPs", "tkCanvText", |
||||
"tkCanvUtil", "tkCanvWind", "tkCanvas", "tkClipboard", "tkCmds", |
||||
"tkColor", "tkConfig", "tkCursor", "tkEntry", "tkError", |
||||
"tkEvent", "tkFileFilter", "tkFocus", "tkFont", "tkFrame", |
||||
"tkGC", "tkGeometry", "tkGet", "tkGrab", "tkGrid", |
||||
"tkImage", "tkImgBmap", "tkImgGIF", "tkImgPNG", "tkImgPPM", |
||||
"tkImgPhoto", "tkImgPhInstance", "tkImgUtil", "tkListbox", "tkMacWinMenu", |
||||
"tkMenu", "tkMenubutton", "tkMenuDraw", "tkMessage", "tkPanedWindow", |
||||
"tkObj", "tkOldConfig", "tkOption", "tkPack", "tkPlace", |
||||
"tkPointer", "tkRectOval", "tkScale", "tkScrollbar", "tkSelect", |
||||
"tkStyle", "tkText", "tkTextBTree", "tkTextDisp", "tkTextImage", |
||||
"tkTextIndex", "tkTextMark", "tkTextTag", "tkTextWind", "tkTrig", |
||||
"tkUndo", "tkUtil", "tkVisual", "tkStubInit", "tkWindow", |
||||
}; |
||||
const unix_names = [_][]const u8{ "tkUnixMenubu", "tkUnixScale" }; |
||||
const xlib_names = [_][]const u8{ "xcolors", "xdraw", "xgc", "ximage", "xutil" }; |
||||
const win_names = [_][]const u8{ |
||||
"tkWin3d", "tkWin32Dll", "tkWinButton", "tkWinClipboard", "tkWinColor", |
||||
"tkWinConfig", "tkWinCursor", "tkWinDialog", "tkWinDraw", "tkWinEmbed", |
||||
"tkWinFont", "tkWinImage", "tkWinInit", "tkWinKey", "tkWinMenu", |
||||
"tkWinPixmap", "tkWinPointer", "tkWinRegion", "tkWinScrlbr", "tkWinSend", |
||||
"tkWinSendCom", "tkWinWindow", "tkWinWm", "tkWinX", "stubs", |
||||
"ttkWinMonitor", "ttkWinTheme", "ttkWinXPTheme", |
||||
}; |
||||
const ttk_names = [_][]const u8{ |
||||
"ttkBlink", "ttkButton", "ttkCache", "ttkClamTheme", "ttkClassicTheme", |
||||
"ttkDefaultTheme", "ttkElements", "ttkEntry", "ttkFrame", "ttkImage", |
||||
"ttkInit", "ttkLabel", "ttkLayout", "ttkManager", "ttkNotebook", |
||||
"ttkPanedwindow", "ttkProgress", "ttkScale", "ttkScrollbar", "ttkScroll", |
||||
"ttkSeparator", "ttkSquare", "ttkState", "ttkTagSet", "ttkTheme", |
||||
"ttkTrace", "ttkTrack", "ttkTreeview", "ttkWidget", "ttkStubInit", |
||||
}; |
||||
|
||||
pub const TkBuild = struct { |
||||
lib: *std.Build.Step.Compile, |
||||
pkgidx: std.Build.LazyPath, |
||||
patchlevel: []const u8, //e.g "8.6.17" (tk.h TK_PATCH_LEVEL) |
||||
libdir: []const u8, //install dir name, e.g "tk8.6" |
||||
dll_file: []const u8, //e.g "tk86t.dll" |
||||
}; |
||||
|
||||
pub fn build_tk86(comptime tcldir: []const u8, comptime subdir: []const u8, b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, stublib: *std.Build.Step.Compile) !TkBuild { |
||||
//-- version facts from the staged tree (never hardcoded) |
||||
const tkh_content = common.readSourceFile(b, subdir ++ "/generic/tk.h"); |
||||
const tk_h_version = common.parseDefineString(tkh_content, "TK_VERSION") orelse @panic("TK_VERSION not found in tk.h"); |
||||
const tk_h_patchlevel = common.parseDefineString(tkh_content, "TK_PATCH_LEVEL") orelse @panic("TK_PATCH_LEVEL not found in tk.h"); |
||||
if (!std.mem.eql(u8, tk_h_version, "8.6")) { |
||||
std.debug.panic("staged tk tree is {s} but this recipe expresses Tk 8.6 (sources.config tk ref / dir mismatch?)", .{tk_h_version}); |
||||
} |
||||
const tk_nodot = "86"; |
||||
const dll_name = "tk" ++ tk_nodot ++ "t"; //rules.vc TKLIBNAME, TCL_MAJOR_VERSION==8 arm |
||||
const dll_file = dll_name ++ ".dll"; |
||||
const script_dir_rel = "lib/tk8.6"; //rules.vc SCRIPT_INSTALL_DIR for DOING_TK |
||||
|
||||
const lib = b.addLibrary(.{ |
||||
.linkage = .dynamic, |
||||
.name = dll_name, |
||||
.root_module = b.createModule(.{ |
||||
.target = target, |
||||
.optimize = optimize, |
||||
}), |
||||
}); |
||||
|
||||
//-- flag classes (rules.vc pkgcflags for PROJECT=tk: cflags + INCLUDES + |
||||
//TCL_DEFINES + PRJ_DEFINES + OPTDEFINES + USE_STUBS_DEFS + /DBUILD_tk) |
||||
var flags = std.array_list.Managed([]const u8).init(b.allocator); |
||||
defer flags.deinit(); |
||||
try flags.appendSlice(&.{ |
||||
"-Wall", |
||||
"-O3", |
||||
"-fomit-frame-pointer", |
||||
"-finput-charset=UTF-8", |
||||
//the tcl 8.6 recipe's finding, kept here: clang UBSan traps must stay |
||||
//fully off on windows |
||||
"-fno-sanitize=undefined", |
||||
"-fno-sanitize-trap=undefined", |
||||
//project defines: makefile.vc PRJ_DEFINES (/DBUILD_ttk + CONFIG_DEFS; |
||||
//inline=__inline and the _CRT_*_NO_DEPRECATE pair are MSVC-isms) |
||||
"-DBUILD_tk", |
||||
"-DBUILD_ttk", |
||||
"-DSTDC_HEADERS=1", |
||||
"-DHAVE_SYS_TYPES_H=1", |
||||
"-DHAVE_SYS_STAT_H=1", |
||||
"-DHAVE_STDLIB_H=1", |
||||
"-DHAVE_STRING_H=1", |
||||
"-DHAVE_MEMORY_H=1", |
||||
"-DHAVE_STRINGS_H=1", |
||||
"-DHAVE_UXTHEME_H=1", //makefile default (OPTS=noxp turns it off) |
||||
//rules.vc USE_STUBS_DEFS for a non-tcl project |
||||
"-DUSE_TCL_STUBS=1", |
||||
"-DUSE_TCLOO_STUBS=1", |
||||
//OPTDEFINES equivalents, matching the flag set the 8.6 core was built with |
||||
"-DTCL_THREADS=1", |
||||
"-DNDEBUG=1", |
||||
"-DTCL_CFG_OPTIMIZED=1", |
||||
"-DTCL_CFG_DO64BIT=1", |
||||
"-DHAVE_NO_SEH=1", //gcc-class: no __try/__except |
||||
}); |
||||
|
||||
var sources = std.array_list.Managed([]const u8).init(b.allocator); |
||||
inline for (generic_names) |n| try sources.append(subdir ++ "/generic/" ++ n ++ ".c"); |
||||
inline for (unix_names) |n| try sources.append(subdir ++ "/unix/" ++ n ++ ".c"); |
||||
inline for (xlib_names) |n| try sources.append(subdir ++ "/xlib/" ++ n ++ ".c"); |
||||
inline for (win_names) |n| try sources.append(subdir ++ "/win/" ++ n ++ ".c"); |
||||
inline for (ttk_names) |n| try sources.append(subdir ++ "/generic/ttk/" ++ n ++ ".c"); |
||||
|
||||
//tkUuid.h overlay: makefile.vc concatenates win/tkUuid.h.in + the checkout's |
||||
//manifest.uuid; wrapfiletofile reproduces exactly that. |
||||
const wrapfilecmd = b.addExecutable(.{ |
||||
.name = "wrapfiletofile", |
||||
.root_module = b.createModule(.{ |
||||
.root_source_file = b.path("tools/wrapfiletofile.zig"), |
||||
.target = b.graph.host, |
||||
}), |
||||
}); |
||||
const uuidcmd_step = b.addRunArtifact(wrapfilecmd); |
||||
uuidcmd_step.addArgs(&.{ |
||||
"-prefix", |
||||
"#define TK_VERSION_UUID \\", |
||||
"-prefixnl", |
||||
"1", |
||||
"-input", |
||||
}); |
||||
uuidcmd_step.addFileArg(b.path(subdir ++ "/manifest.uuid")); |
||||
uuidcmd_step.addArg("-output"); |
||||
const tkuuid_file = uuidcmd_step.addOutputFileArg("tkUuid.h"); |
||||
lib.root_module.addIncludePath(tkuuid_file.dirname()); //overlay first |
||||
|
||||
lib.root_module.addIncludePath(b.path(subdir ++ "/generic")); |
||||
lib.root_module.addIncludePath(b.path(subdir ++ "/generic/ttk")); |
||||
lib.root_module.addIncludePath(b.path(subdir ++ "/win")); |
||||
lib.root_module.addIncludePath(b.path(subdir ++ "/xlib")); //PRJ_INCLUDES |
||||
lib.root_module.addIncludePath(b.path(subdir ++ "/bitmaps")); //PRJ_INCLUDES |
||||
lib.root_module.addIncludePath(b.path(tcldir ++ "/generic")); |
||||
lib.root_module.addIncludePath(b.path(tcldir ++ "/win")); |
||||
|
||||
lib.root_module.addCSourceFiles(.{ |
||||
.files = sources.items, |
||||
.flags = flags.items, |
||||
}); |
||||
|
||||
//tkMain.c twice - ansi (forced) + UNICODE 'tkMain2' (makefile.vc parity) |
||||
var mainansi_flags = std.array_list.Managed([]const u8).init(b.allocator); |
||||
defer mainansi_flags.deinit(); |
||||
try mainansi_flags.appendSlice(flags.items); |
||||
try mainansi_flags.appendSlice(&.{ "-UUNICODE", "-U_UNICODE" }); |
||||
lib.root_module.addCSourceFile(.{ |
||||
.file = b.path(subdir ++ "/generic/tkMain.c"), |
||||
.flags = mainansi_flags.items, |
||||
}); |
||||
var mainw_flags = std.array_list.Managed([]const u8).init(b.allocator); |
||||
defer mainw_flags.deinit(); |
||||
try mainw_flags.appendSlice(flags.items); |
||||
try mainw_flags.appendSlice(&.{ "-DUNICODE", "-D_UNICODE" }); |
||||
lib.root_module.addCSourceFile(.{ |
||||
.file = b.path(subdir ++ "/generic/tkMain.c"), |
||||
.flags = mainw_flags.items, |
||||
}); |
||||
|
||||
//wish.exe.manifest overlay: win/rc/tk.rc embeds it as RT_MANIFEST (that is |
||||
//what enables comctl32 v6 themed scrollbars in the DLL), and RT_MANIFEST |
||||
//file references resolve through the rc include paths. 8.6's makefile |
||||
//substitutes @TK_WIN_VERSION@ with $(DOTVERSION).0.0. |
||||
const tk_win_version = b.fmt("{s}.0.0", .{tk_h_version}); |
||||
const wish_manifest_content = common.replaceAll(b, common.replaceAll(b, common.readSourceFile(b, subdir ++ "/win/wish.exe.manifest.in"), "@TK_WIN_VERSION@", tk_win_version), "@MACHINE@", "AMD64"); |
||||
const wf_tkrc = b.addWriteFiles(); |
||||
_ = wf_tkrc.add("wish.exe.manifest", wish_manifest_content); |
||||
lib.root_module.addWin32ResourceFile(.{ |
||||
.file = b.path(subdir ++ "/win/rc/tk.rc"), |
||||
//TCL_THREADS drives the rc's OriginalFilename suffix (tk86t.dll) |
||||
.flags = &.{"-DTCL_THREADS=1"}, |
||||
.include_paths = &.{ |
||||
wf_tkrc.getDirectory(), |
||||
b.path(subdir ++ "/win"), |
||||
b.path(subdir ++ "/win/rc"), |
||||
b.path(subdir ++ "/generic"), |
||||
b.path(tcldir ++ "/generic"), |
||||
}, |
||||
}); |
||||
|
||||
lib.root_module.linkLibrary(stublib); |
||||
lib.root_module.link_libc = true; |
||||
//rules.vc winlibs + makefile.vc PRJ_LIBS, plus the OLE/dialog/IME imports the |
||||
//win sources pull in (tkWinSendCom, tkWinDialog, tkWinX) |
||||
inline for (.{ "netapi32", "gdi32", "user32", "userenv", "winspool", "shell32", "ole32", "oleaut32", "uuid", "comctl32", "comdlg32", "imm32", "uxtheme", "advapi32", "kernel32" }) |l| { |
||||
lib.root_module.linkSystemLibrary(l, .{}); |
||||
} |
||||
|
||||
b.installArtifact(lib); //bin/tk86t.dll (+ tk86t.lib import lib -> lib/) |
||||
|
||||
//tk script library -> <prefix>/lib/tk8.6 (whole-tree copy: stock splits the |
||||
//demos out to a separate dir, this keeps them inside - same simplification |
||||
//the tcl-side library install makes) |
||||
const install_tk_library = b.addInstallDirectory(.{ |
||||
.source_dir = b.path(subdir ++ "/library"), |
||||
.install_dir = .prefix, |
||||
.install_subdir = script_dir_rel, |
||||
}); |
||||
b.getInstallStep().dependOn(&install_tk_library.step); |
||||
|
||||
//pkgIndex.tcl per makefile.vc install-binaries (windows arm of its two-branch |
||||
//text - the unix DISPLAY branch cannot apply to a windows-only suite; |
||||
//'file normalize' added as in the 9.0 recipe so the load path is cwd-proof). |
||||
const wf_pkgidx = b.addWriteFiles(); |
||||
const pkgidx = wf_pkgidx.add("pkgIndex.tcl", b.fmt( |
||||
\\if {{![package vsatisfies [package provide Tcl] 8.6.0]}} return |
||||
\\package ifneeded Tk {s} [list load [file normalize [file join $dir .. .. bin {s}]]] |
||||
\\ |
||||
, .{ tk_h_patchlevel, dll_file })); |
||||
const pkgidx_install = b.addInstallFileWithDir(pkgidx, .prefix, script_dir_rel ++ "/pkgIndex.tcl"); |
||||
b.getInstallStep().dependOn(&pkgidx_install.step); |
||||
|
||||
return .{ .lib = lib, .pkgidx = pkgidx, .patchlevel = tk_h_patchlevel, .libdir = "tk8.6", .dll_file = dll_file }; |
||||
} |
||||
@ -0,0 +1,36 @@
|
||||
# suite_tcl86 critcl configuration: zig cc as the C toolchain (G-100). |
||||
# Forked from suite_tcl90/critcl_zig.config - generation-neutral content: critcl |
||||
# compiles against whichever tcl headers/stubs the DRIVING shell reports, so the |
||||
# 8.6 suite needs no flag differences here. 'zig' is resolved from PATH - the |
||||
# suite recipe prepends the pinned bin/tools zig dir for the critcl invocation. |
||||
# Target is the native windows-gnu triple (matches the suite's tcl runtime ABI). |
||||
# |
||||
# The settings live under an EXPLICIT target, win32-x86_64-zig, and the recipe |
||||
# invokes critcl with '-target win32-x86_64-zig': critcl otherwise chooses its |
||||
# build target by PROBING the environment for compilers, which made the selection |
||||
# depend on what happened to be on PATH (a visible gcc landed on the config |
||||
# defaults; a scrubbed environment fell back to critcl's builtin msvc 'cl' |
||||
# target and never used these settings - suite_tcl90 G-102 finding). |
||||
|
||||
platform win32-x86_64 |
||||
|
||||
win32-x86_64-zig platform win32-x86_64 |
||||
win32-x86_64-zig compile zig cc -target x86_64-windows-gnu -c -fPIC |
||||
win32-x86_64-zig version zig version |
||||
win32-x86_64-zig link zig cc -target x86_64-windows-gnu -shared |
||||
win32-x86_64-zig include -I |
||||
win32-x86_64-zig libinclude -L |
||||
win32-x86_64-zig object .o |
||||
win32-x86_64-zig output -o [list $outfile] |
||||
win32-x86_64-zig optimize -O2 |
||||
win32-x86_64-zig noassert -DNDEBUG |
||||
win32-x86_64-zig tclstubs -DUSE_TCL_STUBS |
||||
win32-x86_64-zig tkstubs -DUSE_TK_STUBS |
||||
win32-x86_64-zig debug_symbols -g |
||||
win32-x86_64-zig strip -Wl,-s |
||||
win32-x86_64-zig link_debug |
||||
win32-x86_64-zig link_release |
||||
win32-x86_64-zig embed_manifest |
||||
win32-x86_64-zig ldoutput |
||||
win32-x86_64-zig link_preload |
||||
win32-x86_64-zig sharedlibext .dll |
||||
@ -0,0 +1,109 @@
|
||||
# suite_tcl86 patches |
||||
|
||||
## sdx wrap.tcl - tclkit.inf binary-read fix (G-101) |
||||
|
||||
Recovered into tracked form 2026-07-26. Same rationale as the suite_tcl90 patch |
||||
recovery: these files previously existed ONLY in VCS-ignored on-disk copies |
||||
(`scratch/` and `TEMP_REFERENCE/` are ignored by both git and fossil - root |
||||
`.gitignore:35,59` and `.fossil-settings/ignore-glob:35-36,58-59`), so a |
||||
`git clean -xdf` would have destroyed the only evidence of what the patch is. |
||||
|
||||
### What this documents |
||||
|
||||
`bin/sdx.kit` is TRACKED and is the tool `src/make.tcl` resolves for the 'kit' |
||||
wrap path (discovery ladder at src/make.tcl:5048-5097). It is NOT stock sdx: it |
||||
is a locally-patched build whose patch was recorded nowhere in version control. |
||||
|
||||
Two distinct sdx binaries were found on the author's machine, differing by 121 |
||||
bytes: |
||||
|
||||
| copy | sha256 | size | VCS | |
||||
| --- | --- | --- | --- | |
||||
| `bin/sdx.kit` (== `TEMP_REFERENCE/sdx/sdx.kit`) | `5d4aa629495bb68b737dfe7280363ceb0a6653938380e8c9ccc9063a3864f531` | 119191 | tracked | |
||||
| `scratch/sdx.kit` (== `scratch/sdx-20110317.kit`) | `04dc85d4503c037f26c2b8719e45e4e20385674fbc7404481f3c171fce0a26c3` | 119312 | ignored | |
||||
|
||||
Unwrapped, both are 64 files and are IDENTICAL except `lib/app-sdx/wrap.tcl`. |
||||
That one file is the entire provenance delta, and it is the two-line change |
||||
captured here. |
||||
|
||||
### The change |
||||
|
||||
In the Windows version-resource customization path (wrap.tcl:232-239 in the |
||||
patched copy), reading `tclkit.inf`: |
||||
|
||||
``` |
||||
- set fd [open [file join $idir tclkit.inf]] |
||||
+ set fd [open [file join $idir tclkit.inf] "r"] |
||||
+ fconfigure $fd -translation binary |
||||
``` |
||||
|
||||
The array read from that file is handed straight to |
||||
`::stringfileinfo::writeStringInfo`, which patches the PE version resource of the |
||||
output executable. Without binary translation the read is line-ending-translated, |
||||
so this reads as a fix for CRLF corruption of `tclkit.inf` content on Windows. |
||||
NOT VERIFIED against a failing case - the fix is plausible and small, but no |
||||
reproducer was recorded with it. Confirming (or retiring) it is part of the |
||||
G-101 sdx characterization work. |
||||
|
||||
Note the patch only fires when ALL of: `-runtime` was given, the runtime has a |
||||
`.exe` extension, and `tclkit.inf` exists in the source `.vfs`. No `tclkit.inf` |
||||
currently exists anywhere in this repo, so the patched path is DORMANT for |
||||
present builds - it matters only if/when version-stamping of wrapped executables |
||||
is turned on. |
||||
|
||||
### Files |
||||
|
||||
- `sdx-2011.03.17-wrap.tcl` - the STOCK baseline, byte-exact |
||||
(sha256 `41e669dce6da5b102f4924a4c177501b0ab8f3f62bf0657d88bdea73089c0a75`). |
||||
Kept in full because upstream is GONE: sdx's home was |
||||
`svn://svn.equi4.com/sdx/trunk` (per its ChangeLog, last entry 2011-03-17 by |
||||
Pat Thoyts) and it cannot be re-fetched. This is the irreplaceable artifact |
||||
here - the patched version is independently recoverable by unwrapping the |
||||
tracked `bin/sdx.kit`. |
||||
- `sdx-wrap_tclkitinf_binary.tcl` - the PATCHED file as it exists inside |
||||
`bin/sdx.kit`, byte-exact |
||||
(sha256 `7a77009be04e0da5fb750d86a6c1e7141bf712422434d0908456e40766b847be`). |
||||
Kept as a drop-in per the suite_tcl90 convention (full patched file alongside |
||||
the diff), so a rebuild does not depend on a working `patch` tool. |
||||
- `sdx-wrap.tcl.tclkitinf-binary.patch` - the diff between the two. Round-trip |
||||
verified 2026-07-26: applying it to the stock baseline reproduces the patched |
||||
file byte for byte. Apply with `patch --binary` on Windows - without it the |
||||
CRLF context lines will not match. |
||||
|
||||
LINE ENDINGS: the two `.tcl` files are CRLF and MUST STAY CRLF. They are vendored |
||||
fidelity artifacts whose bytes must match the kit contents; the repo's usual |
||||
LF-on-edit preference does not apply to them. Do not run a line-ending normalizer |
||||
over this directory. This README is LF. |
||||
|
||||
### Verifying the capture |
||||
|
||||
`sdx version` walks a mounted kit and prints `<mtime> <crc-hi>-<crc-lo>` |
||||
(`lib/app-sdx/version.tcl`). Observed under |
||||
`bin/runtime/win32-x86_64/tclkit86bi.exe`: |
||||
|
||||
``` |
||||
bin/sdx.kit -> 2025/06/04 22:56:36 69170-33997 |
||||
scratch/sdx.kit -> 2011/03/17 23:39:41 50768-16003 |
||||
``` |
||||
|
||||
The tracked kit's timestamp is exactly the patched `wrap.tcl` mtime, which is |
||||
what confirms the patch is inside the tracked kit rather than only on disk. |
||||
|
||||
TRAP for any rebuild-and-compare: `traverse` hashes file NAME + MTIME + SIZE, not |
||||
content, so this signature is NOT reproducible across a re-wrap unless mtimes are |
||||
normalised (`sdx version -fixtime`). Content-level characterization needs its own |
||||
comparison - unwrap and diff trees, plus behavioural wrap/unwrap/mksplit |
||||
round-trips - not this signature alone. |
||||
|
||||
### Why this lives here |
||||
|
||||
Placed under the suite that owns the question rather than beside the binary: |
||||
`bin/` is documented as build outputs and tooling (bin/AGENTS.md), not source |
||||
material. G-101 (kit container strategy for zig-built 8.6 runtimes) owns the sdx |
||||
provenance and rebuild decision, and sdx is the kit-wrapping tool that goal must |
||||
either keep, rebuild, or replace. If G-101 replaces sdx with a suite-owned kit |
||||
writer, this capture stays as the record of what the retired tool did. |
||||
|
||||
Full findings - including the bootstrap circularity (sdx.kit is itself a metakit |
||||
starkit and needs a tclkit to run), the 2011-era bundled library set, and the |
||||
stale `bin/sdx1.bat` wrapper - are in `goals/G-101-tcl86-kit-container-strategy.md`. |
||||
@ -0,0 +1,344 @@
|
||||
# wrap - convert file system tree to a starkit |
||||
# by Matt Newman <matt@sensus.org> and Jean-Claude Wippler <jcw@equi4.com> |
||||
# |
||||
# 20020607 jcw added -writeable, switched to starkit package |
||||
# the default is now to creates a read-only starkit |
||||
|
||||
set header \ |
||||
{#!/bin/sh |
||||
# % |
||||
exec @PROG@ "$0" ${1+"$@"} |
||||
package require starkit |
||||
starkit::header @TYPE@ @OPTS@ |
||||
} |
||||
append header \32 |
||||
regsub % $header \\ header |
||||
|
||||
if {[llength $argv] < 1} { |
||||
puts stderr "Usage: $argv0 outfile ?-option ...?" |
||||
exit 1 |
||||
} |
||||
|
||||
set origtime [clock seconds] |
||||
|
||||
proc readfile {name} { |
||||
set fd [open $name] |
||||
fconfigure $fd -translation binary |
||||
set data [read $fd] |
||||
close $fd |
||||
return $data |
||||
} |
||||
|
||||
proc writefile {name data} { |
||||
set fd [open $name w] |
||||
fconfigure $fd -translation binary |
||||
puts -nonewline $fd $data |
||||
close $fd |
||||
} |
||||
|
||||
# decode Windows .ICO file contents into the individual bit maps |
||||
# Each icon header has: |
||||
# byte : width in pixels (0 for 256 px) |
||||
# byte : height in pixels (0 for 256px) |
||||
# byte : number of colors in palette (0 for truecolor) |
||||
# byte : reserved (0) |
||||
# short: number of color planes (0 or 1) |
||||
# short: number of bits per pixel |
||||
# long : size of the bitmap data in bytes |
||||
# long : offset to the start of bitmap data |
||||
proc decICO {dat} { |
||||
set result {} |
||||
binary scan $dat sss - type count |
||||
for {set pos 6} {[incr count -1] >= 0} {incr pos 16} { |
||||
binary scan $dat @${pos}ccccssii w h cc - p bc bir io |
||||
if {$cc == 0} { set cc 256 } |
||||
#puts "pos $pos w $w h $h cc $cc p $p bc $bc bir $bir io $io" |
||||
binary scan $dat @${io}a$bir image |
||||
lappend result ${w}x${h}/$bc $image |
||||
} |
||||
return $result |
||||
} |
||||
|
||||
proc LoadHeader {filename} { |
||||
if {[file normalize $filename] == [info nameofexe]} { |
||||
puts stderr "file in use, cannot be prefix: [file normalize $filename]" |
||||
exit 1 |
||||
} |
||||
set size [file size $filename] |
||||
catch { |
||||
package require vfs::mk4 |
||||
vfs::mk4::Mount $filename hdr -readonly |
||||
# we only look for an icon if the runtime is called *.exe (!) |
||||
if {[string tolower [file extension $filename]] == ".exe"} { |
||||
catch { set ::origicon [readfile hdr/tclkit.ico] } |
||||
} |
||||
} |
||||
catch { vfs::unmount $filename } |
||||
return [readfile $filename] |
||||
} |
||||
|
||||
set out [lindex $argv 0] |
||||
set base [file root [file tail $out]] |
||||
set idir $base.vfs |
||||
if {![file isdirectory $idir]} { |
||||
if {[file isdirectory $base] && [file exists $base/main.tcl]} { |
||||
set idir $base |
||||
if {[lindex [split $out .] 0] eq $out} { |
||||
# append kit if user hasn't specified an extension |
||||
set out $base.kit |
||||
} |
||||
} |
||||
} |
||||
set compress 1 |
||||
set verbose 0 |
||||
set ropts -readonly |
||||
set prefix 0 |
||||
set reusefile 0 |
||||
set prog tclkit |
||||
set type mk4 |
||||
set explist {} |
||||
set syncopts {} |
||||
|
||||
set a [lindex $argv 1] |
||||
while {[string match -* $a]} { |
||||
switch -- $a { |
||||
-interp { |
||||
set prog [lindex $argv 2] |
||||
set argv [lreplace $argv 1 2] |
||||
} |
||||
-runtime { |
||||
set pfile [lindex $argv 2] |
||||
if {$pfile == $out} { |
||||
set reusefile 1 |
||||
} else { |
||||
set header [LoadHeader $pfile] |
||||
} |
||||
set argv [lreplace $argv 1 2] |
||||
set prefix 1 |
||||
} |
||||
-writable - |
||||
-writeable { |
||||
#set ropts "-nocommit" |
||||
set ropts "" |
||||
set argv [lreplace $argv 1 1] |
||||
} |
||||
-nocomp - |
||||
-nocompress { |
||||
set compress 0 |
||||
set argv [lreplace $argv 1 1] |
||||
} |
||||
-verbose { |
||||
set verbose 1 |
||||
set argv [lreplace $argv 1 1] |
||||
} |
||||
-uncomp { |
||||
lappend explist [lindex $argv 2] |
||||
set argv [lreplace $argv 1 2] |
||||
} |
||||
-vfs { |
||||
set idir [lindex $argv 2] |
||||
set argv [lreplace $argv 1 2] |
||||
} |
||||
default { |
||||
lappend syncopts [lindex $argv 1] [lindex $argv 2] |
||||
set argv [lreplace $argv 1 2] |
||||
} |
||||
} |
||||
set a [lindex $argv 1] |
||||
} |
||||
|
||||
if {![file isdir $idir]} { |
||||
puts stderr "Input directory not found: $idir" |
||||
exit 1 |
||||
} |
||||
|
||||
if {!$prefix} { |
||||
regsub @PROG@ $header $prog header |
||||
regsub @OPTS@ $header $ropts header |
||||
regsub @TYPE@ $header $type header |
||||
|
||||
set n [string length $header] |
||||
while {$n <= 240} { |
||||
append header ################ |
||||
incr n 16 |
||||
} |
||||
|
||||
set slop [expr { 15 - (($n + 15) % 16) }] |
||||
for {set i 0} {$i < $slop} {incr i} { |
||||
append header # |
||||
} |
||||
set n [string length $header] |
||||
if {$n % 16 != 0} { |
||||
error "Header size is $n, should be a multiple of 16" |
||||
} |
||||
} |
||||
|
||||
if {!$reusefile} { |
||||
writefile $out $header |
||||
} |
||||
|
||||
set origsize [file size $out] |
||||
|
||||
switch $tcl_platform(platform) { |
||||
unix { |
||||
catch {file attributes $out -permissions +x} |
||||
} |
||||
windows { |
||||
set batfile [file root $out].bat |
||||
# 2005-03-18 don't create a batfile if "-runtime" is specified |
||||
if {![file exists $batfile] && ![info exists pfile]} { |
||||
set fd [open $batfile w] |
||||
puts -nonewline $fd \ |
||||
"@$prog [file tail $out] %1 %2 %3 %4 %5 %6 %7 %8 %9" |
||||
close $fd |
||||
} |
||||
} |
||||
macintosh { |
||||
catch {file attributes $out -creator TKd4} |
||||
} |
||||
} |
||||
|
||||
# 2003-02-08: added code to patch icon in windows executable |
||||
# triggered by existence of tclkit.ico in vfs dir *and* tclkit.ico in orig |
||||
|
||||
# careful: this applies only to windows executables, but the |
||||
# icon replacement can in fact take place on any platform... |
||||
|
||||
if {[info exists origicon] && [file exists [file join $idir tclkit.ico]]} { |
||||
puts " customizing tclkit.ico in executable" |
||||
set custicon [readfile [file join $idir tclkit.ico]] |
||||
array set newimg [decICO $custicon] |
||||
foreach {k v} [decICO $origicon] { |
||||
if {[info exists newimg($k)]} { |
||||
set len [string length $v] |
||||
set pos [string first $v $header] |
||||
if {$pos < 0} { |
||||
puts " icon $k: NOT FOUND" |
||||
} elseif {[string length $newimg($k)] != $len} { |
||||
puts " icon $k: NOT SAME SIZE" |
||||
} else { |
||||
binary scan $header a${pos}a${len}a* prefix - suffix |
||||
set header "$prefix$newimg($k)$suffix" |
||||
puts " icon $k: replaced" |
||||
} |
||||
} |
||||
} |
||||
writefile $out $header |
||||
} |
||||
|
||||
# 2005-03-15 added AF's code to customize version/description strings in exe's |
||||
if {[info exists pfile] && |
||||
[string tolower [file extension $pfile]] == ".exe" && |
||||
[file exists [file join $idir tclkit.inf]]} { |
||||
puts " customizing strings in executable" |
||||
package require stringfileinfo |
||||
set fd [open [file join $idir tclkit.inf]] |
||||
array set strinfo [read $fd] |
||||
close $fd |
||||
::stringfileinfo::writeStringInfo $out strinfo |
||||
} |
||||
|
||||
proc tclLog {msg} { puts $msg } |
||||
|
||||
proc mkFileStart {filename} { |
||||
set end [file size $filename] |
||||
if {$end < 27} { |
||||
fail "file too small, cannot be a datafile" |
||||
} |
||||
|
||||
set fd [open $filename] |
||||
fconfigure $fd -translation binary |
||||
seek $fd -16 end |
||||
binary scan [read $fd 16] IIII a b c d |
||||
close $fd |
||||
|
||||
#puts [format %x-%d-%x-%d $a $b $c $d] |
||||
|
||||
if {($c >> 24) != -128} { |
||||
error "this is not a Metakit datafile" |
||||
} |
||||
|
||||
# avoid negative sign / overflow issues |
||||
if {[format %x [expr {$a & 0xffffffff}]] eq "80000000"} { |
||||
set start [expr {$end - 16 - $b}] |
||||
} else { |
||||
# if the file is in commit-progress state, we need to do more |
||||
error "this code needs to be finished..." |
||||
} |
||||
|
||||
return $start |
||||
} |
||||
|
||||
if {![catch { package require Mk4tcl }]} { |
||||
vfs::mk4::Mount $out $out |
||||
set argv $syncopts |
||||
lappend argv -compress $compress -verbose $verbose -noerror 0 $idir $out |
||||
|
||||
source [file join [file dirname [info script]] sync.tcl] |
||||
|
||||
# 2003-06-19: new "-uncomp name" option to store specific file(s) |
||||
# in uncompressed form, even if the rest is compressed |
||||
set o $vfs::mk4::compress |
||||
set vfs::mk4::compress 0 |
||||
foreach f $explist { |
||||
file delete -force [file join $out $f] |
||||
file copy [file join $idir $f] [file join $out $f] |
||||
} |
||||
set vfs::mk4::compress $o |
||||
|
||||
vfs::unmount $out |
||||
} elseif {![catch { package require vlerq }]} { |
||||
package require vfs::m2m 1.8 |
||||
|
||||
if {$verbose} { |
||||
puts "Mk4tcl not found, switching to the Vlerq driver." |
||||
} |
||||
|
||||
# 2006-12-06, must do a bit more work for starpacks when there is no Mk4tcl: |
||||
# - split the tail off |
||||
# - truncate the file so only the head remains |
||||
# - copy the original vfs contents to m2m, to be overwritten/extended later |
||||
|
||||
set outsize [file size $out] |
||||
|
||||
if {![catch { mkFileStart $out } mkpos]} { |
||||
set fd [open $out] |
||||
fconfigure $fd -translation binary |
||||
set outhead [read $fd $mkpos] |
||||
set origvfs [read $fd] |
||||
close $fd |
||||
|
||||
set fd [open $out w] |
||||
fconfigure $fd -translation binary |
||||
puts -nonewline $fd $outhead |
||||
close $fd |
||||
} |
||||
|
||||
vfs::m2m::Mount $out $out |
||||
|
||||
if {[info exists origvfs]} { |
||||
set fd [open $out.tmp w] |
||||
fconfigure $fd -translation binary |
||||
puts -nonewline $fd $origvfs |
||||
close $fd |
||||
|
||||
package require vfs::mkcl |
||||
vfs::mkcl::Mount $out.tmp $out.tmp |
||||
|
||||
set argv [list -verbose 0 $out.tmp $out] |
||||
source [file join [file dirname [info script]] sync.tcl] |
||||
|
||||
vfs::unmount $out.tmp |
||||
file delete $out.tmp |
||||
} |
||||
|
||||
set argv $syncopts |
||||
lappend argv -verbose $verbose -noerror 0 $idir $out |
||||
|
||||
source [file join [file dirname [info script]] sync.tcl] |
||||
|
||||
vfs::unmount $out |
||||
} else { |
||||
puts stderr "cannot find required packages (Mk4tcl or Vlerq)" |
||||
exit 1 |
||||
} |
||||
@ -0,0 +1,12 @@
|
||||
--- a/lib/app-sdx/wrap.tcl (sdx 2011-03-17 stock)
|
||||
+++ b/lib/app-sdx/wrap.tcl (bin/sdx.kit patched)
|
||||
@@ -232,7 +232,8 @@
|
||||
[file exists [file join $idir tclkit.inf]]} {
|
||||
puts " customizing strings in executable"
|
||||
package require stringfileinfo
|
||||
- set fd [open [file join $idir tclkit.inf]]
|
||||
+ set fd [open [file join $idir tclkit.inf] "r"]
|
||||
+ fconfigure $fd -translation binary
|
||||
array set strinfo [read $fd]
|
||||
close $fd
|
||||
::stringfileinfo::writeStringInfo $out strinfo
|
||||
@ -0,0 +1,345 @@
|
||||
# wrap - convert file system tree to a starkit |
||||
# by Matt Newman <matt@sensus.org> and Jean-Claude Wippler <jcw@equi4.com> |
||||
# |
||||
# 20020607 jcw added -writeable, switched to starkit package |
||||
# the default is now to creates a read-only starkit |
||||
|
||||
set header \ |
||||
{#!/bin/sh |
||||
# % |
||||
exec @PROG@ "$0" ${1+"$@"} |
||||
package require starkit |
||||
starkit::header @TYPE@ @OPTS@ |
||||
} |
||||
append header \32 |
||||
regsub % $header \\ header |
||||
|
||||
if {[llength $argv] < 1} { |
||||
puts stderr "Usage: $argv0 outfile ?-option ...?" |
||||
exit 1 |
||||
} |
||||
|
||||
set origtime [clock seconds] |
||||
|
||||
proc readfile {name} { |
||||
set fd [open $name] |
||||
fconfigure $fd -translation binary |
||||
set data [read $fd] |
||||
close $fd |
||||
return $data |
||||
} |
||||
|
||||
proc writefile {name data} { |
||||
set fd [open $name w] |
||||
fconfigure $fd -translation binary |
||||
puts -nonewline $fd $data |
||||
close $fd |
||||
} |
||||
|
||||
# decode Windows .ICO file contents into the individual bit maps |
||||
# Each icon header has: |
||||
# byte : width in pixels (0 for 256 px) |
||||
# byte : height in pixels (0 for 256px) |
||||
# byte : number of colors in palette (0 for truecolor) |
||||
# byte : reserved (0) |
||||
# short: number of color planes (0 or 1) |
||||
# short: number of bits per pixel |
||||
# long : size of the bitmap data in bytes |
||||
# long : offset to the start of bitmap data |
||||
proc decICO {dat} { |
||||
set result {} |
||||
binary scan $dat sss - type count |
||||
for {set pos 6} {[incr count -1] >= 0} {incr pos 16} { |
||||
binary scan $dat @${pos}ccccssii w h cc - p bc bir io |
||||
if {$cc == 0} { set cc 256 } |
||||
#puts "pos $pos w $w h $h cc $cc p $p bc $bc bir $bir io $io" |
||||
binary scan $dat @${io}a$bir image |
||||
lappend result ${w}x${h}/$bc $image |
||||
} |
||||
return $result |
||||
} |
||||
|
||||
proc LoadHeader {filename} { |
||||
if {[file normalize $filename] == [info nameofexe]} { |
||||
puts stderr "file in use, cannot be prefix: [file normalize $filename]" |
||||
exit 1 |
||||
} |
||||
set size [file size $filename] |
||||
catch { |
||||
package require vfs::mk4 |
||||
vfs::mk4::Mount $filename hdr -readonly |
||||
# we only look for an icon if the runtime is called *.exe (!) |
||||
if {[string tolower [file extension $filename]] == ".exe"} { |
||||
catch { set ::origicon [readfile hdr/tclkit.ico] } |
||||
} |
||||
} |
||||
catch { vfs::unmount $filename } |
||||
return [readfile $filename] |
||||
} |
||||
|
||||
set out [lindex $argv 0] |
||||
set base [file root [file tail $out]] |
||||
set idir $base.vfs |
||||
if {![file isdirectory $idir]} { |
||||
if {[file isdirectory $base] && [file exists $base/main.tcl]} { |
||||
set idir $base |
||||
if {[lindex [split $out .] 0] eq $out} { |
||||
# append kit if user hasn't specified an extension |
||||
set out $base.kit |
||||
} |
||||
} |
||||
} |
||||
set compress 1 |
||||
set verbose 0 |
||||
set ropts -readonly |
||||
set prefix 0 |
||||
set reusefile 0 |
||||
set prog tclkit |
||||
set type mk4 |
||||
set explist {} |
||||
set syncopts {} |
||||
|
||||
set a [lindex $argv 1] |
||||
while {[string match -* $a]} { |
||||
switch -- $a { |
||||
-interp { |
||||
set prog [lindex $argv 2] |
||||
set argv [lreplace $argv 1 2] |
||||
} |
||||
-runtime { |
||||
set pfile [lindex $argv 2] |
||||
if {$pfile == $out} { |
||||
set reusefile 1 |
||||
} else { |
||||
set header [LoadHeader $pfile] |
||||
} |
||||
set argv [lreplace $argv 1 2] |
||||
set prefix 1 |
||||
} |
||||
-writable - |
||||
-writeable { |
||||
#set ropts "-nocommit" |
||||
set ropts "" |
||||
set argv [lreplace $argv 1 1] |
||||
} |
||||
-nocomp - |
||||
-nocompress { |
||||
set compress 0 |
||||
set argv [lreplace $argv 1 1] |
||||
} |
||||
-verbose { |
||||
set verbose 1 |
||||
set argv [lreplace $argv 1 1] |
||||
} |
||||
-uncomp { |
||||
lappend explist [lindex $argv 2] |
||||
set argv [lreplace $argv 1 2] |
||||
} |
||||
-vfs { |
||||
set idir [lindex $argv 2] |
||||
set argv [lreplace $argv 1 2] |
||||
} |
||||
default { |
||||
lappend syncopts [lindex $argv 1] [lindex $argv 2] |
||||
set argv [lreplace $argv 1 2] |
||||
} |
||||
} |
||||
set a [lindex $argv 1] |
||||
} |
||||
|
||||
if {![file isdir $idir]} { |
||||
puts stderr "Input directory not found: $idir" |
||||
exit 1 |
||||
} |
||||
|
||||
if {!$prefix} { |
||||
regsub @PROG@ $header $prog header |
||||
regsub @OPTS@ $header $ropts header |
||||
regsub @TYPE@ $header $type header |
||||
|
||||
set n [string length $header] |
||||
while {$n <= 240} { |
||||
append header ################ |
||||
incr n 16 |
||||
} |
||||
|
||||
set slop [expr { 15 - (($n + 15) % 16) }] |
||||
for {set i 0} {$i < $slop} {incr i} { |
||||
append header # |
||||
} |
||||
set n [string length $header] |
||||
if {$n % 16 != 0} { |
||||
error "Header size is $n, should be a multiple of 16" |
||||
} |
||||
} |
||||
|
||||
if {!$reusefile} { |
||||
writefile $out $header |
||||
} |
||||
|
||||
set origsize [file size $out] |
||||
|
||||
switch $tcl_platform(platform) { |
||||
unix { |
||||
catch {file attributes $out -permissions +x} |
||||
} |
||||
windows { |
||||
set batfile [file root $out].bat |
||||
# 2005-03-18 don't create a batfile if "-runtime" is specified |
||||
if {![file exists $batfile] && ![info exists pfile]} { |
||||
set fd [open $batfile w] |
||||
puts -nonewline $fd \ |
||||
"@$prog [file tail $out] %1 %2 %3 %4 %5 %6 %7 %8 %9" |
||||
close $fd |
||||
} |
||||
} |
||||
macintosh { |
||||
catch {file attributes $out -creator TKd4} |
||||
} |
||||
} |
||||
|
||||
# 2003-02-08: added code to patch icon in windows executable |
||||
# triggered by existence of tclkit.ico in vfs dir *and* tclkit.ico in orig |
||||
|
||||
# careful: this applies only to windows executables, but the |
||||
# icon replacement can in fact take place on any platform... |
||||
|
||||
if {[info exists origicon] && [file exists [file join $idir tclkit.ico]]} { |
||||
puts " customizing tclkit.ico in executable" |
||||
set custicon [readfile [file join $idir tclkit.ico]] |
||||
array set newimg [decICO $custicon] |
||||
foreach {k v} [decICO $origicon] { |
||||
if {[info exists newimg($k)]} { |
||||
set len [string length $v] |
||||
set pos [string first $v $header] |
||||
if {$pos < 0} { |
||||
puts " icon $k: NOT FOUND" |
||||
} elseif {[string length $newimg($k)] != $len} { |
||||
puts " icon $k: NOT SAME SIZE" |
||||
} else { |
||||
binary scan $header a${pos}a${len}a* prefix - suffix |
||||
set header "$prefix$newimg($k)$suffix" |
||||
puts " icon $k: replaced" |
||||
} |
||||
} |
||||
} |
||||
writefile $out $header |
||||
} |
||||
|
||||
# 2005-03-15 added AF's code to customize version/description strings in exe's |
||||
if {[info exists pfile] && |
||||
[string tolower [file extension $pfile]] == ".exe" && |
||||
[file exists [file join $idir tclkit.inf]]} { |
||||
puts " customizing strings in executable" |
||||
package require stringfileinfo |
||||
set fd [open [file join $idir tclkit.inf] "r"] |
||||
fconfigure $fd -translation binary |
||||
array set strinfo [read $fd] |
||||
close $fd |
||||
::stringfileinfo::writeStringInfo $out strinfo |
||||
} |
||||
|
||||
proc tclLog {msg} { puts $msg } |
||||
|
||||
proc mkFileStart {filename} { |
||||
set end [file size $filename] |
||||
if {$end < 27} { |
||||
fail "file too small, cannot be a datafile" |
||||
} |
||||
|
||||
set fd [open $filename] |
||||
fconfigure $fd -translation binary |
||||
seek $fd -16 end |
||||
binary scan [read $fd 16] IIII a b c d |
||||
close $fd |
||||
|
||||
#puts [format %x-%d-%x-%d $a $b $c $d] |
||||
|
||||
if {($c >> 24) != -128} { |
||||
error "this is not a Metakit datafile" |
||||
} |
||||
|
||||
# avoid negative sign / overflow issues |
||||
if {[format %x [expr {$a & 0xffffffff}]] eq "80000000"} { |
||||
set start [expr {$end - 16 - $b}] |
||||
} else { |
||||
# if the file is in commit-progress state, we need to do more |
||||
error "this code needs to be finished..." |
||||
} |
||||
|
||||
return $start |
||||
} |
||||
|
||||
if {![catch { package require Mk4tcl }]} { |
||||
vfs::mk4::Mount $out $out |
||||
set argv $syncopts |
||||
lappend argv -compress $compress -verbose $verbose -noerror 0 $idir $out |
||||
|
||||
source [file join [file dirname [info script]] sync.tcl] |
||||
|
||||
# 2003-06-19: new "-uncomp name" option to store specific file(s) |
||||
# in uncompressed form, even if the rest is compressed |
||||
set o $vfs::mk4::compress |
||||
set vfs::mk4::compress 0 |
||||
foreach f $explist { |
||||
file delete -force [file join $out $f] |
||||
file copy [file join $idir $f] [file join $out $f] |
||||
} |
||||
set vfs::mk4::compress $o |
||||
|
||||
vfs::unmount $out |
||||
} elseif {![catch { package require vlerq }]} { |
||||
package require vfs::m2m 1.8 |
||||
|
||||
if {$verbose} { |
||||
puts "Mk4tcl not found, switching to the Vlerq driver." |
||||
} |
||||
|
||||
# 2006-12-06, must do a bit more work for starpacks when there is no Mk4tcl: |
||||
# - split the tail off |
||||
# - truncate the file so only the head remains |
||||
# - copy the original vfs contents to m2m, to be overwritten/extended later |
||||
|
||||
set outsize [file size $out] |
||||
|
||||
if {![catch { mkFileStart $out } mkpos]} { |
||||
set fd [open $out] |
||||
fconfigure $fd -translation binary |
||||
set outhead [read $fd $mkpos] |
||||
set origvfs [read $fd] |
||||
close $fd |
||||
|
||||
set fd [open $out w] |
||||
fconfigure $fd -translation binary |
||||
puts -nonewline $fd $outhead |
||||
close $fd |
||||
} |
||||
|
||||
vfs::m2m::Mount $out $out |
||||
|
||||
if {[info exists origvfs]} { |
||||
set fd [open $out.tmp w] |
||||
fconfigure $fd -translation binary |
||||
puts -nonewline $fd $origvfs |
||||
close $fd |
||||
|
||||
package require vfs::mkcl |
||||
vfs::mkcl::Mount $out.tmp $out.tmp |
||||
|
||||
set argv [list -verbose 0 $out.tmp $out] |
||||
source [file join [file dirname [info script]] sync.tcl] |
||||
|
||||
vfs::unmount $out.tmp |
||||
file delete $out.tmp |
||||
} |
||||
|
||||
set argv $syncopts |
||||
lappend argv -verbose $verbose -noerror 0 $idir $out |
||||
|
||||
source [file join [file dirname [info script]] sync.tcl] |
||||
|
||||
vfs::unmount $out |
||||
} else { |
||||
puts stderr "cannot find required packages (Mk4tcl or Vlerq)" |
||||
exit 1 |
||||
} |
||||
@ -0,0 +1,50 @@
|
||||
#accel_bench.tcl (G-100): tcllibc accelerator evidence under a suite-built shell. |
||||
#Hashes the same payload twice through tcllib's sha1 - once on the critcl |
||||
#accelerator (tcllibc), once on the pure-Tcl implementation - asserts the two |
||||
#digests match and prints the timings plus the speedup ratio. This is the |
||||
#punkcheck-relevant comparison (punkcheck hashing is the workload that made the |
||||
#accelerators worth building). |
||||
# |
||||
#Both implementations are made available with ::sha1::LoadAccelerator (the |
||||
#package itself stops loading at the FIRST working accelerator, so 'tcl' is |
||||
#normally not registered when critcl won) and selected with ::sha1::SwitchTo. |
||||
# |
||||
#args: ?-mb <payload megabytes>? (default 4) |
||||
|
||||
proc fail {msg} {puts stderr "accel_bench FAIL: $msg"; flush stderr; exit 1} |
||||
|
||||
set mb 4 |
||||
for {set i 0} {$i < [llength $argv]} {incr i} { |
||||
switch -- [lindex $argv $i] { |
||||
-mb {incr i; set mb [lindex $argv $i]} |
||||
default {fail "unknown argument: [lindex $argv $i]"} |
||||
} |
||||
} |
||||
|
||||
if {[catch {package require sha1} sha1ver]} {fail "package require sha1: $sha1ver"} |
||||
if {[catch {package require tcllibc} tcllibcver]} {fail "package require tcllibc: $tcllibcver"} |
||||
|
||||
if {![::sha1::LoadAccelerator critcl]} {fail "sha1 critcl accelerator not available (tcllibc $tcllibcver loaded but sha1c missing?)"} |
||||
if {![::sha1::LoadAccelerator tcl]} {fail "sha1 pure-tcl implementation not available"} |
||||
|
||||
#payload: incompressible-ish repeated block, built once, hashed by both |
||||
set block [string repeat "punkshell-suite_tcl86-accel-bench-0123456789abcdef" 1024] |
||||
set data "" |
||||
set target [expr {$mb * 1024 * 1024}] |
||||
while {[string length $data] < $target} {append data $block} |
||||
set bytes [string length $data] |
||||
|
||||
::sha1::SwitchTo critcl |
||||
set t_critcl [lindex [time {set d_critcl [::sha1::sha1 -hex -- $data]}] 0] |
||||
::sha1::SwitchTo tcl |
||||
set t_tcl [lindex [time {set d_tcl [::sha1::sha1 -hex -- $data]}] 0] |
||||
|
||||
if {$d_critcl ne $d_tcl} {fail "digest mismatch: critcl $d_critcl vs pure-tcl $d_tcl"} |
||||
if {$t_critcl <= 0} {set t_critcl 1} |
||||
|
||||
set speedup [format %.1f [expr {double($t_tcl) / double($t_critcl)}]] |
||||
set ms_critcl [format %.1f [expr {$t_critcl / 1000.0}]] |
||||
set ms_tcl [format %.1f [expr {$t_tcl / 1000.0}]] |
||||
puts "accel_bench OK: sha1 over $bytes bytes - critcl ${ms_critcl}ms vs pure-tcl ${ms_tcl}ms = ${speedup}x (digests identical, sha1 $sha1ver, tcllibc $tcllibcver)" |
||||
flush stdout |
||||
exit 0 |
||||
@ -0,0 +1,64 @@
|
||||
#tk_smoke.tcl (G-100): Tk window-station smoke under a suite-built shell. |
||||
#Goes beyond 'package require Tk' (a load-only check passes even when no usable |
||||
#display exists): it maps a real toplevel with a widget in it, forces a display |
||||
#update, then destroys it - the create/destroy-window verification the G-100 |
||||
#acceptance asks for, run on every build rather than once by hand. |
||||
# |
||||
#args: ?-expect <tk patchlevel>? |
||||
#Exits 1 with a 'tk_smoke FAIL:' line on any failure; prints one evidence line |
||||
#on success (version, screen geometry/depth, windowingsystem, widget classes). |
||||
|
||||
proc fail {msg} {puts stderr "tk_smoke FAIL: $msg"; flush stderr; exit 1} |
||||
|
||||
set expect {} |
||||
for {set i 0} {$i < [llength $argv]} {incr i} { |
||||
switch -- [lindex $argv $i] { |
||||
-expect {incr i; set expect [lindex $argv $i]} |
||||
default {fail "unknown argument: [lindex $argv $i]"} |
||||
} |
||||
} |
||||
|
||||
if {[catch {package require Tk} tkver]} {fail "package require Tk: $tkver"} |
||||
if {$expect ne "" && $tkver ne $expect} {fail "Tk version $tkver, expected $expect"} |
||||
if {[catch {package require Ttk} ttkver]} {set ttkver "-"} |
||||
|
||||
#the root window itself: geometry facts prove a real window station/display |
||||
if {[catch { |
||||
wm title . "tk_smoke" |
||||
wm geometry . 320x120+80+80 |
||||
set screen "[winfo screenwidth .]x[winfo screenheight .] depth [winfo screendepth .]" |
||||
set wsys [tk windowingsystem] |
||||
} err]} {fail "root window setup: $err"} |
||||
|
||||
#create: a classic widget, a themed widget and a child toplevel |
||||
if {[catch { |
||||
label .l -text "tk_smoke" |
||||
pack .l |
||||
ttk::button .b -text "ok" |
||||
pack .b |
||||
toplevel .t |
||||
wm title .t "tk_smoke child" |
||||
wm geometry .t 200x80+420+80 |
||||
label .t.l -text "child" |
||||
pack .t.l |
||||
update |
||||
} err]} {fail "widget create/map: $err"} |
||||
|
||||
foreach {label w} {root . classic .l themed .b child .t} { |
||||
if {![winfo ismapped $w]} {fail "window not mapped after update: $label ($w)"} |
||||
} |
||||
set classes [list [winfo class .l] [winfo class .b] [winfo class .t]] |
||||
|
||||
#destroy: the child toplevel first, then every root child - a clean teardown |
||||
if {[catch { |
||||
destroy .t |
||||
update |
||||
if {[winfo exists .t]} {fail "child toplevel survived destroy"} |
||||
destroy .l .b |
||||
update |
||||
if {[llength [winfo children .]]} {fail "root children survived destroy: [winfo children .]"} |
||||
} err]} {fail "widget destroy: $err"} |
||||
|
||||
puts "tk_smoke OK: Tk $tkver (Ttk $ttkver) windowingsystem $wsys screen $screen widgets [join $classes /] create+map+destroy clean" |
||||
flush stdout |
||||
exit 0 |
||||
Loading…
Reference in new issue