Browse Source

G-033: proj: package-mode scope prefix - visitor binary resolves dev/src against the cwd's project

punk_main.tcl: an optional proj: prefix on the package-mode string
(e.g 'proj:internal-src') rebinds the dev/src path blocks to the punk
project containing the current directory instead of the executable's
own project. Root discovery is ::punkboot::proj_root_find, a lean
boot mirror of punk::repo::find_project/is_project_root in Tcl
builtins only (git/fossil control markers via 'file exists', unwise-
path exclusion, ./src plus src/modules|src/vfs|src/scriptapps|
punkproject.toml candidate check; .git accepted as file OR dir for
worktree checkouts - recorded divergence). The proc stays defined
post-boot like the G-129 mount procs. The prefix sits outside the
ordered dash-list, whose block order remains the same-version
tie-break dial; an invalid mode remainder is not consumed (whole arg
falls through as subcommand/script as today); bare 'proj:' reads as
internal and warns. Discovery outcome is always reported on stderr
(detected root + effective precedence - never a silent rebind), a
failed walk-up warns and leaves dev/src unbound (no exe-relative
fallback rebind), and proj: without a dev/src block warns it has no
effect. Under proj:, dev resolves <root>/modules{,_tclN} and
<root>/lib{,_tclN} only; src feeds the discovered root into the
existing src-mode machinery unchanged (tm paths, auto_path, package
prefer latest, inline #modpod scanner). Exe-relative src/dev launches
are untouched.

punk::args::moduledoc::punkexe 0.1.1: the packagemode help text
drafted in the goal file is now live as the packagemode leader of
(script)::punkexe (@leaders max 2), with proj: wording in the @cmd
overview; rendering/parse wiring remains G-032.

Verified on a rebaked punk91 kit, standalone copy outside any source
tree: proj:internal-src from tomlish (fossil root, builds no
executable) loads tomlish 999999.0a1.0 from its src/modules with
kit-first ties; proj:src flips the ordering; from punkshell the
visited-root modpod scan registers 6 modpods; no-project and
no-root-using-block warnings fire and proceed; bin/punk91 src
unchanged.

Docs: bin/AGENTS.md launch-package-modes proj: contract,
src/vfs/AGENTS.md punk_main contract line, ARCHITECTURE.md entry
point. punkshell 0.29.0 (minor - new launch invocation) + CHANGELOG.

Claude-Session: https://claude.ai/code/session_0156PuejSCGjgeGb7jiABrDU
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
Julian Noble 2 days ago
parent
commit
768dab399f
  1. 4
      ARCHITECTURE.md
  2. 15
      CHANGELOG.md
  3. 8
      bin/AGENTS.md
  4. 2
      punkproject.toml
  5. 38
      src/modules/punk/args/moduledoc/punkexe-999999.0a1.0.tm
  6. 2
      src/modules/punk/args/moduledoc/punkexe-buildversion.txt
  7. 2
      src/vfs/AGENTS.md
  8. 125
      src/vfs/_config/punk_main.tcl

4
ARCHITECTURE.md

@ -42,7 +42,7 @@ app package from src/lib/ (app-punkshell, app-punkscript, app-repl, app-shellsp
## Boot and launch chain
- **Kit anatomy.** Each `src/vfs/*.vfs` folder is a runtime payload; `src/runtime/mapvfs.config` maps payload folders to platform runtimes under `bin/runtime/<platform>/`; `src/vfs/_vfscommon.vfs/` is a generated merge of common libraries (never hand-edited); `src/vfs/_config/` holds the entry scripts. Sources: `src/vfs/AGENTS.md`, `src/runtime/AGENTS.md`.
- **Entry point.** `src/vfs/_config/punk_main.tcl`. An optional first argument is a dash-delimited package mode composed of tokens from `dev`, `os`, `src`, `internal` (`internal` is always appended when absent). The next argument is the subcommand: `shell`, `script`, `punk`, `tclsh`, `shellspy`. Any other first argument is treated as a script invocation; no arguments at all means interactive shell. Subcommands map to app packages under `src/lib/` (`app-punkshell`, `app-punkscript`, `app-repl`, `app-shellspy`).
- **Entry point.** `src/vfs/_config/punk_main.tcl`. An optional first argument is a dash-delimited package mode composed of tokens from `dev`, `os`, `src`, `internal` (`internal` is always appended when absent), optionally scoped with the `proj:` prefix (G-033: `dev`/`src` resolve against the project containing the cwd - walk-up to the nearest git/fossil repo root with a punkshell-style src tree - instead of the executable's own project; discovery is always reported, never a silent rebind). The next argument is the subcommand: `shell`, `script`, `punk`, `tclsh`, `shellspy`. Any other first argument is treated as a script invocation; no arguments at all means interactive shell. Subcommands map to app packages under `src/lib/` (`app-punkshell`, `app-punkscript`, `app-repl`, `app-shellspy`).
- **Package modes pick module provenance.** `internal` uses module snapshots baked into the kit at build time; `dev` loads build outputs from repo-root `modules/` and `lib/`; `src` loads the unbuilt working tree (`src/modules`, `src/lib`, `src/bootsupport`, `src/vendormodules`) with `package prefer latest` so magic-version dev modules (`999999.0a1.0`) beat stamped snapshots. `src` mode is the standard way to verify working-tree changes without a rebuild. Source: `bin/AGENTS.md` "Launch package modes".
- **Payload mount derivation (G-129, achieved).** The boot keys zipfs presence on `tcl::zipfs::mount` and derives where the executable's attached archive actually mounted from the mount table itself (the entry whose archive file is the executable; fallback: the mount containing the boot script) instead of assuming `tcl::zipfs::root` + `//zipfs:/app`. Modern runtimes still answer `//zipfs:/app`; the androwish/undroidwish 8.6 backport has no `root` command, mounts at the executable's own path, and boots the same payload through its `app/main.tcl` in-archive hook (`src/vfs/punk8win.vfs` carries fauxlinks for both conventions). A mounted archive the boot cannot attribute is reported on stderr rather than silently yielding no internal paths. The derivation procs stay defined post-boot (`::punkboot::zipfs_kit_mountbase`). Sources: `src/vfs/AGENTS.md`, `bin/AGENTS.md` "Kit-wrappable runtime requirements", `src/tests/shell/testsuites/punkexe/kitmountpoint.test`.
- **Static package capture (G-058, achieved).** Boot probe-loads the runtime's statically linked packages in a throwaway interp and records what each provides; every interp the shell fabricates (boot, codethread, shellthread workers) seeds `package ifneeded <name> <ver> {load {} <prefix>}` from that record, and `punk::packagepreference` resolves static-vs-bundled version-aware. Sources: `src/vfs/AGENTS.md`, `goals/archive/G-058-static-runtime-packages.md`.
@ -106,7 +106,7 @@ Mechanics here are documented as pointers only - detailed prose would be obsolet
- Input mode and completion: G-013 (raw-mode default), G-044 (punk::args-driven completion).
- Stored configuration and help: G-014 (punk::config toml), G-042 (subshell help topics), G-043 (subshell definition plugins).
- Console err channel: G-011.
- Launch surface: G-023 (version-named binaries), G-033 (`proj:` package mode), G-077 (`-e` one-liners), G-089 (scriptlib in kits).
- Launch surface: G-023 (version-named binaries), G-077 (`-e` one-liners), G-089 (scriptlib in kits).
- 8.6 buildsuite family: G-101 (kit container) - the core runtime (G-099) and the Tk/tklib/tcllib dependency set (G-100) are achieved 2026-07-26.
## Doc map - which lane holds what

15
CHANGELOG.md

@ -5,6 +5,21 @@ The latest `## [X.Y.Z]` header must match the `version` field in `punkproject.to
Entries are newest-first; one bullet per notable change. See the root `AGENTS.md`
"Project Versioning" section for the bump policy.
## [0.29.0] - 2026-07-28
- `proj:` package-mode scope prefix (G-033): an installed or standalone punk shell
binary can visit the punk project containing the current directory -
`<punkexe> proj:internal-src shell` (canonical, kit copies win same-version ties)
or `proj:src` (project copies win). The boot walks up from the cwd to the nearest
git/fossil repo root with a punkshell-style src tree and feeds it to the existing
src/dev path machinery (src/modules + bootsupport + vendormodules + src/lib,
`package prefer latest`, #modpod registration), reporting the detected root and
effective precedence on stderr - warn-and-proceed (dev/src unbound) when no
project is found, never an exe-relative fallback rebind. Exe-relative plain
`src`/`dev` launches are unchanged. The packagemode contract (blocks, ordering,
proj: examples) is now live punk::args documentation in
punk::args::moduledoc::punkexe 0.1.1 (rendering wiring remains G-032).
## [0.28.4] - 2026-07-27
- punk::zip 0.3.0 (G-126): optional punkzip extraction accelerator. New

8
bin/AGENTS.md

@ -87,7 +87,7 @@ platform-specific difference left in examples is path separator style
### Launch package modes (built punk shells)
The first argument to a built punk shell may be a dash-delimited package mode composed of tokens from `dev`, `os`, `src`, `internal` (e.g. `punksys src`, `punk902z dev-os`). `internal` is the default and is always appended when absent. A first argument that is not a valid mode list is treated as a subcommand instead. Implementation: `src/vfs/_config/punk_main.tcl` (search `all_package_modes`).
The first argument to a built punk shell may be a dash-delimited package mode composed of tokens from `dev`, `os`, `src`, `internal` (e.g. `punksys src`, `punk902z dev-os`), optionally scoped with the `proj:` prefix (e.g. `punk91 proj:internal-src`). `internal` is the default and is always appended when absent. A first argument that is not a valid mode list is treated as a subcommand instead (a `proj:` prefix on a non-mode string is not consumed either). Implementation: `src/vfs/_config/punk_main.tcl` (search `all_package_modes`). The full packagemode contract (block meanings, ordering, proj: examples) is the punk::args documentation at id `(script)::punkexe` (module `punk::args::moduledoc::punkexe`).
`src` mode is the one that matters for verifying working-tree changes:
@ -95,6 +95,12 @@ The first argument to a built punk shell may be a dash-delimited package mode co
- Prepends `src/modules`, `src/modules_tcl<N>`, `src/bootsupport/modules{,_tcl<N>}` and `src/vendormodules{,_tcl<N>}` to the module path, sets `package prefer latest` so dev-numbered `999999.0a1.0` source modules beat kit-stamped snapshots on unversioned `package require`, and registers `#modpod` modules from `src/modules` (startup notice: `src mode: registered N #modpod modules from .../src/modules`).
- Consequence: `punksys src` / `punk902z src` exercises current working-tree source with no kit rebuild; a plain launch (`punksys`) exercises the module snapshots baked into the kit at build time. `package present <pkg>` reporting `999999.0a1.0` (vs a release version like `0.7.1`) tells you which set a session is running - runbooks with version expectations must state the intended launch mode.
`proj:` scope (G-033, achieved - see goals/archive/G-033-proj-mode-cwd-project.md) makes `dev`/`src` resolve against the project containing the CURRENT DIRECTORY instead of the executable's own project - visitor mode for an installed/standalone punk binary exploring a project that builds no shell of its own (the project may be modules-only, e.g. tomlish):
- Root discovery walks up from the cwd to the nearest git/fossil repo root that looks like a punkshell-style project (has `./src` plus one of `src/modules`, `src/vfs`, `src/scriptapps`, or `punkproject.toml` - a lean boot mirror of `punk::repo::is_project_root`).
- The launch always reports the detected root and effective mode precedence on stderr; when no project is found it warns and proceeds with dev/src unbound (never a silent or false rebind, no exe-relative fallback). `proj:` with no dev/src block warns that it has no effect.
- Canonical visitor invocation: `<punkexe> proj:internal-src shell` - kit copies win same-version ties, protecting the visiting shell's own infrastructure. `proj:src` is the faithful-vintage variant where the visited project's copies win ties. The project's genuinely-own code (dev-versioned or absent from the kit) loads from the project in either order.
### Kit-wrappable runtime requirements (G-129)
What a runtime must provide for `make.tcl bake` to wrap it as a punk ZIP kit and for that

2
punkproject.toml

@ -1,4 +1,4 @@
[project]
name = "punkshell"
version = "0.28.4"
version = "0.29.0"
license = "BSD-2-Clause"

38
src/modules/punk/args/moduledoc/punkexe-999999.0a1.0.tm

@ -91,9 +91,13 @@ tcl::namespace::eval punk::args::moduledoc::punkexe {
An optional FIRST argument selects package modes: one or more of
the tokens dev, os, src, internal joined with '-' when combined
(e.g 'dev', 'src', 'dev-src'). Modes decide which module sources
the shell trusts and their precedence; 'internal' (kit-bundled
modules) is always appended when absent. Details: bin/AGENTS.md
(e.g 'dev', 'src', 'dev-src'), optionally scoped with the
'proj:' prefix (e.g 'proj:internal-src') so dev/src resolve
against the project containing the current directory instead of
the executable's own (G-033 visitor mode). Modes decide which
module sources the shell trusts and their precedence; 'internal'
(kit-bundled modules) is always appended when absent. Full
contract: the packagemode leader below and bin/AGENTS.md
'launch package modes' in the punkshell source tree.
The next argument selects a subcommand from the choices below.
@ -102,7 +106,33 @@ tcl::namespace::eval punk::args::moduledoc::punkexe {
('shell'); any other first argument is treated as a script
invocation (handled as for the 'script' subcommand)."
@form -synopsis "<punkexe> ?packagemode? ?subcommand? ?arg ...?"
@leaders -min 0 -max 1
@leaders -min 0 -max 2
packagemode -type string -optional 1 -default internal -help\
"Package-source mode: an ordered dash-separated list of path
blocks, optionally scoped with the 'proj:' prefix.
Blocks (each adds a group of module/library paths):
internal - paths inside the executable's kit (always included;
appended last unless listed explicitly)
dev - the project's built output (<projectroot>/modules ...)
src - the project's unbuilt source (src/modules,
src/bootsupport/modules, src/vendormodules, src/lib)
os - ad-hoc .tm paths from the current directory/environment
Without 'proj:', dev/src resolve against the executable's own
project (executable in <projectroot>/bin). With 'proj:', they
resolve against the nearest project root at or above the current
directory (a git or fossil repository root) - for an installed
punkshell binary visiting a project that builds no shell of its
own.
ORDER MATTERS: earlier blocks win when the same version of a
module exists in more than one location.
Examples:
src work on the executable's own project source
proj:internal-src explore the cwd project; the executable's own
copies win version ties (robust visitor default)
proj:src explore the cwd project; ITS copies win version
ties (faithful to the project's snapshot vintage)
The launch reports the detected project root and effective
precedence."
subcommand -type string -optional 1 -choicerestricted 0 -choices {tclsh script shell punk shellspy} -choicelabels {
tclsh
" Run as a (near) stock tclsh - no punk modules loaded."

2
src/modules/punk/args/moduledoc/punkexe-buildversion.txt

@ -1,3 +1,3 @@
0.1.0
0.1.1
#First line must be a semantic version number
#all other lines are ignored.

2
src/vfs/AGENTS.md

@ -16,7 +16,7 @@ VFS (Virtual File System) folders define the runtime payloads that get wrapped i
- A `*.vfs` folder built against a runtime is expected to carry a root-level startup script: an actual `main.tcl`, or a root fauxlink resolving to the name `main.tcl` whose target exists and is a `.tcl` file. `make.tcl` warns when neither is present (column-0 `BUILD-WARNING:` token, ANSI-highlighted, recapped at end of run like provenance warnings) but still builds - a kit without a startup script is legal. Overlay-only folders with no runtime mapping (e.g `_vfscommon.vfs`) are not checked.
- VFS content must be compatible with the target platform runtime.
- `_vfscommon.vfs/` is an auto-generated merge of common libraries; manually editing it will be overwritten.
- `_config/punk_main.tcl` accepts an optional package_mode argument before the subcommand. Valid modes are `dev`, `os`, `internal`, and `src`, dash-delimited in priority order (e.g `src-internal`). `internal` is always appended if omitted.
- `_config/punk_main.tcl` accepts an optional package_mode argument before the subcommand. Valid modes are `dev`, `os`, `internal`, and `src`, dash-delimited in priority order (e.g `src-internal`). `internal` is always appended if omitted. An optional `proj:` prefix (G-033, e.g `proj:internal-src`) makes `dev`/`src` resolve against the project containing the cwd (walk-up to the nearest git/fossil repo root with a punkshell-style src tree, via `::punkboot::proj_root_find`) instead of the executable's own project; discovery outcome is always reported on stderr and a failed discovery leaves dev/src unbound rather than falling back exe-relative.
- `_config/punk_main.tcl` captures the runtime's static/builtin packages at boot (G-058): empty-filename `info loaded` prefixes are probe-loaded in a throwaway interp (denylist `::punkboot::static_probe_denylist`, default `tk* vfs mk4tcl vlerq tdbc*` - side-effecting or composite inits) and each package a probe-load actually PROVIDES is recorded in `::punkboot::static_packages` {pkgname {version <v> prefix <p>}} with `::punkboot::static_prefixes` alongside. The boot interp and every punkshell-fabricated interp/thread (punk::lib::interp_sync_package_paths / snapshot_package_paths, repl codethread, shellthread workers) seed `package ifneeded <name> <ver> {load {} <prefix>}` from it, and punk::packagepreference resolves static-vs-bundled version-aware. Composite statics whose script layer lived in the runtime's own (replaced) zipfs provide nothing under the probe and are correctly left to bundled copies.
- `src` mode loads unbuilt modules and libraries from the project's `src/` tree (`src/modules`, `src/lib`, `src/bootsupport`, `src/vendormodules`) instead of built output. It also runs an inline `#modpod` package-ifneeded scanner (using Tcl builtins only, since no punk modules are loaded at boot time) and sets `package prefer latest` so `999999.0a1.0` dev modules are preferred over stable bootsupport/vendored copies.
- `_config/punk_main.tcl` and `_config/project_main.tcl` derive the kit's payload location from the runtime's own zipfs mount table (G-129): zipfs presence keys on `tcl::zipfs::mount` (not `tcl::zipfs::root`, which the androwish/undroidwish 8.6 backport lacks), the mount base is the table entry whose archive file is `[info nameofexecutable]` (fallback: the mount containing the boot script), `//zipfs:/app` stays the expected modern answer rather than a compiled-in assumption, and a mounted archive that cannot be attributed to the executable is reported on stderr. The derivation lives in `::punkboot` procs (`zipfs_kit_mountbase`, `zipfs_mount_pairs`, `path_within`) that remain defined after boot for probing and tests. Both files carry identical copies of this logic (G-031 is the planned consolidation). Characterization: `src/tests/shell/testsuites/punkexe/kitmountpoint.test`.

125
src/vfs/_config/punk_main.tcl

@ -366,6 +366,45 @@ apply { args {
}
return ""
}
proc proj_root_find {startdir} {
#G-033: lean boot mirror of punk::repo::find_project (scanup on
#is_project_root) using only Tcl builtins - punk::repo is not loadable at
#the package-mode boot phase. Walks up from $startdir to the nearest VCS
#repo root (git or fossil control markers; 'file exists' sees
#windows-hidden items) that also passes a lean punk::repo::is_candidate_root
#check: not an unwise location, has ./src, and one of ./src/modules,
#./src/vfs, ./src/scriptapps or ./punkproject.toml. Keep the semantics
#aligned with punk::repo so a project findable at boot is findable by the
#runtime layer and vice versa (known divergence: .git is accepted as file
#OR dir - git worktree/submodule checkouts are legitimate visit targets).
#Returns the project root, or "" when no candidate is found.
set unwise_paths [list "/" "/dev" "/bin" "/root" "/etc" "/opt" "/usr" "/usr/local" "/usr/local/bin" "/usr/local/lib" "c:/windows"]
set dir [file normalize $startdir]
while 1 {
set is_repo_root 0
foreach marker [list .git _FOSSIL_ .fslckout .fos] {
if {[file exists [file join $dir $marker]]} {
set is_repo_root 1
break
}
}
if {$is_repo_root && [string tolower $dir] ni $unwise_paths} {
if {[file isdirectory [file join $dir src]]} {
if {[file isdirectory [file join $dir src modules]]\
|| [file isdirectory [file join $dir src vfs]]\
|| [file isdirectory [file join $dir src scriptapps]]\
|| [file exists [file join $dir punkproject.toml]]} {
return $dir
}
}
}
set parent [file dirname $dir]
if {$parent eq $dir} {
return ""
}
set dir $parent
}
}
}
#G-129: key zipfs presence on tcl::zipfs::mount - present in every supported zipfs
@ -613,14 +652,24 @@ apply { args {
#Token-by-token validation: instead of exhaustively listing all permutations,
#split the first arg on dash and validate each token against the known mode set.
#This scales to any number of modes without enumerating every permutation.
#G-033: an optional 'proj:' prefix on the mode string (e.g proj:internal-src)
#scopes WHICH project the dev/src blocks resolve against - the project containing
#the cwd instead of the executable's own. The prefix sits outside the ordered
#dash-list, whose block order remains the same-version tie-break dial.
set proj_scope 0
set test_mode_string $test_package_mode
if {[string match proj:* $test_package_mode]} {
set proj_scope 1
set test_mode_string [string range $test_package_mode 5 end]
}
set package_modes ""
set arglist ""
if {$test_package_mode eq ""} {
#empty first arg consumed as equivalent of 'internal'
if {$test_mode_string eq ""} {
#empty first arg (or bare 'proj:') consumed as equivalent of 'internal'
set package_modes internal
set arglist [lrange $args 1 end]
} else {
set tokens [split $test_package_mode -]
set tokens [split $test_mode_string -]
set valid 1
foreach t $tokens {
if {$t ni $all_package_modes} {
@ -636,6 +685,9 @@ apply { args {
set arglist [lrange $args 1 end]
} else {
#not a package_mode - treat as subcommand
#(a 'proj:' prefix on a non-mode string is not consumed either - the
#whole arg passes through, e.g as a script name)
set proj_scope 0
set package_modes internal
set arglist $args
}
@ -644,6 +696,28 @@ apply { args {
set ::argv $arglist
set ::argc [llength $arglist]
#assert: package_modes is now a list of at least length 1 (in which case the only possible value is: internal)
#--------------------------------------------------------
#G-033 proj: scope - resolve dev/src against the project containing the cwd
#(walk-up to the nearest VCS repo root, the punk::repo::is_project_root marker)
#instead of the executable's own project. Explicit prefix = opt-in; discovery and
#its outcome are always reported on stderr (a rebind must never be silent), and a
#failed discovery never falls back to exe-relative roots (no false rebind).
#--------------------------------------------------------
set proj_root ""
if {$proj_scope} {
if {!("dev" in $package_modes || "src" in $package_modes)} {
puts stderr "proj: WARNING - 'proj:' has no effect: package mode list '[join $package_modes -]' contains no project-root-using block (dev or src)"
} else {
set proj_root [::punkboot::proj_root_find [pwd]]
if {$proj_root eq ""} {
puts stderr "proj: WARNING - no project root found walking up from [pwd] (nearest git/fossil repo root with a punkshell-style src tree) - dev/src blocks are not bound to any project (proceeding; internal/os paths unaffected)"
} else {
puts stderr "proj: project root detected (walk-up from [pwd]): $proj_root"
puts stderr "proj: effective package mode precedence: [join $package_modes -] (earlier blocks win same-version ties)"
}
}
}
#Note regarding the use of package forget and binary packages
#If the package has loaded a binary component - then a package forget and a subsequent package require can result in both binaries being present, as seen in 'info loaded' result - potentially resulting in anomalous behaviour
#In general package forget after a package has already been required may need special handling and should be avoided where possible.
@ -722,6 +796,17 @@ apply { args {
#case differences could represent different paths on unix-like platforms.
#It's perhaps a little unwise to configure matching paths with only case differences for a cross-platform tool .. but we should support it for those who use it and have no interest in windows - todo! review
if {"dev" in $package_modes} {
set exe_module_folders [list]
if {$proj_scope} {
#G-033: dev module paths resolve against the cwd-walk-up project root
#only - no exe-relative fallback (a proj: launch must never silently
#rebind to the executable's own project; a failed discovery was
#already warned above and the dev block then contributes nothing).
if {$proj_root ne ""} {
lappend exe_module_folders $proj_root/modules
lappend exe_module_folders $proj_root/modules_tcl$tclmajorv
}
} else {
set normexe_dir [file dirname $normexe]
if {[file tail $normexe_dir] eq "bin"} {
#underlying exe in a bin dir - backtrack 1
@ -741,6 +826,7 @@ apply { args {
lappend exe_module_folders $nameexe_dir/modules
lappend exe_module_folders $nameexe_dir/modules_tcl$tclmajorv
}
}
#foreach modulefolder $exe_module_folders {
# set lc_external_tm_dirs [string tolower $external_tm_dirs]
@ -766,7 +852,10 @@ apply { args {
# }
#}
if {![llength $exe_module_folders]} {
#proj_scope with no discovered root was already warned at proj: discovery
if {!$proj_scope} {
puts stderr "Warning - no 'modules' or 'modules_tcl$tclmajorv' folders found relative to executable (or it's symlink if any)"
}
} else {
set tm_additions_dev $exe_module_folders
}
@ -776,8 +865,14 @@ apply { args {
#Unlike dev mode (which points at built output in <projectroot>/modules),
#src mode points at the unbuilt source in <projectroot>/src/modules etc.
if {"src" in $package_modes} {
#reuse the dev-mode project root discovery (exe in bin/ -> backtrack 1)
set src_project_root ""
if {$proj_scope} {
#G-033: src resolves against the cwd-walk-up project root; empty
#(warned at discovery) means the src block contributes nothing -
#never an exe-relative fallback rebind.
set src_project_root $proj_root
} else {
#reuse the dev-mode project root discovery (exe in bin/ -> backtrack 1)
set normexe_dir_for_src [file dirname $normexe]
if {[file tail $normexe_dir_for_src] eq "bin"} {
set src_project_root [file dirname $normexe_dir_for_src]
@ -793,6 +888,7 @@ apply { args {
set src_project_root $nameexe_dir_for_src
}
}
}
if {$src_project_root ne "" && [file isdirectory [file join $src_project_root src]]} {
foreach p [list modules modules_tcl$tclmajorv] {
@ -815,10 +911,17 @@ apply { args {
lappend tm_additions_src $modpath
}
}
} else {
if {$proj_scope} {
#no discovered root was already warned at proj: discovery
if {$src_project_root ne ""} {
puts stderr "Warning - src mode (proj:): no src/ directory under detected project root ($src_project_root)"
}
} else {
puts stderr "Warning - src mode: no src/ directory found relative to executable ($normexe_dir_for_src)"
}
}
}
@ -947,6 +1050,19 @@ apply { args {
#on other platforms, case differences could represent different paths
#review
set process_folders [list]
if {$proj_scope} {
#G-033: dev lib paths resolve against the cwd-walk-up project root
#only (no exe-relative or cwd-relative candidates - see the dev
#module-path block above for rationale).
if {$proj_root ne ""} {
foreach libsub [list lib_tcl$tclmajorv lib] {
set libfolder $proj_root/$libsub
if {[file isdirectory $libfolder] && $libfolder ni $process_folders} {
lappend process_folders $libfolder
}
}
}
} else {
foreach libsub [list lib_tcl$tclmajorv lib] {
if {[file tail $nameexe_dir] eq "bin"} {
set libfolder [file dirname $nameexe_dir]/$libsub
@ -979,6 +1095,7 @@ apply { args {
}
}
}
}
foreach f $process_folders {
if {[string match lib_tcl* [file tail $f]]} {
if {[file exists $f/allplatforms]} {

Loading…
Cancel
Save