• ANNOUNCE: tcl-sfe - statically linked Tcl 9.1b0 +packages build system and binaries for Windows

    From Ashok@apnmbx-public@yahoo.com to comp.lang.tcl on Sat Jul 4 08:32:49 2026
    From Newsgroup: comp.lang.tcl

    Downloads: https://github.com/apnadkarni/tcl-sfe/releases
    Repository: https://github.com/apnadkarni/tcl-sfe
    Docs: https://github.com/apnadkarni/tcl-sfe/blob/main/README.md

    This repository hosts single file executables (SFE) of Tcl/Tk for
    Windows and a build system to create and customize them. These are
    completely statically linked (other than the C and Windows runtimes) and therefore avoid issues that arise from similar single file executables
    that write shared libraries to disk.

    The `tclsfe.exe` and `tksfe.exe` programs are enhanced versions of
    `tclsh.exe` and `wish.exe` that include the following extensions by
    default:


    - thread
    - sqlite3
    - tdbc::odbc
    - twapi

    The build system allows omission of any of these if smaller executables
    are desired. Further, SFE's can be customized by adding

    - additional packages or Tcl modules

    - interpreter initalization scripts

    - a main script that implements a complete application

    - statically linked extensions

    Only the last customization needs a compiler.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Colin Macleod@user7@newsgrouper.org.invalid to comp.lang.tcl on Sat Jul 4 08:14:08 2026
    From Newsgroup: comp.lang.tcl

    Ashok <apnmbx-public@yahoo.com> posted:

    Downloads: https://github.com/apnadkarni/tcl-sfe/releases
    Repository: https://github.com/apnadkarni/tcl-sfe
    Docs: https://github.com/apnadkarni/tcl-sfe/blob/main/README.md

    This repository hosts single file executables (SFE) of Tcl/Tk for
    Windows and a build system to create and customize them. These are
    completely statically linked (other than the C and Windows runtimes) and therefore avoid issues that arise from similar single file executables
    that write shared libraries to disk.

    Good to see! Efai
    --
    Colin Macleod ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ https://cmacleod.me.uk

    FEED HOUSE SAVE FEED HOUSE SAVE FEED HOUSE SAVE
    GAZA GAZA GAZA GAZA GAZA GAZA GAZA GAZA GAZA
    NOW! NOW! NOW! NOW! NOW! NOW! NOW! NOW! NOW!
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Olivier@user1108@newsgrouper.org.invalid to comp.lang.tcl on Sun Jul 5 17:28:00 2026
    From Newsgroup: comp.lang.tcl


    Ashok <apnmbx-public@yahoo.com> posted:

    Thank you ! Your contributions and explanations (as in your book),
    to the construction of single file executables are priceless for a
    user that has not the knowledge to dive into the compilation step.

    Olivier
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Sun Jul 5 13:59:03 2026
    From Newsgroup: comp.lang.tcl



    Wow, this is fantastic Ashok!

    I downloaded tksfe.exe and since I already had a magicsplat 9.0.2 in a side directory, I tried the following command:

    sfe::make newsingle.exe {*}[lmap d [glob -directory {D:/magic/Tcl902/lib} -types d *] {if {[file tail $d] in {tcl9}} continue ; set d}]

    This built a 34-megabyte single file executable. Note the suppression of the tcl9 directory, which had previously given an error:

    VFS path A:/temp/tcl_9XK4MHMB/tcl9 exists and either A:/temp/tcl_9XK4MHMB/tcl9
    or D:/magic/Tcl902/lib/tcl9 is a directory.

    I then went through every package with a .dll I could find and ran package require on each of them, verifying via Process Explorer that the DLL really did get copied out to the temp directory rather than being found some other way.

    The only failure I found was:

    % package require Blend2d
    couldn't load from current filesystem

    This works fine against a plain disk install of Tcl902, so something about the SFE/zipfs environment trips it up.

    I also tested that I could create another single file .exe from the first one I created with all the packages included. Here I simply added a main.tcl, and that worked.

    The only thing I'm wondering is when a new tcl/tk release comes out, it would be handy to accept a .exe as a path argument to be able to read the prior sfe and propagate everything into a new tcl/tk release. So, for example, this should be able to update an existing sfe quite easily:

    > tksfe.exe (a new version)
    % package require sfe
    % sfe::make newsingleV2.exe newsingle.exe

    Your sfe is a great way to create a fully batteries-included single file executable!!!

    Outstanding work!

    Eric




    On 7/3/2026 8:02 PM, Ashok wrote:
    Downloads: https://github.com/apnadkarni/tcl-sfe/releases
    Repository: https://github.com/apnadkarni/tcl-sfe
    Docs: https://github.com/apnadkarni/tcl-sfe/blob/main/README.md

    This repository hosts single file executables (SFE) of Tcl/Tk for
    Windows and a build system to create and customize them. These are
    completely statically linked (other than the C and Windows runtimes) and therefore avoid issues that arise from similar single file executables
    that write shared libraries to disk.

    The `tclsfe.exe` and `tksfe.exe` programs are enhanced versions of `tclsh.exe` and `wish.exe` that include the following extensions by
    default:


    - thread
    - sqlite3
    - tdbc::odbc
    - twapi

    The build system allows omission of any of these if smaller executables
    are desired. Further, SFE's can be customized by adding

    - additional packages or Tcl modules

    - interpreter initalization scripts

    - a main script that implements a complete application

    - statically linked extensions

    Only the last customization needs a compiler.




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Sun Jul 5 19:23:52 2026
    From Newsgroup: comp.lang.tcl

    I thought I would take a stab at adding a feature to Ashok's sfe, since I get to play with zips and some OO code. So, I added an option, "-exe filename" and a helper function to do the work:

    method addFromSfe {exePath} {
    # Merges the package content of another SFE into this VFS, skipping
    # any top-level entry that already exists (so the current base
    # runtime's own bundled packages always take precedence over
    # same-named ones carried in from an older SFE).
    set mnt //zipfs:/sfemerge_[pid]
    zipfs mount $exePath $mnt
    try {
    set vfsDir [my getVfsDir]
    foreach srcPath [glob [file join $mnt *]] {
    set destPath [file join $vfsDir [file tail $srcPath]]
    if {[file exists $destPath]} {
    puts stderr "Note: skipping [file tail $srcPath] from $exePath - already present from base runtime."
    continue
    }
    file copy -force -- $srcPath $vfsDir
    }
    } finally {
    zipfs unmount $mnt
    }
    }


    proc sfe::make {outPath args} {
    # Creates a new single-file executable from the current one with the
    # addition of paths. If a path is a directory, it is copied along with
    # its content to the top level of the vfs. If an ordinary file, it is
    # copied to a directory in Tcl module path if it has a .tm extension
    # or the top level of the vfs. A path preceded by -exe is treated as
    # a prior SFE whose package content should be merged in; -exe may
    # appear any number of times, in any position, in the argument list.
    set sfe [SfeMaker new]
    try {
    set expectExe 0

    foreach arg $args {
    if {$expectExe} {
    $sfe addFromSfe [file normalize $arg]
    set expectExe 0
    continue
    }
    if {$arg eq "-exe"} {
    set expectExe 1
    continue
    }
    set path [file normalize $arg]
    set type [file type $path]

    switch $type {
    directory {
    $sfe addPackage $path
    }
    file {
    if {[string equal -nocase [file extension $path] ".tm"]} {
    $sfe addModule $path
    } else {
    $sfe addPath $path [file tail $path]
    }
    }
    default {
    puts stderr "Warning: Skipping $path of type $type."
    }
    }
    }
    if {$expectExe} {
    error "-exe requires a following path argument."
    }
    $sfe buildSfe $outPath
    } finally {
    $sfe destroy
    }
    }



    On 7/5/2026 1:59 PM, et99 wrote:


    Wow, this is fantastic Ashok!

    I downloaded tksfe.exe and since I already had a magicsplat 9.0.2 in a side directory, I tried the following command:

    -a-a sfe::make newsingle.exe {*}[lmap d [glob -directory {D:/magic/Tcl902/lib} -types d *] {if {[file tail $d] in {tcl9}} continue ; set d}]

    This built a 34-megabyte single file executable. Note the suppression of the tcl9 directory, which had previously given an error:

    -a-a-a VFS path A:/temp/tcl_9XK4MHMB/tcl9 exists and either A:/temp/tcl_9XK4MHMB/tcl9
    -a-a-a or D:/magic/Tcl902/lib/tcl9 is a directory.

    I then went through every package with a .dll I could find and ran package require on each of them, verifying via Process Explorer that the DLL really did get copied out to the temp directory rather than being found some other way.

    The only failure I found was:

    -a-a-a % package require Blend2d
    -a-a-a couldn't load from current filesystem

    This works fine against a plain disk install of Tcl902, so something about the SFE/zipfs environment trips it up.

    I also tested that I could create another single file .exe from the first one I created with all the packages included. Here I simply added a main.tcl, and that worked.

    The only thing I'm wondering is when a new tcl/tk release comes out, it would be handy to accept a .exe as a path argument to be able to read the prior sfe and propagate everything into a new tcl/tk release. So, for example, this should be able to update an existing sfe quite easily:

    -a-a-a > tksfe.exe (a new version)
    -a-a-a-a-a % package require sfe
    -a-a-a-a-a % sfe::make newsingleV2.exe newsingle.exe

    Your sfe is a great way to create a fully batteries-included single file executable!!!

    Outstanding work!

    Eric




    On 7/3/2026 8:02 PM, Ashok wrote:
    Downloads: https://github.com/apnadkarni/tcl-sfe/releases
    Repository: https://github.com/apnadkarni/tcl-sfe
    Docs: https://github.com/apnadkarni/tcl-sfe/blob/main/README.md

    This repository hosts single file executables (SFE) of Tcl/Tk for
    Windows and a build system to create and customize them. These are
    completely statically linked (other than the C and Windows runtimes) and
    therefore avoid issues that arise from similar single file executables
    that write shared libraries to disk.

    The `tclsfe.exe` and `tksfe.exe` programs are enhanced versions of
    `tclsh.exe` and `wish.exe` that include the following extensions by
    default:


    - thread
    - sqlite3
    - tdbc::odbc
    - twapi

    The build system allows omission of any of these if smaller executables
    are desired. Further, SFE's can be customized by adding

    - additional packages or Tcl modules

    - interpreter initalization scripts

    - a main script that implements a complete application

    - statically linked extensions

    Only the last customization needs a compiler.





    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Ashok@apnmbx-public@yahoo.com to comp.lang.tcl on Mon Jul 6 12:10:29 2026
    From Newsgroup: comp.lang.tcl

    Eric,

    Thanks for testing!

    Yes, the Tcl9 suppression is required because overwriting of directories
    is explicitly rejected, to avoid confusion between target directories overlapping. Since sfe itself already has Tcl 9 script files, that is a conflict if you try to add external Tcl 9 core scripts.

    The Blend2d failure is probably not specific to sfe but rather the same
    issue with embedded DLL's being dependent on other DLL's in any
    zipkit/tclkit system. They have to be explicitly copied out to disk.

    BTW, note that adding packages that include binary extensions means they
    are written out to disk. In that case, you might as well be using any zipkit/tclkit. The uniqueness of tclsfe is only static linking.

    Regarding copying over of files for new releases, currently there is no tracking of which files came from Tcl and which came from extensions. I
    think the simpler solution is just to have a script that adds packages
    that you can then run every time a new tclsfe based on a new Tcl release
    comes out.

    On 7/6/2026 2:29 AM, et99 wrote:


    Wow, this is fantastic Ashok!

    I downloaded tksfe.exe and since I already had a magicsplat 9.0.2 in a
    side directory, I tried the following command:

    -a-a sfe::make newsingle.exe {*}[lmap d [glob -directory {D:/magic/ Tcl902/lib} -types d *] {if {[file tail $d] in {tcl9}} continue ; set d}]

    This built a 34-megabyte single file executable. Note the suppression of
    the tcl9 directory, which had previously given an error:

    -a-a-a VFS path A:/temp/tcl_9XK4MHMB/tcl9 exists and either A:/temp/ tcl_9XK4MHMB/tcl9
    -a-a-a or D:/magic/Tcl902/lib/tcl9 is a directory.

    I then went through every package with a .dll I could find and ran
    package require on each of them, verifying via Process Explorer that the
    DLL really did get copied out to the temp directory rather than being
    found some other way.

    The only failure I found was:

    -a-a-a % package require Blend2d
    -a-a-a couldn't load from current filesystem

    This works fine against a plain disk install of Tcl902, so something
    about the SFE/zipfs environment trips it up.

    I also tested that I could create another single file .exe from the
    first one I created with all the packages included. Here I simply added
    a main.tcl, and that worked.

    The only thing I'm wondering is when a new tcl/tk release comes out, it would be handy to accept a .exe as a path argument to be able to read
    the prior sfe and propagate everything into a new tcl/tk release. So,
    for example, this should be able to update an existing sfe quite easily:

    -a-a-a > tksfe.exe (a new version)
    -a-a-a-a-a % package require sfe
    -a-a-a-a-a % sfe::make newsingleV2.exe newsingle.exe

    Your sfe is a great way to create a fully batteries-included single file executable!!!

    Outstanding work!

    Eric




    On 7/3/2026 8:02 PM, Ashok wrote:
    Downloads: https://github.com/apnadkarni/tcl-sfe/releases
    Repository: https://github.com/apnadkarni/tcl-sfe
    Docs: https://github.com/apnadkarni/tcl-sfe/blob/main/README.md

    This repository hosts single file executables (SFE) of Tcl/Tk for
    Windows and a build system to create and customize them. These are
    completely statically linked (other than the C and Windows runtimes) and
    therefore avoid issues that arise from similar single file executables
    that write shared libraries to disk.

    The `tclsfe.exe` and `tksfe.exe` programs are enhanced versions of
    `tclsh.exe` and `wish.exe` that include the following extensions by
    default:


    - thread
    - sqlite3
    - tdbc::odbc
    - twapi

    The build system allows omission of any of these if smaller executables
    are desired. Further, SFE's can be customized by adding

    - additional packages or Tcl modules

    - interpreter initalization scripts

    - a main script that implements a complete application

    - statically linked extensions

    Only the last customization needs a compiler.





    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Ashok@apnmbx-public@yahoo.com to comp.lang.tcl on Mon Jul 6 12:13:38 2026
    From Newsgroup: comp.lang.tcl

    Yeah, this might work :-)

    On 7/6/2026 7:53 AM, et99 wrote:
    I thought I would take a stab at adding a feature to Ashok's sfe, since
    I get to play with zips and some OO code. So, I added an option, "-exe filename" and a helper function to do the work:

    -a-a-a method addFromSfe {exePath} {
    -a-a-a-a-a-a-a # Merges the package content of another SFE into this VFS, skipping
    -a-a-a-a-a-a-a # any top-level entry that already exists (so the current base
    -a-a-a-a-a-a-a # runtime's own bundled packages always take precedence over
    -a-a-a-a-a-a-a # same-named ones carried in from an older SFE).
    -a-a-a-a-a-a-a set mnt //zipfs:/sfemerge_[pid]
    -a-a-a-a-a-a-a zipfs mount $exePath $mnt
    -a-a-a-a-a-a-a try {
    -a-a-a-a-a-a-a-a-a-a-a set vfsDir [my getVfsDir]
    -a-a-a-a-a-a-a-a-a-a-a foreach srcPath [glob [file join $mnt *]] {
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a set destPath [file join $vfsDir [file tail $srcPath]]
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a if {[file exists $destPath]} {
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a puts stderr "Note: skipping [file tail $srcPath]
    from $exePath - already present from base runtime."
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a continue
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a file copy -force -- $srcPath $vfsDir
    -a-a-a-a-a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a } finally {
    -a-a-a-a-a-a-a-a-a-a-a zipfs unmount $mnt
    -a-a-a-a-a-a-a }
    -a-a-a }


    proc sfe::make {outPath args} {
    -a-a-a # Creates a new single-file executable from the current one with the
    -a-a-a # addition of paths. If a path is a directory, it is copied along with
    -a-a-a # its content to the top level of the vfs. If an ordinary file, it is
    -a-a-a # copied to a directory in Tcl module path if it has a .tm extension
    -a-a-a # or the top level of the vfs. A path preceded by -exe is treated as
    -a-a-a # a prior SFE whose package content should be merged in; -exe may
    -a-a-a # appear any number of times, in any position, in the argument list.
    -a-a-a set sfe [SfeMaker new]
    -a-a-a try {
    -a-a-a-a-a-a-a set expectExe 0

    -a-a-a-a-a-a-a foreach arg $args {
    -a-a-a-a-a-a-a-a-a-a-a if {$expectExe} {
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a $sfe addFromSfe [file normalize $arg]
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a set expectExe 0
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a continue
    -a-a-a-a-a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a-a-a-a-a if {$arg eq "-exe"} {
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a set expectExe 1
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a continue
    -a-a-a-a-a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a-a-a-a-a set path [file normalize $arg]
    -a-a-a-a-a-a-a-a-a-a-a set type [file type $path]

    -a-a-a-a-a-a-a-a-a-a-a switch $type {
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a directory {
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a $sfe addPackage $path
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a file {
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a if {[string equal -nocase [file extension $path]
    ".tm"]} {
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a $sfe addModule $path
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a } else {
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a $sfe addPath $path [file tail $path]
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a default {
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a puts stderr "Warning: Skipping $path of type $type."
    -a-a-a-a-a-a-a-a-a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a if {$expectExe} {
    -a-a-a-a-a-a-a-a-a-a-a error "-exe requires a following path argument."
    -a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a $sfe buildSfe $outPath
    -a-a-a } finally {
    -a-a-a-a-a-a-a $sfe destroy
    -a-a-a }
    }



    On 7/5/2026 1:59 PM, et99 wrote:


    Wow, this is fantastic Ashok!

    I downloaded tksfe.exe and since I already had a magicsplat 9.0.2 in a
    side directory, I tried the following command:

    -a-a-a sfe::make newsingle.exe {*}[lmap d [glob -directory {D:/magic/
    Tcl902/lib} -types d *] {if {[file tail $d] in {tcl9}} continue ; set d}]

    This built a 34-megabyte single file executable. Note the suppression
    of the tcl9 directory, which had previously given an error:

    -a-a-a-a VFS path A:/temp/tcl_9XK4MHMB/tcl9 exists and either A:/temp/
    tcl_9XK4MHMB/tcl9
    -a-a-a-a or D:/magic/Tcl902/lib/tcl9 is a directory.

    I then went through every package with a .dll I could find and ran
    package require on each of them, verifying via Process Explorer that
    the DLL really did get copied out to the temp directory rather than
    being found some other way.

    The only failure I found was:

    -a-a-a-a % package require Blend2d
    -a-a-a-a couldn't load from current filesystem

    This works fine against a plain disk install of Tcl902, so something
    about the SFE/zipfs environment trips it up.

    I also tested that I could create another single file .exe from the
    first one I created with all the packages included. Here I simply
    added a main.tcl, and that worked.

    The only thing I'm wondering is when a new tcl/tk release comes out,
    it would be handy to accept a .exe as a path argument to be able to
    read the prior sfe and propagate everything into a new tcl/tk release.
    So, for example, this should be able to update an existing sfe quite
    easily:

    -a-a-a-a > tksfe.exe (a new version)
    -a-a-a-a-a-a % package require sfe
    -a-a-a-a-a-a % sfe::make newsingleV2.exe newsingle.exe

    Your sfe is a great way to create a fully batteries-included single
    file executable!!!

    Outstanding work!

    Eric




    On 7/3/2026 8:02 PM, Ashok wrote:
    Downloads: https://github.com/apnadkarni/tcl-sfe/releases
    Repository: https://github.com/apnadkarni/tcl-sfe
    Docs: https://github.com/apnadkarni/tcl-sfe/blob/main/README.md

    This repository hosts single file executables (SFE) of Tcl/Tk for
    Windows and a build system to create and customize them. These are
    completely statically linked (other than the C and Windows runtimes) and >>> therefore avoid issues that arise from similar single file executables
    that write shared libraries to disk.

    The `tclsfe.exe` and `tksfe.exe` programs are enhanced versions of
    `tclsh.exe` and `wish.exe` that include the following extensions by
    default:


    - thread
    - sqlite3
    - tdbc::odbc
    - twapi

    The build system allows omission of any of these if smaller executables
    are desired. Further, SFE's can be customized by adding

    - additional packages or Tcl modules

    - interpreter initalization scripts

    - a main script that implements a complete application

    - statically linked extensions

    Only the last customization needs a compiler.






    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Mon Jul 6 08:17:25 2026
    From Newsgroup: comp.lang.tcl

    Ashok,

    Thanks - on Blend2d, a quick look at its pkgIndex.tcl shows it uses a
    custom BL::_findDLL proc to locate the DLL rather than a plain
    load [file join $dir name.dll] call. That non-standard load might be
    what's causing the failure, though I haven't confirmed it further.

    Otherwise - really appreciate how much simpler this is than the qwrap/unwrap/wrap zipkit approach I (and I'd guess others) have been
    using. Not needing a static wish/tclsh build or an MSVC install is a
    big win.

    On that note, with -exe, someone with an existing SFE -
    however it was built, even something well short of a full
    batteries-included one - could update its Tcl/Tk core straight from
    your next release without needing to track down or reassemble any of
    the packages it already contains, no magicsplat distro or compiler
    required.

    Eric




    On 7/5/2026 11:40 PM, Ashok wrote:
    Eric,

    Thanks for testing!

    Yes, the Tcl9 suppression is required because overwriting of directories is explicitly rejected, to avoid confusion between target directories overlapping. Since sfe itself already has Tcl 9 script files, that is a conflict if you try to add external Tcl 9 core scripts.

    The Blend2d failure is probably not specific to sfe but rather the same issue with embedded DLL's being dependent on other DLL's in any zipkit/tclkit system. They have to be explicitly copied out to disk.

    BTW, note that adding packages that include binary extensions means they are written out to disk. In that case, you might as well be using any zipkit/tclkit. The uniqueness of tclsfe is only static linking.

    Regarding copying over of files for new releases, currently there is no tracking of which files came from Tcl and which came from extensions. I think the simpler solution is just to have a script that adds packages that you can then run every time a new tclsfe based on a new Tcl release comes out.

    On 7/6/2026 2:29 AM, et99 wrote:


    Wow, this is fantastic Ashok!

    I downloaded tksfe.exe and since I already had a magicsplat 9.0.2 in a side directory, I tried the following command:

    -a-a-a sfe::make newsingle.exe {*}[lmap d [glob -directory {D:/magic/ Tcl902/lib} -types d *] {if {[file tail $d] in {tcl9}} continue ; set d}]

    This built a 34-megabyte single file executable. Note the suppression of the tcl9 directory, which had previously given an error:

    -a-a-a-a VFS path A:/temp/tcl_9XK4MHMB/tcl9 exists and either A:/temp/ tcl_9XK4MHMB/tcl9
    -a-a-a-a or D:/magic/Tcl902/lib/tcl9 is a directory.

    I then went through every package with a .dll I could find and ran package require on each of them, verifying via Process Explorer that the DLL really did get copied out to the temp directory rather than being found some other way.

    The only failure I found was:

    -a-a-a-a % package require Blend2d
    -a-a-a-a couldn't load from current filesystem

    This works fine against a plain disk install of Tcl902, so something about the SFE/zipfs environment trips it up.

    I also tested that I could create another single file .exe from the first one I created with all the packages included. Here I simply added a main.tcl, and that worked.

    The only thing I'm wondering is when a new tcl/tk release comes out, it would be handy to accept a .exe as a path argument to be able to read the prior sfe and propagate everything into a new tcl/tk release. So, for example, this should be able to update an existing sfe quite easily:

    -a-a-a-a > tksfe.exe (a new version)
    -a-a-a-a-a-a % package require sfe
    -a-a-a-a-a-a % sfe::make newsingleV2.exe newsingle.exe

    Your sfe is a great way to create a fully batteries-included single file executable!!!

    Outstanding work!

    Eric




    On 7/3/2026 8:02 PM, Ashok wrote:
    Downloads: https://github.com/apnadkarni/tcl-sfe/releases
    Repository: https://github.com/apnadkarni/tcl-sfe
    Docs: https://github.com/apnadkarni/tcl-sfe/blob/main/README.md

    This repository hosts single file executables (SFE) of Tcl/Tk for
    Windows and a build system to create and customize them. These are
    completely statically linked (other than the C and Windows runtimes) and >>> therefore avoid issues that arise from similar single file executables
    that write shared libraries to disk.

    The `tclsfe.exe` and `tksfe.exe` programs are enhanced versions of
    `tclsh.exe` and `wish.exe` that include the following extensions by
    default:


    - thread
    - sqlite3
    - tdbc::odbc
    - twapi

    The build system allows omission of any of these if smaller executables
    are desired. Further, SFE's can be customized by adding

    - additional packages or Tcl modules

    - interpreter initalization scripts

    - a main script that implements a complete application

    - statically linked extensions

    Only the last customization needs a compiler.






    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Ashok@apnmbx-public@yahoo.com to comp.lang.tcl on Wed Jul 8 12:03:39 2026
    From Newsgroup: comp.lang.tcl

    v0.2 release

    - added x86 binaries
    - -icon option for modifying the icon
    - -version option for customizing version resource (version, company and product name etc.)

    Eric, I thought about also adding your code. But I still see a potential
    for conflicts. For example, the new SFE might contain a newer version of
    a package. Copying missing entries from an older SFE may copy older
    versions of the package (because directories are versioned by many
    packages) creating a runtime conflict. It would be a useful feature but
    have to think about it a bit more.

    /Ashok

    On 7/4/2026 8:32 AM, Ashok wrote:
    Downloads: https://github.com/apnadkarni/tcl-sfe/releases
    Repository: https://github.com/apnadkarni/tcl-sfe
    Docs: https://github.com/apnadkarni/tcl-sfe/blob/main/README.md

    This repository hosts single file executables (SFE) of Tcl/Tk for
    Windows and a build system to create and customize them. These are
    completely statically linked (other than the C and Windows runtimes) and therefore avoid issues that arise from similar single file executables
    that write shared libraries to disk.

    The `tclsfe.exe` and `tksfe.exe` programs are enhanced versions of `tclsh.exe` and `wish.exe` that include the following extensions by
    default:


    - thread
    - sqlite3
    - tdbc::odbc
    - twapi

    The build system allows omission of any of these if smaller executables
    are desired. Further, SFE's can be customized by adding

    - additional packages or Tcl modules

    - interpreter initalization scripts

    - a main script that implements a complete application

    - statically linked extensions

    Only the last customization needs a compiler.




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Wed Jul 8 19:36:08 2026
    From Newsgroup: comp.lang.tcl

    Ashok,

    The icon is a nice addition.

    Fair point on my -exe idea. What if instead, we just allow an export - the code below
    is roughly what I'm thinking:

    This sidesteps the versioning problem you raised entirely - nothing the
    tool has to get right on the person's behalf. Usage would be something
    like:

    sfe::export oldrelease.exe C:/staging/old_packages

    Here's how that might then be re-imported after the user goes over the directory and removes anything stale or unwanted - maybe with a new
    -allof option so they don't have to glob it themselves:

    sfe::make newrelease.exe -allof C:/staging/old_packages



    proc sfe::export {exePath outDir {force ""}} {
    # Extracts the package content of an SFE to a plain directory on
    # disk, so specific packages can be inspected and selectively fed
    # back into sfe::make. outDir must not already exist, or must be
    # empty, unless force is "force".
    set exePath [file normalize $exePath]
    if {![file isfile $exePath]} {
    error "\"$exePath\" is not a file."
    }
    if {[string tolower [file extension $exePath]] ne ".exe"} {
    error "\"$exePath\" does not have a .exe extension."
    }

    set outDir [file normalize $outDir]
    if {[file exists $outDir]} {
    if {![file isdirectory $outDir]} {
    error "\"$outDir\" exists and is not a directory."
    }
    if {$force ne "force" && [llength [glob -nocomplain -directory $outDir *]]} {
    error "\"$outDir\" is not empty. Use \"force\" to reuse it anyway."
    }
    } else {
    file mkdir $outDir
    }

    set mnt //zipfs:/sfeexport_[pid]
    zipfs mount $exePath $mnt
    try {
    file copy -force -- {*}[glob [file join $mnt *]] $outDir
    } finally {
    zipfs unmount $mnt
    }
    }




    Eric


    On 7/7/2026 11:33 PM, Ashok wrote:
    v0.2 release

    - added x86 binaries
    - -icon option for modifying the icon
    - -version option for customizing version resource (version, company and product name etc.)

    Eric, I thought about also adding your code. But I still see a potential for conflicts. For example, the new SFE might contain a newer version of a package. Copying missing entries from an older SFE may copy older versions of the package (because directories are versioned by many packages) creating a runtime conflict. It would be a useful feature but have to think about it a bit more.

    /Ashok

    On 7/4/2026 8:32 AM, Ashok wrote:
    Downloads: https://github.com/apnadkarni/tcl-sfe/releases
    Repository: https://github.com/apnadkarni/tcl-sfe
    Docs: https://github.com/apnadkarni/tcl-sfe/blob/main/README.md

    This repository hosts single file executables (SFE) of Tcl/Tk for
    Windows and a build system to create and customize them. These are
    completely statically linked (other than the C and Windows runtimes) and
    therefore avoid issues that arise from similar single file executables
    that write shared libraries to disk.

    The `tclsfe.exe` and `tksfe.exe` programs are enhanced versions of
    `tclsh.exe` and `wish.exe` that include the following extensions by
    default:


    - thread
    - sqlite3
    - tdbc::odbc
    - twapi

    The build system allows omission of any of these if smaller executables
    are desired. Further, SFE's can be customized by adding

    - additional packages or Tcl modules

    - interpreter initalization scripts

    - a main script that implements a complete application

    - statically linked extensions

    Only the last customization needs a compiler.





    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From et99@et99@rocketship1.me to comp.lang.tcl on Wed Jul 8 22:57:27 2026
    From Newsgroup: comp.lang.tcl

    On 7/8/2026 7:36 PM, et99 wrote:

    The icon is a nice addition.


    Hi Ashok,

    I tested the new -icon <file> flag rCo it embeds the icon as a PE resource correctly. It shows on the taskbar, however, the titlebar icon on the toplevel windows still shows Tk's default icon.

    The fix that worked for me: in main.tcl, where I also added a file app.ico along side of it,

    wm iconbitmap . -default //zipfs:/app/app.ico

    This gets all toplevels, including the console, current and later created windows.

    I also verified setting a couple -version fields.

    Thanks again for this wonderful resource,

    Eric

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Ashok@apnmbx-public@yahoo.com to comp.lang.tcl on Mon Jul 13 10:13:26 2026
    From Newsgroup: comp.lang.tcl

    I've added a ticket to take a look the next time I work on sfe - https://github.com/apnadkarni/tcl-sfe/issues/5

    On 7/9/2026 8:06 AM, et99 wrote:
    Ashok,

    The icon is a nice addition.

    Fair point on my -exe idea. What if instead, we just allow an export -
    the code below
    is roughly what I'm thinking:

    This sidesteps the versioning problem you raised entirely - nothing the
    tool has to get right on the person's behalf. Usage would be something
    like:

    -a-a-a sfe::export oldrelease.exe C:/staging/old_packages

    Here's how that might then be re-imported after the user goes over the directory and removes anything stale or unwanted - maybe with a new
    -allof option so they don't have to glob it themselves:

    -a-a-a sfe::make newrelease.exe -allof C:/staging/old_packages



    proc sfe::export {exePath outDir {force ""}} {
    -a-a-a # Extracts the package content of an SFE to a plain directory on
    -a-a-a # disk, so specific packages can be inspected and selectively fed
    -a-a-a # back into sfe::make. outDir must not already exist, or must be
    -a-a-a # empty, unless force is "force".
    -a-a-a set exePath [file normalize $exePath]
    -a-a-a if {![file isfile $exePath]} {
    -a-a-a-a-a-a-a error "\"$exePath\" is not a file."
    -a-a-a }
    -a-a-a if {[string tolower [file extension $exePath]] ne ".exe"} {
    -a-a-a-a-a-a-a error "\"$exePath\" does not have a .exe extension."
    -a-a-a }

    -a-a-a set outDir [file normalize $outDir]
    -a-a-a if {[file exists $outDir]} {
    -a-a-a-a-a-a-a if {![file isdirectory $outDir]} {
    -a-a-a-a-a-a-a-a-a-a-a error "\"$outDir\" exists and is not a directory."
    -a-a-a-a-a-a-a }
    -a-a-a-a-a-a-a if {$force ne "force" && [llength [glob -nocomplain -directory
    $outDir *]]} {
    -a-a-a-a-a-a-a-a-a-a-a error "\"$outDir\" is not empty. Use \"force\" to reuse it
    anyway."
    -a-a-a-a-a-a-a }
    -a-a-a } else {
    -a-a-a-a-a-a-a file mkdir $outDir
    -a-a-a }

    -a-a-a set mnt //zipfs:/sfeexport_[pid]
    -a-a-a zipfs mount $exePath $mnt
    -a-a-a try {
    -a-a-a-a-a-a-a file copy -force -- {*}[glob [file join $mnt *]] $outDir
    -a-a-a } finally {
    -a-a-a-a-a-a-a zipfs unmount $mnt
    -a-a-a }
    }




    Eric


    On 7/7/2026 11:33 PM, Ashok wrote:
    v0.2 release

    - added x86 binaries
    - -icon option for modifying the icon
    - -version option for customizing version resource (version, company
    and product name etc.)

    Eric, I thought about also adding your code. But I still see a
    potential for conflicts. For example, the new SFE might contain a
    newer version of a package. Copying missing entries from an older SFE
    may copy older versions of the package (because directories are
    versioned by many packages) creating a runtime conflict. It would be a
    useful feature but have to think about it a bit more.

    /Ashok

    On 7/4/2026 8:32 AM, Ashok wrote:
    Downloads: https://github.com/apnadkarni/tcl-sfe/releases
    Repository: https://github.com/apnadkarni/tcl-sfe
    Docs: https://github.com/apnadkarni/tcl-sfe/blob/main/README.md

    This repository hosts single file executables (SFE) of Tcl/Tk for
    Windows and a build system to create and customize them. These are
    completely statically linked (other than the C and Windows runtimes) and >>> therefore avoid issues that arise from similar single file executables
    that write shared libraries to disk.

    The `tclsfe.exe` and `tksfe.exe` programs are enhanced versions of
    `tclsh.exe` and `wish.exe` that include the following extensions by
    default:


    - thread
    - sqlite3
    - tdbc::odbc
    - twapi

    The build system allows omission of any of these if smaller executables
    are desired. Further, SFE's can be customized by adding

    - additional packages or Tcl modules

    - interpreter initalization scripts

    - a main script that implements a complete application

    - statically linked extensions

    Only the last customization needs a compiler.






    --- Synchronet 3.22a-Linux NewsLink 1.2