@ -2368,8 +2368,141 @@ pub fn build(b: *std.Build) !void {
\\
\\
;
;
const tkb = tk_build . ? ; / / windows target ( checked just above )
const tkb = tk_build . ? ; / / windows target ( checked just above )
var family_tree_base : [ 2 ] std . Build . LazyPath = undefined ;
/ / default 2 : r1 of every ( 9.0 . 5 , variant ) pair was PUBLISHED to punkbin
for ( 0 . . 2 ) | ti | { / / 0 = core payload ( plain + punk ) , 1 = bi payload
/ / 2026 - 07 - 22 and is immutable - subsequent assemblies ( first content
/ / change : tclvfs forTcl9 / 1.5 . 0 ) emit as r2 until r2 is itself published
/ / and superseded . Bump this default whenever the current rev publishes .
const familyrev = b . option ( u32 , " familyrev " , " assembly revision N for the -r<N> family artifact names (kit-family-artifacts; default 2 - r1 published 2026-07-22) " ) orelse 2 ;
/ / G - 117 schema v1 identity options . origin = canonical artifact repo the
/ / artifacts are BUILT FOR ( not necessarily where they end up hosted -
/ / mirrors preserve it ) . packager = declared identity , resolution chain
/ / - Dpackager > env PUNKBIN_PACKAGER > building checkout ' s git identity >
/ / " unrecorded " ( declarative , not proof - signing is the verification layer ) .
const originurl = b . option ( [ ] const u8 , " originurl " , " canonical artifact repo url the family artifacts are built FOR ('origin' field; default punkbin) " ) orelse " https://www.gitea1.intx.com.au/jn/punkbin " ;
const projecturl = b . option ( [ ] const u8 , " projecturl " , " project url recorded in the artifact records ('project_url' field; default unrecorded) " ) orelse " unrecorded " ;
const packager = blk : {
if ( b . option ( [ ] const u8 , " packager " , " declared packager identity for the artifact records (-Dpackager > env PUNKBIN_PACKAGER > git identity > unrecorded) " ) ) | p | break : blk p ;
if ( b . graph . environ_map . get ( " PUNKBIN_PACKAGER " ) ) | p | {
if ( p . len ! = 0 ) break : blk p ;
}
var gc : u8 = undefined ;
const gname : ? [ ] const u8 = b . runAllowFail ( & . { " git " , " config " , " user.name " } , & gc , . ignore ) catch null ;
if ( gname ! = null and gc = = 0 ) {
const nm = std . mem . trim ( u8 , gname . ? , " \t \r \n " ) ;
if ( nm . len ! = 0 ) {
const gmail : ? [ ] const u8 = b . runAllowFail ( & . { " git " , " config " , " user.email " } , & gc , . ignore ) catch null ;
if ( gmail ! = null and gc = = 0 ) {
const em = std . mem . trim ( u8 , gmail . ? , " \t \r \n " ) ;
if ( em . len ! = 0 ) break : blk b . fmt ( " {s} <{s}> " , . { nm , em } ) ;
}
break : blk nm ;
}
}
break : blk " unrecorded " ;
} ;
const FamilyKit = struct {
variant : [ ] const u8 ,
working_name : [ ] const u8 ,
prefix_exe : * std . Build . Step . Compile ,
tree : usize ,
} ;
const family_kits = [ _ ] FamilyKit {
. { . variant = " plain " , . working_name = b . fmt ( " tclsh{s}.exe " , . { tcl_h_patchlevel } ) , . prefix_exe = tclsh_exe , . tree = 0 } ,
. { . variant = " punk " , . working_name = b . fmt ( " tclsh{s}-punk.exe " , . { tcl_h_patchlevel } ) , . prefix_exe = tclsh_pr_exe , . tree = 0 } ,
. { . variant = " punk-bi " , . working_name = b . fmt ( " tclsh{s}-punk-bi.exe " , . { tcl_h_patchlevel } ) , . prefix_exe = tclsh_pr_exe , . tree = 1 } ,
} ;
/ / source checkout uuids ( also consumed by kit - family - artifacts below )
const uuid_tcl = common . manifestUuid ( b , tcl_source_folder ) ;
const uuid_thread = common . manifestUuid ( b , " ../tclthread " ) ;
const uuid_tclvfs = common . manifestUuid ( b , " ../tclvfs " ) ;
const uuid_tk = common . manifestUuid ( b , " ../tk9 " ) ;
const uuid_tcllib = common . manifestUuid ( b , " ../tcllib " ) ;
const uuid_tklib = common . manifestUuid ( b , " ../tklib " ) ;
/ / G - 117 : per - member EMBEDDED artifact record ( schema v1 ) , staged into each
/ / member ' s payload tree as base / punkbin - artifact . toml ( namespaced so a
/ / future G - 025 kit - stamp file can coexist ; the record survives make . tcl
/ / kit wrapping , which overlays without clearing ) . Finished - binary facts
/ / ( sha1 , size , built ) stay SIDECAR - ONLY : embed - then - hash ordering , no
/ / circularity - the sidecar + sha1sums . txt remain the integrity authority .
/ / build_id is a uuid - shaped sha1 digest over stable identity inputs
/ / ( artifact name incl - r < N > , toolchain / optimize , patchlevel , the member ' s
/ / source - checkout uuids ) - deterministic so the zig cache holds across
/ / configures ; a correlation key , not an integrity key .
var family_records : [ family_kits . len ] [ ] const u8 = undefined ;
for ( family_kits , 0 . . ) | fk , ki | {
const kbi = fk . tree = = 1 ;
const wroot = fk . working_name [ 0 . . fk . working_name . len - 4 ] ; / / strip " .exe " ( windows branch )
const artifact_name = b . fmt ( " {s}-r{d}.exe " , . { wroot , familyrev } ) ;
const prov_seed = if ( kbi )
b . fmt ( " tcl {s} thread {s} tclvfs {s} tcllib {s} tk {s} tklib {s} " , . { uuid_tcl , uuid_thread , uuid_tclvfs , uuid_tcllib , uuid_tk , uuid_tklib } )
else
b . fmt ( " tcl {s} thread {s} tclvfs {s} tcllib {s} " , . { uuid_tcl , uuid_thread , uuid_tclvfs , uuid_tcllib } ) ;
var idigest : [ 20 ] u8 = undefined ;
std . crypto . hash . Sha1 . hash ( b . fmt ( " punkbin-artifact|{s}|zig {s}|{s}|tcl{s}|{s} " , . { artifact_name , builtin . zig_version_string , @tagName ( optimize ) , tcl_h_patchlevel , prov_seed } ) , & idigest , . { } ) ;
const ihex = std . fmt . bytesToHex ( idigest , . lower ) ;
const build_id = b . fmt ( " {s}-{s}-{s}-{s}-{s} " , . { ihex [ 0 . . 8 ] , ihex [ 8 . . 12 ] , ihex [ 12 . . 16 ] , ihex [ 16 . . 20 ] , ihex [ 20 . . 32 ] } ) ;
const batteries = if ( kbi )
b . fmt ( " [ \" Thread {s} \" , \" vfs {s} \" , \" tcllib {s} \" , \" tcllibc {s} \" , \" Tk {s} \" , \" tklib {s} \" ] " , . { thread_build . version , tclvfs_info . dotversion , tcllib_ver , tcllib_ver , tkb . patchlevel , tklib_ver } )
else
b . fmt ( " [ \" Thread {s} \" , \" vfs {s} \" , \" tcllib {s} \" , \" tcllibc {s} \" ] " , . { thread_build . version , tclvfs_info . dotversion , tcllib_ver , tcllib_ver } ) ;
const piperepl_block : [ ] const u8 = if ( std . mem . eql ( u8 , fk . variant , " plain " ) )
" piperepl = false "
else
" piperepl = true \n piperepl_default = \" on \" \n piperepl_opt_out = \" TCLSH_PIPEREPL=0 \" " ;
const prov_lines = if ( kbi )
b . fmt ( " tcl_checkout = \" {s} \" \n thread_checkout = \" {s} \" \n tclvfs_checkout = \" {s} \" \n tk_checkout = \" {s} \" \n tcllib_checkout = \" {s} \" \n tklib_checkout = \" {s} \" " , . { uuid_tcl , uuid_thread , uuid_tclvfs , uuid_tk , uuid_tcllib , uuid_tklib } )
else
b . fmt ( " tcl_checkout = \" {s} \" \n thread_checkout = \" {s} \" \n tclvfs_checkout = \" {s} \" \n tcllib_checkout = \" {s} \" " , . { uuid_tcl , uuid_thread , uuid_tclvfs , uuid_tcllib } ) ;
family_records [ ki ] = b . fmt (
\\#punkshell runtime artifact metadata - EMBEDDED copy (G-117 schema v1),
\\#written at kit-family staging. Finished-binary facts (sha1, size, built)
\\#live only in the sidecar toml + sha1sums.txt, which remain the integrity
\\#authority; this copy makes a stray or renamed runtime self-describing.
\\schema = 1
\\
\\[artifact]
\\name = "{s}"
\\class = "runtime"
\\variant = "{s}"
\\working_name = "{s}"
\\revision = {d}
\\target = "win32-x86_64"
\\#build_id: offline correlation key re-joining a renamed copy to its record;
\\#identical in embedded and sidecar copies. Uuid-shaped digest of stable
\\#identity inputs (deterministic) - not an integrity key.
\\build_id = "{s}"
\\#origin: canonical artifact repo this artifact was BUILT FOR - not
\\#necessarily where it is hosted; mirrors preserve it.
\\origin = "{s}"
\\#packager: declared identity, not proof - signing (minisign sidecars)
\\#is the verification layer.
\\packager = "{s}"
\\project = "punkshell"
\\project_url = "{s}"
\\#license: summary for the distributed artifact; component license texts
\\#ride inside the attached image (tcl_library/license.terms etc).
\\license = "TCL"
\\build_host_platform = "win32-x86_64"
\\
\\[runtime]
\\tcl_patchlevel = "{s}"
\\{s}
\\attached_batteries = {s}
\\
\\[provenance]
\\suite = "suite_tcl90"
\\toolchain = "zig {s}"
\\optimize = "{s}"
\\{s}
\\
, . { artifact_name , fk . variant , fk . working_name , familyrev , build_id , originurl , packager , projecturl , tcl_h_patchlevel , piperepl_block , batteries , builtin . zig_version_string , @tagName ( optimize ) , prov_lines } ) ;
}
var family_tree_base : [ family_kits . len ] std . Build . LazyPath = undefined ;
for ( family_kits , 0 . . ) | fk , ki | { / / per - member payload tree : shared content + the member ' s embedded record
const famwf = b . addWriteFiles ( ) ;
const famwf = b . addWriteFiles ( ) ;
/ / core script library at the boot position ( tzdata / encoding ride
/ / core script library at the boot position ( tzdata / encoding ride
/ / inside the source library tree ) , dde / registry dlls inside
/ / inside the source library tree ) , dde / registry dlls inside
@ -2383,32 +2516,22 @@ pub fn build(b: *std.Build) !void {
}
}
/ / package - search hook for the lib / tree
/ / package - search hook for the lib / tree
_ = famwf . add ( " base/lib/pkgIndex.tcl " , family_libext_pkgindex ) ;
_ = famwf . add ( " base/lib/pkgIndex.tcl " , family_libext_pkgindex ) ;
/ / G - 117 embedded artifact record ( per - member ; see the record block above )
_ = famwf . add ( " base/punkbin-artifact.toml " , family_records [ ki ] ) ;
/ / batteries ( installed shape )
/ / batteries ( installed shape )
try tclvfs_shared . familyadd_tclvfs_package ( " ../tclvfs " , b , famwf , b . fmt ( " base/lib/vfs{s} " , . { tclvfs_info . dotversion } ) , tclvfs_compile ) ;
try tclvfs_shared . familyadd_tclvfs_package ( " ../tclvfs " , b , famwf , b . fmt ( " base/lib/vfs{s} " , . { tclvfs_info . dotversion } ) , tclvfs_compile ) ;
_ = famwf . addCopyFile ( thread_build . pkgidx , b . fmt ( " base/lib/thread{s}/pkgIndex.tcl " , . { thread_build . version } ) ) ;
_ = famwf . addCopyFile ( thread_build . pkgidx , b . fmt ( " base/lib/thread{s}/pkgIndex.tcl " , . { thread_build . version } ) ) ;
_ = famwf . addCopyFile ( thread_build . lib . getEmittedBin ( ) , b . fmt ( " base/bin/{s} " , . { thread_build . dll_file } ) ) ;
_ = famwf . addCopyFile ( thread_build . lib . getEmittedBin ( ) , b . fmt ( " base/bin/{s} " , . { thread_build . dll_file } ) ) ;
_ = famwf . addCopyDirectory ( tcllib_out , b . fmt ( " base/lib/tcllib{s} " , . { tcllib_ver } ) , . { } ) ;
_ = famwf . addCopyDirectory ( tcllib_out , b . fmt ( " base/lib/tcllib{s} " , . { tcllib_ver } ) , . { } ) ;
_ = famwf . addCopyDirectory ( critcl_libout , " base/lib " , . { } ) ; / / carries tcllibc /
_ = famwf . addCopyDirectory ( critcl_libout , " base/lib " , . { } ) ; / / carries tcllibc /
if ( ti = = 1 ) {
if ( fk . tree = = 1 ) {
_ = famwf . addCopyDirectory ( b . path ( " ../tk9/library " ) , b . fmt ( " base/lib/{s} " , . { tkb . libdir } ) , . { } ) ;
_ = famwf . addCopyDirectory ( b . path ( " ../tk9/library " ) , b . fmt ( " base/lib/{s} " , . { tkb . libdir } ) , . { } ) ;
_ = famwf . addCopyFile ( tkb . pkgidx , b . fmt ( " base/lib/{s}/pkgIndex.tcl " , . { tkb . libdir } ) ) ;
_ = famwf . addCopyFile ( tkb . pkgidx , b . fmt ( " base/lib/{s}/pkgIndex.tcl " , . { tkb . libdir } ) ) ;
_ = famwf . addCopyFile ( tkb . lib . getEmittedBin ( ) , b . fmt ( " base/bin/{s} " , . { tkb . dll_file } ) ) ;
_ = famwf . addCopyFile ( tkb . lib . getEmittedBin ( ) , b . fmt ( " base/bin/{s} " , . { tkb . dll_file } ) ) ;
_ = famwf . addCopyDirectory ( tklib_out , b . fmt ( " base/lib/tklib{s} " , . { tklib_ver } ) , . { } ) ;
_ = famwf . addCopyDirectory ( tklib_out , b . fmt ( " base/lib/tklib{s} " , . { tklib_ver } ) , . { } ) ;
}
}
family_tree_base [ t i] = fam_tcl_library . dirname ( ) ;
family_tree_base [ k i] = fam_tcl_library . dirname ( ) ;
}
}
const FamilyKit = struct {
variant : [ ] const u8 ,
working_name : [ ] const u8 ,
prefix_exe : * std . Build . Step . Compile ,
tree : usize ,
} ;
const family_kits = [ _ ] FamilyKit {
. { . variant = " plain " , . working_name = b . fmt ( " tclsh{s}.exe " , . { tcl_h_patchlevel } ) , . prefix_exe = tclsh_exe , . tree = 0 } ,
. { . variant = " punk " , . working_name = b . fmt ( " tclsh{s}-punk.exe " , . { tcl_h_patchlevel } ) , . prefix_exe = tclsh_pr_exe , . tree = 0 } ,
. { . variant = " punk-bi " , . working_name = b . fmt ( " tclsh{s}-punk-bi.exe " , . { tcl_h_patchlevel } ) , . prefix_exe = tclsh_pr_exe , . tree = 1 } ,
} ;
var family_checks : [ family_kits . len ] * std . Build . Step = undefined ;
var family_checks : [ family_kits . len ] * std . Build . Step = undefined ;
var family_installed : [ family_kits . len ] [ ] const u8 = undefined ;
var family_installed : [ family_kits . len ] [ ] const u8 = undefined ;
for ( family_kits , 0 . . ) | fk , ki | {
for ( family_kits , 0 . . ) | fk , ki | {
@ -2419,9 +2542,9 @@ pub fn build(b: *std.Build) !void {
wrap . addArg ( " -outfile " ) ;
wrap . addArg ( " -outfile " ) ;
const wrapped = wrap . addOutputFileArg ( fk . working_name ) ;
const wrapped = wrap . addOutputFileArg ( fk . working_name ) ;
wrap . addArg ( " -indir " ) ;
wrap . addArg ( " -indir " ) ;
wrap . addDirectoryArg ( family_tree_base [ fk . tree ] ) ;
wrap . addDirectoryArg ( family_tree_base [ ki ] ) ;
wrap . addArg ( " -strip " ) ;
wrap . addArg ( " -strip " ) ;
wrap . addDirectoryArg ( family_tree_base [ fk . tree ] ) ;
wrap . addDirectoryArg ( family_tree_base [ ki ] ) ;
wrap . addArg ( " -infile " ) ;
wrap . addArg ( " -infile " ) ;
wrap . addArtifactArg ( fk . prefix_exe ) ;
wrap . addArtifactArg ( fk . prefix_exe ) ;
const inst = b . addInstallFileWithDir ( wrapped , . prefix , b . fmt ( " family/{s} " , . { fk . working_name } ) ) ;
const inst = b . addInstallFileWithDir ( wrapped , . prefix , b . fmt ( " family/{s} " , . { fk . working_name } ) ) ;
@ -2452,19 +2575,10 @@ pub fn build(b: *std.Build) !void {
/ / family runtime executes real tooling from its attached batteries .
/ / family runtime executes real tooling from its attached batteries .
/ / Depends on the checks : only verified kits get artifact records .
/ / Depends on the checks : only verified kits get artifact records .
/ / Publication to the real punkbin repo stays a deliberate user step .
/ / Publication to the real punkbin repo stays a deliberate user step .
/ / default 2 : r1 of every ( 9.0 . 5 , variant ) pair was PUBLISHED to punkbin
/ / ( familyrev + the schema v1 identity options and checkout uuids are
/ / 2026 - 07 - 22 and is immutable - subsequent assemblies ( first content
/ / declared above with the family staging - the embedded records need them )
/ / change : tclvfs forTcl9 / 1.5 . 0 ) emit as r2 until r2 is itself published
/ / and superseded . Bump this default whenever the current rev publishes .
const familyrev = b . option ( u32 , " familyrev " , " assembly revision N for the -r<N> family artifact names (kit-family-artifacts; default 2 - r1 published 2026-07-22) " ) orelse 2 ;
const family_artifacts_step = b . step ( " kit-family-artifacts " , " emit punkbin-layout artifact copies (-r<N>) + toml metadata + sha1sums for the verified family kits -> <prefix>/family/punkbin/<target> " ) ;
const family_artifacts_step = b . step ( " kit-family-artifacts " , " emit punkbin-layout artifact copies (-r<N>) + toml metadata + sha1sums for the verified family kits -> <prefix>/family/punkbin/<target> " ) ;
const artifacts_outdir = common . replaceAll ( b , b . pathJoin ( & . { b . install_path , " family " , " punkbin " , " win32-x86_64 " } ) , " \\ " , " / " ) ;
const artifacts_outdir = common . replaceAll ( b , b . pathJoin ( & . { b . install_path , " family " , " punkbin " , " win32-x86_64 " } ) , " \\ " , " / " ) ;
const uuid_tcl = common . manifestUuid ( b , tcl_source_folder ) ;
const uuid_thread = common . manifestUuid ( b , " ../tclthread " ) ;
const uuid_tclvfs = common . manifestUuid ( b , " ../tclvfs " ) ;
const uuid_tk = common . manifestUuid ( b , " ../tk9 " ) ;
const uuid_tcllib = common . manifestUuid ( b , " ../tcllib " ) ;
const uuid_tklib = common . manifestUuid ( b , " ../tklib " ) ;
const emit = b . addSystemCommand ( & . { family_installed [ 0 ] } ) ;
const emit = b . addSystemCommand ( & . { family_installed [ 0 ] } ) ;
common . scrubTclEnv ( emit ) ;
common . scrubTclEnv ( emit ) ;
emit . has_side_effects = true ;
emit . has_side_effects = true ;