From 4da12e624b194d7b9b4fd9a5fd6bad04fdd76376 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Mon, 23 Feb 2026 00:23:06 +1100 Subject: [PATCH] first shot at enabling build when runtime being used is the same file as the one used to create a vfs (fix mounted tclkit path masking problem) --- src/make.tcl | 47 ++++++++++++++++--- .../custom/_project/punk.basic/src/make.tcl | 47 ++++++++++++++++--- .../_project/punk.project-0.1/src/make.tcl | 47 ++++++++++++++++--- .../_project/punk.shell-0.1/src/make.tcl | 47 ++++++++++++++++--- 4 files changed, 164 insertions(+), 24 deletions(-) diff --git a/src/make.tcl b/src/make.tcl index 5dc72254..b17de3e9 100644 --- a/src/make.tcl +++ b/src/make.tcl @@ -2447,6 +2447,17 @@ set rt_sourcefolder $sourcefolder/runtime ;#where our config lives #review - when building kits for other platforms - it's unlikely runtime will be marked as executable - we should probably process all files in runtime folder except those with certain extensions +if {[file dirname [info nameofexecutable]] eq $rtfolder} { + #fix so that we can find and use a runtime tclkit that is currently in use as the runtime that is running this script. + # - when the current runtime is using a runtime in the rtfolder that is a tclkit, it is mounted at the same path as the physical file and so appears to Tcl as if it's a directory. + # - use external filesystem tools to make a copy of the file + if {$::tcl_platform(platform) eq "windows"} { + exec cmd /c copy [info nameofexecutable] $rtfolder/[file rootname [info nameofexecutable]]_BUILDCOPY.exe + } else { + exec cp [info nameofexecutable] $rtfolder/[info nameofexecutable]_BUILDCOPY + } +} + set rtfolder_files [glob -nocomplain -dir $rtfolder -types {f} -tail *] set exclusions {.config .md .ico .txt .doc .pdf .htm .html} ;#we don't encourage other files in runtime folder aside from mapvfs.config - but lets ignore some common possibilities lappend exclusions .zip .7z .pea .bz2 .tar .gz .tgz .z .xz ;#don't allow archives to directly be treated as runtimes - tolerate presence but require user to unpack or rename if they're to be used as runtimes @@ -2575,7 +2586,7 @@ puts "---------------------" #only test the runtime capabilities for runtimes that are actually in our map -#how can we do this for runtimes from other platforms? +#how can we do this for runtimes from other platforms? #method1 try to mount as zip and kit - depends on current runtime to have mkzip - just because there is zip data doesn't mean the kit can mount it #method2 analyze executable to determine if its for another platform - then ask user and save answers in a config file.? #mthod3 qemu? @@ -2617,11 +2628,22 @@ foreach runtime [dict keys $runtime_vfs_map] { exit 0 } #invoke can fail if runtime not an executable file for the current platform + if {![file type $rtfolder/$runtime] eq "directory"} { + #assume it's a mounted tclkit (because tcl kits mount in same place as their underlying path and mask the executable) + #use the BUILDCOPY created above - REVIEW + if {$::tcl_platform(platform) eq "windows"} { + set useruntime [file rootname [file tail $runtime]]_BUILDCOPY.exe + } else { + set useruntime ${runtime}_BUILDCOPY + } + } else { + set useruntime $runtime + } if {![catch { - lassign [punk::lib::invoke [list $rtfolder/$runtime <<$capscript]] stdout stderr exitcode + lassign [punk::lib::invoke [list $rtfolder/$useruntime <<$capscript]] stdout stderr exitcode } errM]} { if {$exitcode == 0} { - dict set runtime_caps $runtime $stdout + dict set runtime_caps $runtime $stdout } dict set runtime_caps $runtime exitcode $exitcode } else { @@ -2657,6 +2679,18 @@ foreach runtimefile $runtimes { # file copy $rtfolder/$runtimefile $buildfolder/buildruntime.exe #} + if {![file type $rtfolder/$runtimefile] eq "directory"} { + #assume it's a mounted tclkit (because tcl kits mount in same place as their underlying path and mask the executable) + #use the BUILDCOPY created above - REVIEW + if {$::tcl_platform(platform) eq "windows"} { + set useruntime [file rootname [file tail $runtimefile]]_BUILDCOPY.exe + } else { + set useruntime ${runtimefile}_BUILDCOPY + } + } else { + set useruntime $runtimefile + } + set basedir $buildfolder set config [dict create\ -make-step copy_runtime\ @@ -2666,7 +2700,8 @@ foreach runtimefile $runtimes { $installer set_source_target $rtfolder $buildfolder set event [$installer start_event $config] $event targetset_init INSTALL $buildfolder/build_$runtimefile - $event targetset_addsource $rtfolder/$runtimefile + #$event targetset_addsource $rtfolder/$runtimefile + $event targetset_addsource $rtfolder/$useruntimefile ;#possibly the _BUILDCOPY in the runtime folder (created for when mounted in current executable as a tclkit) $event targetset_addsource $buildfolder/build_$runtimefile ;#self as source for change detection #---------- @@ -2678,9 +2713,9 @@ foreach runtimefile $runtimes { $event targetset_started # -- --- --- --- --- --- #This is the full runtime - *possibly* with some sort of vfs attached. - puts stdout "Copying runtime (as is) from $rtfolder/$runtimefile to $buildfolder/build_$runtimefile" + puts stdout "Copying runtime (as is) from $rtfolder/$useruntimefile to $buildfolder/build_$runtimefile" if {[catch { - file copy -force $rtfolder/$runtimefile $buildfolder/build_$runtimefile ;#becomes building_runtime + file copy -force $rtfolder/$useruntimefile $buildfolder/build_$runtimefile ;#becomes building_runtime } errM]} { puts stderr " >> copy runtime to $buildfolder/build_$runtimefile FAILED" $event targetset_end FAILED diff --git a/src/project_layouts/custom/_project/punk.basic/src/make.tcl b/src/project_layouts/custom/_project/punk.basic/src/make.tcl index 5dc72254..b17de3e9 100644 --- a/src/project_layouts/custom/_project/punk.basic/src/make.tcl +++ b/src/project_layouts/custom/_project/punk.basic/src/make.tcl @@ -2447,6 +2447,17 @@ set rt_sourcefolder $sourcefolder/runtime ;#where our config lives #review - when building kits for other platforms - it's unlikely runtime will be marked as executable - we should probably process all files in runtime folder except those with certain extensions +if {[file dirname [info nameofexecutable]] eq $rtfolder} { + #fix so that we can find and use a runtime tclkit that is currently in use as the runtime that is running this script. + # - when the current runtime is using a runtime in the rtfolder that is a tclkit, it is mounted at the same path as the physical file and so appears to Tcl as if it's a directory. + # - use external filesystem tools to make a copy of the file + if {$::tcl_platform(platform) eq "windows"} { + exec cmd /c copy [info nameofexecutable] $rtfolder/[file rootname [info nameofexecutable]]_BUILDCOPY.exe + } else { + exec cp [info nameofexecutable] $rtfolder/[info nameofexecutable]_BUILDCOPY + } +} + set rtfolder_files [glob -nocomplain -dir $rtfolder -types {f} -tail *] set exclusions {.config .md .ico .txt .doc .pdf .htm .html} ;#we don't encourage other files in runtime folder aside from mapvfs.config - but lets ignore some common possibilities lappend exclusions .zip .7z .pea .bz2 .tar .gz .tgz .z .xz ;#don't allow archives to directly be treated as runtimes - tolerate presence but require user to unpack or rename if they're to be used as runtimes @@ -2575,7 +2586,7 @@ puts "---------------------" #only test the runtime capabilities for runtimes that are actually in our map -#how can we do this for runtimes from other platforms? +#how can we do this for runtimes from other platforms? #method1 try to mount as zip and kit - depends on current runtime to have mkzip - just because there is zip data doesn't mean the kit can mount it #method2 analyze executable to determine if its for another platform - then ask user and save answers in a config file.? #mthod3 qemu? @@ -2617,11 +2628,22 @@ foreach runtime [dict keys $runtime_vfs_map] { exit 0 } #invoke can fail if runtime not an executable file for the current platform + if {![file type $rtfolder/$runtime] eq "directory"} { + #assume it's a mounted tclkit (because tcl kits mount in same place as their underlying path and mask the executable) + #use the BUILDCOPY created above - REVIEW + if {$::tcl_platform(platform) eq "windows"} { + set useruntime [file rootname [file tail $runtime]]_BUILDCOPY.exe + } else { + set useruntime ${runtime}_BUILDCOPY + } + } else { + set useruntime $runtime + } if {![catch { - lassign [punk::lib::invoke [list $rtfolder/$runtime <<$capscript]] stdout stderr exitcode + lassign [punk::lib::invoke [list $rtfolder/$useruntime <<$capscript]] stdout stderr exitcode } errM]} { if {$exitcode == 0} { - dict set runtime_caps $runtime $stdout + dict set runtime_caps $runtime $stdout } dict set runtime_caps $runtime exitcode $exitcode } else { @@ -2657,6 +2679,18 @@ foreach runtimefile $runtimes { # file copy $rtfolder/$runtimefile $buildfolder/buildruntime.exe #} + if {![file type $rtfolder/$runtimefile] eq "directory"} { + #assume it's a mounted tclkit (because tcl kits mount in same place as their underlying path and mask the executable) + #use the BUILDCOPY created above - REVIEW + if {$::tcl_platform(platform) eq "windows"} { + set useruntime [file rootname [file tail $runtimefile]]_BUILDCOPY.exe + } else { + set useruntime ${runtimefile}_BUILDCOPY + } + } else { + set useruntime $runtimefile + } + set basedir $buildfolder set config [dict create\ -make-step copy_runtime\ @@ -2666,7 +2700,8 @@ foreach runtimefile $runtimes { $installer set_source_target $rtfolder $buildfolder set event [$installer start_event $config] $event targetset_init INSTALL $buildfolder/build_$runtimefile - $event targetset_addsource $rtfolder/$runtimefile + #$event targetset_addsource $rtfolder/$runtimefile + $event targetset_addsource $rtfolder/$useruntimefile ;#possibly the _BUILDCOPY in the runtime folder (created for when mounted in current executable as a tclkit) $event targetset_addsource $buildfolder/build_$runtimefile ;#self as source for change detection #---------- @@ -2678,9 +2713,9 @@ foreach runtimefile $runtimes { $event targetset_started # -- --- --- --- --- --- #This is the full runtime - *possibly* with some sort of vfs attached. - puts stdout "Copying runtime (as is) from $rtfolder/$runtimefile to $buildfolder/build_$runtimefile" + puts stdout "Copying runtime (as is) from $rtfolder/$useruntimefile to $buildfolder/build_$runtimefile" if {[catch { - file copy -force $rtfolder/$runtimefile $buildfolder/build_$runtimefile ;#becomes building_runtime + file copy -force $rtfolder/$useruntimefile $buildfolder/build_$runtimefile ;#becomes building_runtime } errM]} { puts stderr " >> copy runtime to $buildfolder/build_$runtimefile FAILED" $event targetset_end FAILED diff --git a/src/project_layouts/custom/_project/punk.project-0.1/src/make.tcl b/src/project_layouts/custom/_project/punk.project-0.1/src/make.tcl index 5dc72254..b17de3e9 100644 --- a/src/project_layouts/custom/_project/punk.project-0.1/src/make.tcl +++ b/src/project_layouts/custom/_project/punk.project-0.1/src/make.tcl @@ -2447,6 +2447,17 @@ set rt_sourcefolder $sourcefolder/runtime ;#where our config lives #review - when building kits for other platforms - it's unlikely runtime will be marked as executable - we should probably process all files in runtime folder except those with certain extensions +if {[file dirname [info nameofexecutable]] eq $rtfolder} { + #fix so that we can find and use a runtime tclkit that is currently in use as the runtime that is running this script. + # - when the current runtime is using a runtime in the rtfolder that is a tclkit, it is mounted at the same path as the physical file and so appears to Tcl as if it's a directory. + # - use external filesystem tools to make a copy of the file + if {$::tcl_platform(platform) eq "windows"} { + exec cmd /c copy [info nameofexecutable] $rtfolder/[file rootname [info nameofexecutable]]_BUILDCOPY.exe + } else { + exec cp [info nameofexecutable] $rtfolder/[info nameofexecutable]_BUILDCOPY + } +} + set rtfolder_files [glob -nocomplain -dir $rtfolder -types {f} -tail *] set exclusions {.config .md .ico .txt .doc .pdf .htm .html} ;#we don't encourage other files in runtime folder aside from mapvfs.config - but lets ignore some common possibilities lappend exclusions .zip .7z .pea .bz2 .tar .gz .tgz .z .xz ;#don't allow archives to directly be treated as runtimes - tolerate presence but require user to unpack or rename if they're to be used as runtimes @@ -2575,7 +2586,7 @@ puts "---------------------" #only test the runtime capabilities for runtimes that are actually in our map -#how can we do this for runtimes from other platforms? +#how can we do this for runtimes from other platforms? #method1 try to mount as zip and kit - depends on current runtime to have mkzip - just because there is zip data doesn't mean the kit can mount it #method2 analyze executable to determine if its for another platform - then ask user and save answers in a config file.? #mthod3 qemu? @@ -2617,11 +2628,22 @@ foreach runtime [dict keys $runtime_vfs_map] { exit 0 } #invoke can fail if runtime not an executable file for the current platform + if {![file type $rtfolder/$runtime] eq "directory"} { + #assume it's a mounted tclkit (because tcl kits mount in same place as their underlying path and mask the executable) + #use the BUILDCOPY created above - REVIEW + if {$::tcl_platform(platform) eq "windows"} { + set useruntime [file rootname [file tail $runtime]]_BUILDCOPY.exe + } else { + set useruntime ${runtime}_BUILDCOPY + } + } else { + set useruntime $runtime + } if {![catch { - lassign [punk::lib::invoke [list $rtfolder/$runtime <<$capscript]] stdout stderr exitcode + lassign [punk::lib::invoke [list $rtfolder/$useruntime <<$capscript]] stdout stderr exitcode } errM]} { if {$exitcode == 0} { - dict set runtime_caps $runtime $stdout + dict set runtime_caps $runtime $stdout } dict set runtime_caps $runtime exitcode $exitcode } else { @@ -2657,6 +2679,18 @@ foreach runtimefile $runtimes { # file copy $rtfolder/$runtimefile $buildfolder/buildruntime.exe #} + if {![file type $rtfolder/$runtimefile] eq "directory"} { + #assume it's a mounted tclkit (because tcl kits mount in same place as their underlying path and mask the executable) + #use the BUILDCOPY created above - REVIEW + if {$::tcl_platform(platform) eq "windows"} { + set useruntime [file rootname [file tail $runtimefile]]_BUILDCOPY.exe + } else { + set useruntime ${runtimefile}_BUILDCOPY + } + } else { + set useruntime $runtimefile + } + set basedir $buildfolder set config [dict create\ -make-step copy_runtime\ @@ -2666,7 +2700,8 @@ foreach runtimefile $runtimes { $installer set_source_target $rtfolder $buildfolder set event [$installer start_event $config] $event targetset_init INSTALL $buildfolder/build_$runtimefile - $event targetset_addsource $rtfolder/$runtimefile + #$event targetset_addsource $rtfolder/$runtimefile + $event targetset_addsource $rtfolder/$useruntimefile ;#possibly the _BUILDCOPY in the runtime folder (created for when mounted in current executable as a tclkit) $event targetset_addsource $buildfolder/build_$runtimefile ;#self as source for change detection #---------- @@ -2678,9 +2713,9 @@ foreach runtimefile $runtimes { $event targetset_started # -- --- --- --- --- --- #This is the full runtime - *possibly* with some sort of vfs attached. - puts stdout "Copying runtime (as is) from $rtfolder/$runtimefile to $buildfolder/build_$runtimefile" + puts stdout "Copying runtime (as is) from $rtfolder/$useruntimefile to $buildfolder/build_$runtimefile" if {[catch { - file copy -force $rtfolder/$runtimefile $buildfolder/build_$runtimefile ;#becomes building_runtime + file copy -force $rtfolder/$useruntimefile $buildfolder/build_$runtimefile ;#becomes building_runtime } errM]} { puts stderr " >> copy runtime to $buildfolder/build_$runtimefile FAILED" $event targetset_end FAILED diff --git a/src/project_layouts/custom/_project/punk.shell-0.1/src/make.tcl b/src/project_layouts/custom/_project/punk.shell-0.1/src/make.tcl index 5dc72254..b17de3e9 100644 --- a/src/project_layouts/custom/_project/punk.shell-0.1/src/make.tcl +++ b/src/project_layouts/custom/_project/punk.shell-0.1/src/make.tcl @@ -2447,6 +2447,17 @@ set rt_sourcefolder $sourcefolder/runtime ;#where our config lives #review - when building kits for other platforms - it's unlikely runtime will be marked as executable - we should probably process all files in runtime folder except those with certain extensions +if {[file dirname [info nameofexecutable]] eq $rtfolder} { + #fix so that we can find and use a runtime tclkit that is currently in use as the runtime that is running this script. + # - when the current runtime is using a runtime in the rtfolder that is a tclkit, it is mounted at the same path as the physical file and so appears to Tcl as if it's a directory. + # - use external filesystem tools to make a copy of the file + if {$::tcl_platform(platform) eq "windows"} { + exec cmd /c copy [info nameofexecutable] $rtfolder/[file rootname [info nameofexecutable]]_BUILDCOPY.exe + } else { + exec cp [info nameofexecutable] $rtfolder/[info nameofexecutable]_BUILDCOPY + } +} + set rtfolder_files [glob -nocomplain -dir $rtfolder -types {f} -tail *] set exclusions {.config .md .ico .txt .doc .pdf .htm .html} ;#we don't encourage other files in runtime folder aside from mapvfs.config - but lets ignore some common possibilities lappend exclusions .zip .7z .pea .bz2 .tar .gz .tgz .z .xz ;#don't allow archives to directly be treated as runtimes - tolerate presence but require user to unpack or rename if they're to be used as runtimes @@ -2575,7 +2586,7 @@ puts "---------------------" #only test the runtime capabilities for runtimes that are actually in our map -#how can we do this for runtimes from other platforms? +#how can we do this for runtimes from other platforms? #method1 try to mount as zip and kit - depends on current runtime to have mkzip - just because there is zip data doesn't mean the kit can mount it #method2 analyze executable to determine if its for another platform - then ask user and save answers in a config file.? #mthod3 qemu? @@ -2617,11 +2628,22 @@ foreach runtime [dict keys $runtime_vfs_map] { exit 0 } #invoke can fail if runtime not an executable file for the current platform + if {![file type $rtfolder/$runtime] eq "directory"} { + #assume it's a mounted tclkit (because tcl kits mount in same place as their underlying path and mask the executable) + #use the BUILDCOPY created above - REVIEW + if {$::tcl_platform(platform) eq "windows"} { + set useruntime [file rootname [file tail $runtime]]_BUILDCOPY.exe + } else { + set useruntime ${runtime}_BUILDCOPY + } + } else { + set useruntime $runtime + } if {![catch { - lassign [punk::lib::invoke [list $rtfolder/$runtime <<$capscript]] stdout stderr exitcode + lassign [punk::lib::invoke [list $rtfolder/$useruntime <<$capscript]] stdout stderr exitcode } errM]} { if {$exitcode == 0} { - dict set runtime_caps $runtime $stdout + dict set runtime_caps $runtime $stdout } dict set runtime_caps $runtime exitcode $exitcode } else { @@ -2657,6 +2679,18 @@ foreach runtimefile $runtimes { # file copy $rtfolder/$runtimefile $buildfolder/buildruntime.exe #} + if {![file type $rtfolder/$runtimefile] eq "directory"} { + #assume it's a mounted tclkit (because tcl kits mount in same place as their underlying path and mask the executable) + #use the BUILDCOPY created above - REVIEW + if {$::tcl_platform(platform) eq "windows"} { + set useruntime [file rootname [file tail $runtimefile]]_BUILDCOPY.exe + } else { + set useruntime ${runtimefile}_BUILDCOPY + } + } else { + set useruntime $runtimefile + } + set basedir $buildfolder set config [dict create\ -make-step copy_runtime\ @@ -2666,7 +2700,8 @@ foreach runtimefile $runtimes { $installer set_source_target $rtfolder $buildfolder set event [$installer start_event $config] $event targetset_init INSTALL $buildfolder/build_$runtimefile - $event targetset_addsource $rtfolder/$runtimefile + #$event targetset_addsource $rtfolder/$runtimefile + $event targetset_addsource $rtfolder/$useruntimefile ;#possibly the _BUILDCOPY in the runtime folder (created for when mounted in current executable as a tclkit) $event targetset_addsource $buildfolder/build_$runtimefile ;#self as source for change detection #---------- @@ -2678,9 +2713,9 @@ foreach runtimefile $runtimes { $event targetset_started # -- --- --- --- --- --- #This is the full runtime - *possibly* with some sort of vfs attached. - puts stdout "Copying runtime (as is) from $rtfolder/$runtimefile to $buildfolder/build_$runtimefile" + puts stdout "Copying runtime (as is) from $rtfolder/$useruntimefile to $buildfolder/build_$runtimefile" if {[catch { - file copy -force $rtfolder/$runtimefile $buildfolder/build_$runtimefile ;#becomes building_runtime + file copy -force $rtfolder/$useruntimefile $buildfolder/build_$runtimefile ;#becomes building_runtime } errM]} { puts stderr " >> copy runtime to $buildfolder/build_$runtimefile FAILED" $event targetset_end FAILED