]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
tea: pull in upstream teaish. Consolidate the build definition from the upstream...
authorstephan <stephan@noemail.net>
Mon, 28 Apr 2025 09:25:19 +0000 (09:25 +0000)
committerstephan <stephan@noemail.net>
Mon, 28 Apr 2025 09:25:19 +0000 (09:25 +0000)
FossilOrigin-Name: 0ea5993dd8549056d73f3d5447e0a810495ece23a75be8add78fba6842125d85

autoconf/tea/Makefile.in
autoconf/tea/autosetup/core.tcl
autoconf/tea/autosetup/tester.tcl
autoconf/tea/teaish.tcl
autosetup/proj.tcl
manifest
manifest.uuid

index 60c8761d62cc3569ee7788d6a4b5d1c085e672af..5aa374cf78e18ea1a3e7f4f33451da45e126fbd8 100644 (file)
@@ -34,8 +34,8 @@ INSTALL.noexec = $(INSTALL) -m 0644
 # any given teaish build.
 #
 tx.name          = @TEAISH_NAME@
-tx.pkgName       = @TEAISH_PKGNAME@
 tx.version       = @TEAISH_VERSION@
+tx.name.pkg      = @TEAISH_PKGNAME@
 tx.libdir        = @TEAISH_LIBDIR_NAME@
 tx.loadPrefix    = @TEAISH_LOAD_PREFIX@
 tx.tcl           = @TEAISH_TCL@
@@ -48,6 +48,12 @@ tx.dll9          = @TEAISH_DLL9@
 tx.dll           = $(tx.dll$(TCL_MAJOR_VERSION))
 tx.dir           = @TEAISH_EXT_DIR@
 
+@if TEAISH_DIST_NAME
+tx.name.dist     = @TEAISH_DIST_NAME@
+@else
+tx.name.dist     = $(teaish.name)
+@endif
+
 teaish.dir           = @abs_top_srcdir@
 #teaish.dir.autosetup = @TEAISH_AUTOSETUP_DIR@
 teaish.makefile      = Makefile
@@ -69,6 +75,7 @@ libdir         = @libdir@
 libexecdir     = @libexecdir@
 localstatedir  = @localstatedir@
 mandir         = @mandir@
+prefix         = @prefix@
 runstatedir    = @runstatedir@
 sbindir        = @sbindir@
 sharedstatedir = @sharedstatedir@
@@ -81,16 +88,17 @@ sysconfdir     = @sysconfdir@
 #
 TCLSH             = @TCLSH_CMD@
 TCL_CONFIG_SH     = @TCL_CONFIG_SH@
+TCL_EXEC_PREFIX   = @TCL_EXEC_PREFIX@
 TCL_INCLUDE_SPEC  = @TCL_INCLUDE_SPEC@
+TCL_LIBS          = @TCL_LIBS@
 TCL_LIB_SPEC      = @TCL_LIB_SPEC@
-TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
-TCL_EXEC_PREFIX   = @TCL_EXEC_PREFIX@
-TCL_VERSION       = @TCL_VERSION@
 TCL_MAJOR_VERSION = @TCL_MAJOR_VERSION@
 TCL_MINOR_VERSION = @TCL_MINOR_VERSION@
 TCL_PATCH_LEVEL   = @TCL_PATCH_LEVEL@
+TCL_PREFIX        = @TCL_PREFIX@
 TCL_SHLIB_SUFFIX  = @TCL_SHLIB_SUFFIX@
-TCL_LIBS          = @TCL_LIBS@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION       = @TCL_VERSION@
 TCLLIBDIR         = @TCLLIBDIR@
 
 #
@@ -107,10 +115,15 @@ CFLAGS.configure = @SH_CFLAGS@ @TEAISH_CFLAGS@ @CFLAGS@ @CPPFLAGS@ $(TCL_INCLUDE
 # LDFLAGS.configure = LDFLAGS as known at configure-time.
 #
 # This ordering is deliberate: flags populated via tcl's
-# [teaish-ldflags-add] should preceed LDFLAGS (which typically
+# [teaish-ldflags-add] should precede LDFLAGS (which typically
 # comes from the ./configure command-line invocation).
 #
-LDFLAGS.configure = @SH_LDFLAGS@ @TEAISH_LDFLAGS@ @LDFLAGS@ $(TCL_STUB_LIB_SPEC)
+LDFLAGS.configure = @TEAISH_LDFLAGS@ @LDFLAGS@
+
+#
+# Linker flags for linkhing a shared library.
+#
+LDFLAGS.shlib = @SH_LDFLAGS@
 
 #
 # The following tx.XYZ vars may be populated/modified by teaish.tcl
@@ -119,9 +132,9 @@ LDFLAGS.configure = @SH_LDFLAGS@ @TEAISH_LDFLAGS@ @LDFLAGS@ $(TCL_STUB_LIB_SPEC)
 
 #
 # tx.src is the list of source or object files to include in the
-# (single) compiler invocation. This will initially contain any
-# sources passed to [teaish-src-add], but may also be appended to
-# by teaish.make.
+# (single) compiler/linker invocation. This will initially contain any
+# sources passed to [teaish-src-add], but may also be appended to by
+# teaish.make.
 #
 tx.src     =@TEAISH_EXT_SRC@
 
@@ -163,25 +176,49 @@ teaish__autogen.deps = \
   @TEAISH_PKGINDEX_TCL_IN@ \
   @AUTODEPS@
 
+@if TEAISH_MAKEFILE_IN
+$(tx.makefile): $(tx.makefile.in)
+@endif
+
+teaish.autoreconfig = \
+  @TEAISH_AUTORECONFIG@
+
 #
 # Problem: when more than one target can invoke TEAISH_AUTORECONFIG,
 # we can get parallel reconfigures running. Thus, targets which
 # may require reconfigure should depend on...
 #
 config.log: $(teaish__autogen.deps)
-       @TEAISH_AUTORECONFIG@
+       $(teaish.autoreconfig)
 # ^^^ We would love to skip this when running [dist]clean, but there's
 # no POSIX Make-portable way to do that. GNU Make can.
 .PHONY: reconfigure
 reconfigure:
-       @TEAISH_AUTORECONFIG@
+       $(teaish.autoreconfig)
 
 $(teaish.makefile): $(teaish__auto.def) $(teaish.makefile.in) \
   @AUTODEPS@
 
+@if TEAISH_TESTER_TCL_IN
 @TEAISH_TESTER_TCL_IN@:
 @TEAISH_TESTER_TCL@: @TEAISH_TESTER_TCL_IN@
 config.log: @TEAISH_TESTER_TCL@
+@endif
+
+#
+# CC variant for compiling Tcl-using sources.
+#
+CC.tcl = \
+  $(CC) -o $@ $(CFLAGS.configure) $(CFLAGS) $(tx.CFLAGS)
+
+#
+# CC variant for linking $(tx.src) into an extension DLL.  Note that
+# $(tx.src) must come before $(LDFLAGS...) for linking to third-party
+# libs to work.
+#
+CC.dll = \
+  $(CC.tcl) $(tx.src) $(LDFLAGS.shlib) \
+    $(LDFLAGS.configure) $(LDFLAGS) $(tx.LDFLAGS) $(TCL_STUB_LIB_SPEC)
 
 @if TEAISH_ENABLE_DLL
 #
@@ -189,8 +226,11 @@ config.log: @TEAISH_TESTER_TCL@
 # target: the extension shared lib.
 #
 $(tx.dll): $(tx.src) config.log
-       $(CC) -o $@ $(CFLAGS.configure) $(CFLAGS) $(tx.CFLAGS) \
-               $(tx.src) $(LDFLAGS.configure) $(LDFLAGS) $(tx.LDFLAGS)
+       @if [ "x" = "x$(tx.src)" ]; then \
+               echo "Makefile var tx.src (source/object files) is empty" 1>&2; \
+               exit 1; \
+       fi
+       $(CC.dll)
 
 all: $(tx.dll)
 @endif # TEAISH_ENABLE_DLL
@@ -208,6 +248,7 @@ test-extension: # this name is reserved for use by teaish.make[.in]
 @if TEAISH_ENABLE_DLL
 test-prepre: $(tx.dll)
 @endif
+@if TEAISH_TESTER_TCL
 test-core.args = @TEAISH_TESTER_TCL@
 @if TEAISH_ENABLE_DLL
 test-core.args += '$(tx.dll)' '$(tx.loadPrefix)'
@@ -215,10 +256,14 @@ test-core.args += '$(tx.dll)' '$(tx.loadPrefix)'
 test-core.args += '' ''
 @endif
 test-core.args += @TEAISH_TESTUTIL_TCL@
+test-core: test-pre
+       $(TCLSH) $(test-core.args)
 test-prepre: @TEAISH_TESTER_TCL@
+@else # !TEAISH_TESTER_TCL
+test-prepre:
+@endif # TEAISH_TESTER_TCL
 test-pre: test-prepre
 test-core: test-pre
-       $(TCLSH) $(test-core.args)
 test-post: test-core
 test: test-post
 
@@ -234,7 +279,6 @@ clean-post: clean-core
 clean: clean-post
 
 .PHONY: distclean-pre distclean-core distclean-post clean-extension
-distclean-extension: # this name is reserved for use by teaish.make
 distclean-pre: clean
 distclean-core: distclean-pre
        rm -f Makefile
@@ -256,6 +300,7 @@ distclean-core: distclean-pre
 @if TEAISH_TEST_TCL_IN
        rm -f @TEAISH_TEST_TCL@
 @endif
+distclean-extension: # this name is reserved for use by teaish.make
 distclean-post: distclean-core
 distclean: distclean-post
 
@@ -277,14 +322,15 @@ install-core: install-pre
        $(INSTALL.noexec) @TEAISH_PKGINIT_TCL@ "$(DESTDIR)$(TCLLIBDIR)"
 @endif
 install-test: install-core
-       @echo 'package require $(tx.pkgName) $(tx.version)' > $@.tcl
-       @echo "Post-install test of [package require $(tx.pkgName) $(tx.version)]..."
-       @if $(TCLSH) $@.tcl ; then \
-               echo "test passed"; \
-               rm -f $@.tcl; \
+       @echo "Post-install test of [package require $(tx.name.pkg) $(tx.version)]..."; \
+       if echo \
+               'set c 0;' \
+               'if {[catch {package require  $(tx.name.pkg) $(tx.version)}]} {incr c};' \
+               'exit $$c' \
+               | $(TCLSH) ; then \
+               echo "passed"; \
        else \
-               echo "TEST FAILED"; \
-               rm -f $@.tcl; \
+               echo "FAILED"; \
                exit 1; \
        fi
 install-post: install-test
@@ -302,35 +348,50 @@ uninstall-post: uninstall-core
        @echo "Uninstalled Tcl extension $(tx.name) $(tx.version)"
 uninstall: uninstall-post
 
-Makefile: config.log $(teaish.makefile.in)
 @if TEAISH_MAKEFILE_IN
-config.log: @TEAISH_MAKEFILE_IN@
+Makefile:  $(tx.makefile.in)
+config.log: $(teaish.makefile.in)
 @endif
 
 #
 # Package archive generation ("dist") rules...
 #
 @if TEAISH_ENABLE_DIST
+@if BIN_TAR
 @if BIN_ZIP
+
+# When installing teaish as part of "make dist", we need to run
+# configure with similar flags to what we last configured with but we
+# must not pass on any extension-specific flags, as those won't be
+# recognized when running in --teaish-install mode, causing
+# the sub-configure to fail.
+dist.flags = --with-tclsh=$(TCLSH)
+dist.reconfig = $(teaish.dir)/configure $(dist.flags)
+
 # Temp dir for dist.zip. Must be different than dist.tgz or else
 # parallel builds may hose the dist.
 teaish__dist.tmp.zip = teaish__dist_zip
 #
 # Make a distribution zip file...
 #
-dist.zip.dir = $(tx.name)-$(tx.version)
-dist.zip = $(dist.zip.dir).zip
+dist.basename = $(tx.name.dist)-$(tx.version)
+dist.zip = $(dist.basename).zip
 .PHONY: dist.zip dist.zip-core dist.zip-post
 #dist.zip-pre:
 # We apparently can't add a pre-hook here, else "make dist" rebuilds
 # the archive each time it's run.
 $(dist.zip): $(tx.dist.files)
        @rm -fr $(teaish__dist.tmp.zip)
-       @mkdir -p $(teaish__dist.tmp.zip)/$(dist.zip.dir)
+       @mkdir -p $(teaish__dist.tmp.zip)/$(dist.basename)
        @tar cf $(teaish__dist.tmp.zip)/tmp.tar $(tx.dist.files)
-       @tar xf $(teaish__dist.tmp.zip)/tmp.tar -C $(teaish__dist.tmp.zip)/$(dist.zip.dir)
-       @rm -f $(dist.zip.dir)/tmp.tar $(dist.zip)
-       @cd $(teaish__dist.tmp.zip) && zip -q -r ../$(dist.zip) $(dist.zip.dir)
+       @tar xf $(teaish__dist.tmp.zip)/tmp.tar -C $(teaish__dist.tmp.zip)/$(dist.basename)
+@if TEAISH_DIST_FULL
+       @$(dist.reconfig) \
+               --teaish-install=$(teaish__dist.tmp.zip)/$(dist.basename) \
+               --t-e-d=$(teaish__dist.tmp.zip)/$(dist.basename) >/dev/null
+@endif
+       @rm -f $(dist.basename)/tmp.tar $(dist.zip)
+       @cd $(teaish__dist.tmp.zip) && zip -q -r ../$(dist.zip) $(dist.basename)
        @rm -fr $(teaish__dist.tmp.zip)
        @ls -la $(dist.zip)
 dist.zip-core: $(dist.zip)
@@ -342,23 +403,27 @@ undist-zip:
 undist: undist-zip
 @endif #BIN_ZIP
 
-@if BIN_TAR
 #
 # Make a distribution tarball...
 #
 teaish__dist.tmp.tgz = teaish__dist_tgz
-dist.tgz.dir = $(tx.name)-$(tx.version)
-dist.tgz = $(dist.tgz.dir).tar.gz
+dist.tgz = $(dist.basename).tar.gz
 .PHONY: dist.tgz dist.tgz-core dist.tgz-post
 # dist.tgz-pre:
 # see notes in dist.zip
 $(dist.tgz): $(tx.dist.files)
        @rm -fr $(teaish__dist.tmp.tgz)
-       @mkdir -p $(teaish__dist.tmp.tgz)/$(dist.tgz.dir)
+       @mkdir -p $(teaish__dist.tmp.tgz)/$(dist.basename)
        @tar cf $(teaish__dist.tmp.tgz)/tmp.tar $(tx.dist.files)
-       @tar xf $(teaish__dist.tmp.tgz)/tmp.tar -C $(teaish__dist.tmp.tgz)/$(dist.tgz.dir)
-       @rm -f $(dist.tgz.dir)/tmp.tar $(dist.tgz)
-       @cd $(teaish__dist.tmp.tgz) && tar czf ../$(dist.tgz) $(dist.tgz.dir)
+       @tar xf $(teaish__dist.tmp.tgz)/tmp.tar -C $(teaish__dist.tmp.tgz)/$(dist.basename)
+@if TEAISH_DIST_FULL
+       @rm -f $(teaish__dist.tmp.tgz)/$(dist.basename)/pkgIndex.tcl.in; # kludge
+       @$(dist.reconfig) \
+               --teaish-install=$(teaish__dist.tmp.tgz)/$(dist.basename) \
+               --t-e-d=$(teaish__dist.tmp.zip)/$(dist.basename) >/dev/null
+@endif
+       @rm -f $(dist.basename)/tmp.tar $(dist.tgz)
+       @cd $(teaish__dist.tmp.tgz) && tar czf ../$(dist.tgz) $(dist.basename)
        @rm -fr $(teaish__dist.tmp.tgz)
        @ls -la $(dist.tgz)
 dist.tgz-core: $(dist.tgz)
@@ -368,6 +433,9 @@ dist: dist.tgz
 undist-tgz:
        rm -f $(dist.tgz)
 undist: undist-tgz
+@else #!BIN_TAR
+dist:
+       @echo "The dist rules require tar, which configure did not find." 1>&2; exit 1
 @endif #BIN_TAR
 @else #!TEAISH_ENABLE_DIST
 undist:
@@ -378,6 +446,21 @@ dist:
 @endif
 @endif #TEAISH_ENABLE_DIST
 
+Makefile: @TEAISH_TCL@
+
+@if TEAISH_MAKEFILE_CODE
+#
+# TEAISH_MAKEFILE_CODE may contain literal makefile code, which
+# gets pasted verbatim here. Either [define TEAISH_MAKEFILE_CODE
+# ...] or use [teaish-make-add] to incrementally build up this
+# content.
+#
+# <TEAISH_MAKEFILE_CODE>
+@TEAISH_MAKEFILE_CODE@
+# </TEAISH_MAKEFILE_CODE>
+@endif
+
+@if TEAISH_MAKEFILE
 #
 # TEAISH_MAKEFILE[_IN] defines any extension-specific state this file
 # needs.
@@ -401,31 +484,12 @@ dist:
 # It may optionally hook into various targets as documented in
 # /doc/extensions.md in the canonical teaish source tree.
 #
-# Interestingly, we don't have to pre-filter teaish.makefile.in -
-# we can just import it into here. That skips its teaish-specific
-# validation though. Hmm.
+# Interestingly, we don't have to pre-filter teaish.makefile.in - we
+# can just @include it here. That skips its teaish-specific validation
+# though. Hmm.
 #
-#@if TEAISH_MAKEFILE_IN
-## TEAISH_MAKEFILE_IN ==>
-#Makefile: @TEAISH_MAKEFILE_IN@
-#@include @TEAISH_MAKEFILE_IN@
-#@endif
-#@if !TEAISH_MAKEFILE_IN
-@if TEAISH_MAKEFILE
-# TEAISH_MAKEFILE ==>
+# <TEAISH_MAKEFILE>
 Makefile: @TEAISH_MAKEFILE@
 @include @TEAISH_MAKEFILE@
-@endif #TEAISH_MAKEFILE
-#@endif #!TEAISH_MAKEFILE_IN
-
-#
-# TEAISH_MAKEFILE_CODE may contain literal makefile code, which
-# gets pasted verbatim here. Either [define TEAISH_MAKEFILE_CODE
-# ...] or use [teaish-make-add] to incrementally build up this
-# content.
-#
-@if TEAISH_MAKEFILE_CODE
-# TEAISH_MAKEFILE_CODE ==>
-Makefile: @TEAISH_TCL@
-@TEAISH_MAKEFILE_CODE@
-@endif #TEAISH_MAKEFILE_CODE
+# </TEAISH_MAKEFILE>
+@endif
index 660173b3280e647d6f048440b69ea5c57a27fa84..c0baeb8fe588fba47db3982f234ea4365b3a5203 100644 (file)
@@ -34,6 +34,7 @@ array set teaish__Config [proj-strip-hash-comments {
 
   # set to 1 to enable some internal debugging output
   debug-enabled 0
+
   #
   # 0    = don't yet have extension's pkgindex
   # 0x01 = found TEAISH_EXT_DIR/pkgIndex.tcl.in
@@ -46,6 +47,20 @@ array set teaish__Config [proj-strip-hash-comments {
   #
   pkgindex-policy 0
 
+  #
+  # The pkginit counterpart of pkgindex-policy:
+  #
+  # 0    = no pkginit
+  # 0x01 = found default X.in: generate X from X.in
+  # 0x10 = found static pkginit file X
+  # 0x02 = user-provided X.in generates ./X.
+  # 0x20 = user-provided static pkginit file X
+  #
+  # The 0x0f bits indicate that teaish is responsible for cleaning up
+  # the (generated) pkginit file.
+  #
+  pkginit-policy 0
+
   #
   # If 1+ then teaish__verbose will emit messages.
   #
@@ -53,16 +68,21 @@ array set teaish__Config [proj-strip-hash-comments {
 
   #
   # Mapping of pkginfo -flags to their TEAISH_xxx define (if any).
+  # This must not be modified.
   #
   pkginfo-f2d {
-    -name TEAISH_NAME
-    -pkgName TEAISH_PKGNAME
-    -version TEAISH_VERSION
-    -libDir TEAISH_LIBDIR_NAME
-    -loadPrefix TEAISH_LOAD_PREFIX
-    -vsatisfies TEAISH_VSATISFIES
-    -options {}
-    -pragmas {}
+    -name            TEAISH_NAME
+    -name.dist       TEAISH_DIST_NAME
+    -name.pkg        TEAISH_PKGNAME
+    -version         TEAISH_VERSION
+    -libDir          TEAISH_LIBDIR_NAME
+    -loadPrefix      TEAISH_LOAD_PREFIX
+    -vsatisfies      TEAISH_VSATISFIES
+    -pkgInit.tcl     TEAISH_PKGINIT_TCL
+    -pkgInit.tcl.in  TEAISH_PKGINIT_TCL_IN
+    -url             TEAISH_URL
+    -options         {}
+    -pragmas         {}
   }
 
   #
@@ -93,6 +113,15 @@ array set teaish__Config [proj-strip-hash-comments {
 
   # Dir where teaish.tcl is found.
   extension-dir {}
+
+  # Whether the generates TEASH_VSATISFIES_CODE should error out on a
+  # satisfies error. If 0, it uses return instead of error.
+  vsatisfies-error 1
+
+  # Whether or not to allow a "full dist" - a "make dist" build which
+  # includes both the extension and teaish. By default this is only on
+  # if the extension dir is teaish's dir.
+  dist-full-enabled 0
 }]
 set teaish__Config(core-dir) $::autosetup(libdir)/teaish
 
@@ -139,8 +168,8 @@ if {[teaish-argv-has --teaish-verbose --t-v]} {
 msg-quiet use system ; # Outputs "Host System" and "Build System" lines
 if {"--help" ni $::argv} {
   teaish__verbose 1 msg-result "TEA(ish) Version = $::teaish__Config(version)"
-  teaish__verbose 1 msg-result "Source dir    = $::autosetup(srcdir)"
-  teaish__verbose 1 msg-result "Build dir     = $::autosetup(builddir)"
+  teaish__verbose 1 msg-result "Source dir       = $::autosetup(srcdir)"
+  teaish__verbose 1 msg-result "Build dir        = $::autosetup(builddir)"
 }
 
 #
@@ -152,9 +181,13 @@ if {"--help" ni $::argv} {
 proc teaish-configure-core {} {
   proj-tweak-default-env-dirs
 
+  set ::teaish__Config(install-mode) [teaish-argv-has --teaish-install*]
+  set ::teaish__Config(create-ext-mode) \
+    [teaish-argv-has --teaish-create-extension=* --t-c-e=*]
   set gotExt 0; # True if an extension config is found
-  if {![teaish-argv-has --teaish-create-extension=* --t-c-e=*]} {
-    # Don't look for an extension if we're in --t-c-e mode
+  if {!$::teaish__Config(create-ext-mode)
+      && !$::teaish__Config(install-mode)} {
+    # Don't look for an extension if we're in --t-c-e or --t-i mode
     set gotExt [teaish__find_extension]
   }
 
@@ -210,22 +243,43 @@ proc teaish-configure-core {} {
     teaish-dump-defines
       => {Dump all configure-defined vars to config.defines.txt}
 
-    t-v
-    teaish-verbose=0
+    t-v:=0
+    teaish-verbose:=0
       => {Enable more (often extraneous) messages from the teaish core.}
 
     t-d
-    teaish-debug => {Enable teaish-specific debug output}
+    teaish-debug=0 => {Enable teaish-specific debug output}
+
+    t-i
+    teaish-install:=auto
+      => {Installs a copy of teaish, including autosetup, to the target dir.
+          When used with --teaish-create-extension=DIR, a value of "auto"
+          (no no value) will inherit that directory.}
+
+    #TODO: --teaish-install-extension:=dir as short for
+    # --t-c-e=dir --t-i
+
+    t-e-p:
+    teaish-extension-pkginfo:pkginfo
+      => {For use with --teaish-create-extension. If used, it must be a
+          list of arguments for use with teaish-pkginfo-set, e.g.
+          --teaish-extension-pkginfo="-name Foo -version 2.3"}
+
+    t-v-c
+    teaish-vsatisfies-check=1
+      => {Disable the configure-time "vsatisfies" check on the target tclsh.}
+
   }]; # main options.
 
   if {$gotExt} {
     proj-assert {"" ne [teaish-pkginfo-get -name]}
     proj-assert {[file exists $::teaish__Config(teaish.tcl)]} \
       "Expecting to have found teaish.tcl by now"
-    uplevel 1 [list source $::teaish__Config(teaish.tcl)]
+    uplevel 1 {source $::teaish__Config(teaish.tcl)}
     # Set up some default values if the extension did not set them.
     # This must happen _after_ it's sourced but before
     # teaish-configure is called.
+    teaish__f2d_array f2d
     foreach {pflag key type val} {
       - TEAISH_CFLAGS           -v ""
       - TEAISH_LDFLAGS          -v ""
@@ -234,29 +288,38 @@ proc teaish-configure-core {} {
       - TEAISH_MAKEFILE_IN      -v ""
       - TEAISH_PKGINDEX_TCL     -v ""
       - TEAISH_PKGINDEX_TCL_IN  -v ""
-      - TEAISH_PKGINIT_TCL      -v ""
-      - TEAISH_PKGINIT_TCL_IN   -v ""
       - TEAISH_TEST_TCL         -v ""
       - TEAISH_TEST_TCL_IN      -v ""
 
-      -version    TEAISH_VERSION       -v 0.0.0
-      -pkgName    TEAISH_PKGNAME       -e {teaish-pkginfo-get -name}
-      -libDir     TEAISH_LIBDIR_NAME   -e {
+      -version          :f2d:   -v 0.0.0
+      -name.pkg         :f2d:   -e {teaish-pkginfo-get -name}
+      -name.dist        :f2d:   -e {teaish-pkginfo-get -name}
+      -libDir           :f2d:   -e {
         join [list \
-                [teaish-pkginfo-get -pkgName] \
+                [teaish-pkginfo-get -name.pkg] \
                 [teaish-pkginfo-get -version]] ""
       }
-      -loadPrefix TEAISH_LOAD_PREFIX   -e {
-        string totitle [teaish-get -pkgName]
+      -loadPrefix       :f2d:   -e {
+        string totitle [teaish-get -name.pkg]
       }
-      -vsatisfies TEAISH_VSATISFIES -v {{Tcl 8.5-}}
+      -vsatisfies       :f2d:   -v {{Tcl 8.5-}}
+      -pkgInit.tcl      :f2d:   -v ""
+      -pkgInit.tcl.in   :f2d:   -v ""
+      -url              :f2d:   -v ""
     } {
-      set isDefOnly [expr {"-" eq $pflag}]
-      if {!$isDefOnly &&  [info exists ::teaish__PkgInfo($pflag)]} {
-        continue;
+      set isPIFlag [expr {"-" ne $pflag}]
+      if {$isPIFlag} {
+        if {[info exists ::teaish__PkgInfo($pflag)]} {
+          # Was already set - skip it.
+          continue;
+        }
+        proj-assert {{:f2d:} eq $key}
+        set key $f2d($pflag)
       }
+      proj-assert {"" ne $key}
       set got [get-define $key "<nope>"]
-      if {$isDefOnly && "<nope>" ne $got} {
+      if {"<nope>" ne $got} {
+        # Was already set - skip it.
         continue
       }
       switch -exact -- $type {
@@ -264,13 +327,14 @@ proc teaish-configure-core {} {
         -e { set val [eval $val] }
         default { proj-error "Invalid type flag: $type" }
       }
-      #puts "***** defining default $pflag $key {$val} isDefOnly=$isDefOnly got=$got"
+      #puts "***** defining default $pflag $key {$val} isPIFlag=$isPIFlag got=$got"
       define $key $val
-      if {!$isDefOnly} {
+      if {$isPIFlag} {
         set ::teaish__PkgInfo($pflag) $val
       }
     }
-    unset isDefOnly pflag key type val
+    unset isPIFlag pflag key type val
+    array unset f2d
   }; # sourcing extension's teaish.tcl
 
   if {[llength [info proc teaish-options]] > 0} {
@@ -297,15 +361,28 @@ proc teaish-configure-core {} {
     t-d-d  => teaish-dump-defines
     ted    => teaish-extension-dir
     t-e-d  => teaish-extension-dir
+    t-e-p  => teaish-extension-pkginfo
     t-f    => teaish-force
+    t-i    => teaish-install
     t-v    => teaish-verbose
+    t-v-c  => teaish-vsatisfies-check
   }
 
-  set ::teaish__Config(verbose) [opt-bool teaish-verbose]
+  scan [opt-val teaish-verbose 0] %d ::teaish__Config(verbose)
   set ::teaish__Config(debug-enabled) [opt-bool teaish-debug]
 
+  set exitEarly 0
   if {[proj-opt-was-provided teaish-create-extension]} {
     teaish__create_extension [opt-val teaish-create-extension]
+    incr exitEarly
+  }
+  if {$::teaish__Config(install-mode)} {
+    teaish__install
+    incr exitEarly
+  }
+
+  if {$exitEarly} {
+    file delete -force config.log
     return
   }
   proj-assert {1==$gotExt} "Else we cannot have gotten this far"
@@ -377,24 +454,11 @@ proc teaish__configure_phase1 {} {
     }
   }}; # --[exec-]prefix defaults
   teaish__check_common_bins
-
   #
   # Set up library file names
   #
   proj-file-extensions
-  apply {{} {
-    set name [teaish-pkginfo-get -name]; # _not_ -pkgName
-    set pkgver [teaish-pkginfo-get -version]
-    set libname "lib"
-    if {[string match *-cygwin [get-define host]]} {
-      set libname cyg
-    }
-    define TEAISH_DLL8_BASENAME $libname$name$pkgver
-    define TEAISH_DLL9_BASENAME ${libname}tcl9$name$pkgver
-    set ext [get-define TARGET_DLLEXT]
-    define TEAISH_DLL8 [get-define TEAISH_DLL8_BASENAME]$ext
-    define TEAISH_DLL9 [get-define TEAISH_DLL9_BASENAME]$ext
-  }}
+  teaish__define_pkginfo_derived *
 
   teaish-checks-run -pre
   if {[llength [info proc teaish-configure]] > 0} {
@@ -404,25 +468,50 @@ proc teaish__configure_phase1 {} {
   }
   teaish-checks-run -post
 
-  if {0} {
-    # Reminder: we cannot do a TEAISH_VSATISFIES_TCL check like the
-    # following from here because _this_ tcl instance is very possibly
-    # not the one which will be hosting the extension. This part might
-    # be running in JimTcl, which can't load the being-configured
-    # extension.
-    if {$::autosetup(istcl)} {
-      # ^^^ this is a canonical Tcl, not JimTcl
-      set vsat [get-define TEAISH_VSATISFIES_TCL ""]
-      if {$vsat ne ""
-          && ![package vsatisfies [package provide Tcl] $vsat]} {
-        error [join [list "Tcl package vsatisfies failed for" \
-                       [teaish-pkginfo-get -name] \
-                       [teaish-pkginfo-get -version] \
-                       ": expecting vsatisfies to match ($vsat)"]]
+  apply {{} {
+    # Set up "vsatisfies" code for pkgIndex.tcl.in,
+    # teaish.tester.tcl.in, and for a configure-time check.  We would
+    # like to put this before [teaish-checks-run -pre] but it's
+    # marginally conceivable that a client may need to dynamically
+    # calculate the vsatisfies and set it via [teaish-configure].
+    set vs [get-define TEAISH_VSATISFIES ""]
+    if {"" eq $vs} return
+    set code {}
+    set n 0
+    # Treat $vs as a list-of-lists {{Tcl 8.5-} {Foo 1.0- -3.0} ...}
+    # and generate Tcl which will run package vsatisfies tests with
+    # that info.
+    foreach pv $vs {
+      set n [llength $pv]
+      if {$n < 2} {
+        proj-error "-vsatisfies: {$pv} appears malformed. Whole list is: $vs"
       }
-      unset vsat
-    }
+      set pkg [lindex $pv 0]
+      set vcheck {}
+      for {set i 1} {$i < $n} {incr i} {
+        lappend vcheck [lindex $pv $i]
+      }
+      if {[opt-bool teaish-vsatisfies-check]} {
+        set tclsh [get-define TCLSH_CMD]
+        set vsat "package vsatisfies \[ package provide $pkg \] $vcheck"
+        set vputs "puts \[ $vsat \]"
+        #puts "*** vputs = $vputs"
+        scan [exec echo $vputs | $tclsh] %d vvcheck
+        if {0 == $vvcheck} {
+          proj-fatal -up $tclsh "check failed:" $vsat
+        }
+      }
+      lappend code [string trim [subst -nocommands -nobackslashes {
+if { ![package vsatisfies [package provide $pkg] $vcheck] } {
+  if {$::teaish__Config(vsatisfies-error)} {
+    error {Package $::teaish__PkgInfo(-name) $::teaish__PkgInfo(-version) requires $pv}
+  } else {
+    return
   }
+}}]]
+    }; # foreach pv
+    define TEAISH_VSATISFIES_CODE [join $code "\n"]
+  }}; # vsatisfies
 
   if {[proj-looks-like-windows]} {
     # Without this, linking of an extension will not work on Cygwin or
@@ -458,43 +547,44 @@ proc teaish__configure_phase1 {} {
     }
   }}; # $::teaish__Config(pkgindex-policy)
 
-  set dEx $::teaish__Config(extension-dir)
-  set dSrc $::autosetup(srcdir)
-
-  proj-dot-ins-append $dSrc/Makefile.in
-  proj-dot-ins-append $dSrc/teaish.tester.tcl.in
+  #
+  # Ensure we clean up TEAISH_PKGINIT_TCL if needed and @-process
+  # TEAISH_PKGINIT_TCL_IN if needed.
+  #
+  if {0x0f & $::teaish__Config(pkginit-policy)} {
+    file delete -force -- [get-define TEAISH_PKGINIT_TCL]
+    proj-dot-ins-append [get-define TEAISH_PKGINIT_TCL_IN]
+  }
 
   apply {{} {
-    set vs [get-define TEAISH_VSATISFIES ""]
-    if {"" eq $vs} return
-    # Treat as a list-of-lists {{Tcl 8.5-} {Foo 1.0- -3.0} ...} and
-    # generate Tcl which will run package vsatisfies tests with that
-    # info.
-    set code {}
-    set n 0
-    foreach pv $vs {
-      set n [llength $pv]
-      if {$n < 2} {
-        proj-error "-vsatisfies: {$pv} appears malformed. Whole list is: $vs"
-      }
-      set ifpv [list if \{ "!\[package vsatisfies \[package provide"]
-      lappend ifpv [lindex $pv 0] "\]"
-      for {set i 1} {$i < $n} {incr i} {
-        lappend ifpv [lindex $pv $i]
+    # Queue up any remaining dot-in files
+    set dotIns [list]
+    foreach d {
+      TEAISH_TESTER_TCL_IN
+      TEAISH_TEST_TCL_IN
+      TEAISH_MAKEFILE_IN
+    } {
+      lappend dotIns [get-define $d ""]
+    }
+    lappend dotIns $::autosetup(srcdir)/Makefile.in; # must be after TEAISH_MAKEFILE_IN
+    foreach f $dotIns {
+      if {"" ne $f} {
+        proj-dot-ins-append $f
       }
-      lappend ifpv "\] \} \{\n"
-      lappend ifpv \
-        "error \{Package $::teaish__PkgInfo(-name) $::teaish__PkgInfo(-version) requires $pv\}\n" \
-        "\}"
-      lappend code [join $ifpv]
     }
-    define TEAISH_VSATISFIES_CODE [join $code "\n"]
   }}
 
+  define TEAISH_DIST_FULL \
+    [expr {
+           $::teaish__Config(dist-enabled)
+           && $::teaish__Config(dist-full-enabled)
+         }]
+
+  define TEAISH_AUTOSETUP_DIR  $::teaish__Config(core-dir)
   define TEAISH_ENABLE_DIST    $::teaish__Config(dist-enabled)
   define TEAISH_ENABLE_DLL     $::teaish__Config(dll-enabled)
-  define TEAISH_AUTOSETUP_DIR  $::teaish__Config(core-dir)
   define TEAISH_TCL            $::teaish__Config(teaish.tcl)
+
   define TEAISH_DIST_FILES     [join $::teaish__Config(dist-files)]
   define TEAISH_EXT_DIR        [join $::teaish__Config(extension-dir)]
   define TEAISH_EXT_SRC        [join $::teaish__Config(extension-src)]
@@ -533,7 +623,7 @@ proc teaish__configure_phase1 {} {
   # the configure process.
   #
   #proj-file-write $::autosetup(builddir)/.configured ""
-}
+}; # teaish__configure_phase1
 
 #
 # Run checks for required binaries.
@@ -581,65 +671,72 @@ proc teaish__check_tcl {} {
   set srcdir $::autosetup(srcdir)
   msg-result "Checking for a suitable tcl... "
   set use_tcl 1
-  set with_tclsh [opt-val with-tclsh [proj-get-env TCLSH]]
-  set with_tcl [opt-val with-tcl [proj-get-env TCL_HOME]]
+  set withSh [opt-val with-tclsh [proj-get-env TCLSH]]
+  set tclHome [opt-val with-tcl [proj-get-env TCL_HOME]]
+  if {[string match */lib $tclHome]} {
+    # TEA compatibility kludge: its --with-tcl wants the lib
+    # dir containing tclConfig.sh.
+    #proj-warn "Replacing --with-tcl=$tclHome for TEA compatibility"
+    regsub {/lib^} $tclHome "" tclHome
+    msg-result "NOTE: stripped /lib suffix from --with-tcl=$tclHome (a TEA-ism)"
+  }
   if {0} {
     # This misinteracts with the $TCL_PREFIX default: it will use the
     # autosetup-defined --prefix default
-    if {"prefix" eq $with_tcl} {
-      set with_tcl [get-define prefix]
+    if {"prefix" eq $tclHome} {
+      set tclHome [get-define prefix]
     }
   }
   teaish-debug "use_tcl ${use_tcl}"
-  teaish-debug "with_tclsh=${with_tclsh}"
-  teaish-debug "with_tcl=$with_tcl"
-  if {"" eq $with_tclsh && "" eq $with_tcl} {
+  teaish-debug "withSh=${withSh}"
+  teaish-debug "tclHome=$tclHome"
+  if {"" eq $withSh && "" eq $tclHome} {
     # If neither --with-tclsh nor --with-tcl are provided, try to find
     # a workable tclsh.
-    set with_tclsh [proj-first-bin-of tclsh9.1 tclsh9.0 tclsh8.6 tclsh]
-    teaish-debug "with_tclsh=${with_tclsh}"
+    set withSh [proj-first-bin-of tclsh9.1 tclsh9.0 tclsh8.6 tclsh]
+    teaish-debug "withSh=${withSh}"
   }
 
   set doConfigLookup 1 ; # set to 0 to test the tclConfig.sh-not-found cases
-  if {"" ne $with_tclsh} {
+  if {"" ne $withSh} {
     # --with-tclsh was provided or found above. Validate it and use it
     # to trump any value passed via --with-tcl=DIR.
-    if {![file-isexec $with_tclsh]} {
-      proj-error "TCL shell $with_tclsh is not executable"
+    if {![file-isexec $withSh]} {
+      proj-error "TCL shell $withSh is not executable"
     } else {
-      define TCLSH_CMD $with_tclsh
-      #msg-result "Using tclsh: $with_tclsh"
+      define TCLSH_CMD $withSh
+      #msg-result "Using tclsh: $withSh"
     }
     if {$doConfigLookup &&
-        [catch {exec $with_tclsh $::autosetup(libdir)/find_tclconfig.tcl} result] == 0} {
-      set with_tcl $result
+        [catch {exec $withSh $::autosetup(libdir)/find_tclconfig.tcl} result] == 0} {
+      set tclHome $result
     }
-    if {"" ne $with_tcl && [file isdirectory $with_tcl]} {
-      teaish__verbose 1 msg-result "$with_tclsh recommends the tclConfig.sh from $with_tcl"
+    if {"" ne $tclHome && [file isdirectory $tclHome]} {
+      teaish__verbose 1 msg-result "$withSh recommends the tclConfig.sh from $tclHome"
     } else {
-      proj-warn "$with_tclsh is unable to recommend a tclConfig.sh"
+      proj-warn "$withSh is unable to recommend a tclConfig.sh"
       set use_tcl 0
     }
   }
   set cfg ""
-  set tclSubdirs {tcl9.1 tcl9.0 tcl8.6 lib}
+  set tclSubdirs {tcl9.1 tcl9.0 tcl8.6 tcl8.5 lib}
   while {$use_tcl} {
-    if {"" ne $with_tcl} {
-      # Ensure that we can find tclConfig.sh under ${with_tcl}/...
+    if {"" ne $tclHome} {
+      # Ensure that we can find tclConfig.sh under ${tclHome}/...
       if {$doConfigLookup} {
-        if {[file readable "${with_tcl}/tclConfig.sh"]} {
-          set cfg "${with_tcl}/tclConfig.sh"
+        if {[file readable "${tclHome}/tclConfig.sh"]} {
+          set cfg "${tclHome}/tclConfig.sh"
         } else {
           foreach i $tclSubdirs {
-            if {[file readable "${with_tcl}/$i/tclConfig.sh"]} {
-              set cfg "${with_tcl}/$i/tclConfig.sh"
+            if {[file readable "${tclHome}/$i/tclConfig.sh"]} {
+              set cfg "${tclHome}/$i/tclConfig.sh"
               break
             }
           }
         }
       }
       if {"" eq $cfg} {
-        proj-error "No tclConfig.sh found under ${with_tcl}"
+        proj-error "No tclConfig.sh found under ${tclHome}"
       }
     } else {
       # If we have not yet found a tclConfig.sh file, look in $libdir
@@ -663,14 +760,14 @@ proc teaish__check_tcl {} {
     }
     teaish__verbose 1 msg-result "Using tclConfig.sh = $cfg"
     break
-  }
+  }; # while {$use_tcl}
   define TCL_CONFIG_SH $cfg
   # Export a subset of tclConfig.sh to the current TCL-space.  If $cfg
   # is an empty string, this emits empty-string entries for the
   # various options we're interested in.
   proj-tclConfig-sh-to-autosetup $cfg
 
-  if {"" eq $with_tclsh && $cfg ne ""} {
+  if {"" eq $withSh && $cfg ne ""} {
     # We have tclConfig.sh but no tclsh. Attempt to locate a tclsh
     # based on info from tclConfig.sh.
     set tclExecPrefix [get-define TCL_EXEC_PREFIX]
@@ -680,23 +777,23 @@ proc teaish__check_tcl {} {
                     $tclExecPrefix/bin/tclsh ]
     foreach trySh $tryThese {
       if {[file-isexec $trySh]} {
-        set with_tclsh $trySh
+        set withSh $trySh
         break
       }
     }
-    if {![file-isexec $with_tclsh]} {
+    if {![file-isexec $withSh]} {
       proj-warn "Cannot find a usable tclsh (tried: $tryThese)"
     }
   }
-  define TCLSH_CMD $with_tclsh
+  define TCLSH_CMD $withSh
   if {$use_tcl} {
     # Set up the TCLLIBDIR
     set tcllibdir [get-env TCLLIBDIR ""]
     set extDirName [get-define TEAISH_LIBDIR_NAME]
     if {"" eq $tcllibdir} {
       # Attempt to extract TCLLIBDIR from TCL's $auto_path
-      if {"" ne $with_tclsh &&
-          [catch {exec echo "puts stdout \$auto_path" | "$with_tclsh"} result] == 0} {
+      if {"" ne $withSh &&
+          [catch {exec echo "puts stdout \$auto_path" | "$withSh"} result] == 0} {
         foreach i $result {
           if {[file isdirectory $i]} {
             set tcllibdir $i/$extDirName
@@ -710,8 +807,8 @@ proc teaish__check_tcl {} {
     define TCLLIBDIR $tcllibdir
   }; # find TCLLIBDIR
 
-  if {[file-isexec $with_tclsh]} {
-    teaish__verbose 1 msg-result "Using tclsh        = $with_tclsh"
+  if {[file-isexec $withSh]} {
+    teaish__verbose 1 msg-result "Using tclsh        = $withSh"
     if {$cfg ne ""} {
       define HAVE_TCL 1
     } else {
@@ -723,17 +820,17 @@ proc teaish__check_tcl {} {
   # fatally, else just emit a warning. If we can find the APIs needed
   # to generate a working JimTCL then that will suffice for build-time
   # TCL purposes (see: proc sqlite-determine-codegen-tcl).
-  if {![file-isexec $with_tclsh]} {
+  if {![file-isexec $withSh]} {
     proj-error "Did not find tclsh"
   } elseif {"" eq $cfg} {
     proj-indented-notice -error {
       Cannot find a usable tclConfig.sh file.  Use
-      --with-tcl=DIR to specify a directory where tclConfig.sh can be
+      --with-tcl=DIR to specify a directory near which tclConfig.sh can be
       found, or --with-tclsh=/path/to/tclsh to allow the tclsh binary
       to locate its tclConfig.sh.
     }
   }
-  msg-result "Using Tcl [get-define TCL_VERSION]."
+  msg-result "Using Tcl [get-define TCL_VERSION] from [get-define TCL_PREFIX]."
 }; # teaish__check_tcl
 
 #
@@ -743,16 +840,16 @@ proc teaish__check_tcl {} {
 # not find an extension but the --help flag was seen, in which case
 # that's not an error.
 #
-# This does not _load_ the extension, it simply locates the files
-# which make up an extension.
-#
-# This sets up lots of defines, e.g. TEAISH_EXT_DIR.
+# This does not _load_ the extension, it primarily locates the files
+# which make up an extension and fills out no small amount of teaish
+# state related to that.
 #
 proc teaish__find_extension {} {
-
+  proj-assert {!$::teaish__Config(install-mode)}
   teaish__verbose 1 msg-result "Looking for teaish extension..."
+
   # Helper for the foreach loop below.
-  set lambdaMT {{mustHave fid dir} {
+  set checkTeaishTcl {{mustHave fid dir} {
     if {[file isdirectory $dir]} {
       set f [file join $dir $fid]
       if {[file readable $f]} {
@@ -765,12 +862,12 @@ proc teaish__find_extension {} {
     }
     return ""
   }}
+
   #
   # We have to handle some flags manually because the extension must
   # be loaded before [options] is run (so that the extension can
   # inject its own options).
   #
-  #set extM ""; # teaish.make.in
   set dirBld $::autosetup(builddir); # dir we're configuring under
   set dirSrc $::autosetup(srcdir);   # where teaish's configure script lives
   set extT ""; # teaish.tcl
@@ -789,11 +886,12 @@ proc teaish__find_extension {} {
         if {![file isdirectory $extD]} {
           proj-error "--teaish-extension-dir value is not a directory: $extD"
         }
-        set extT [apply $lambdaMT 1 teaish.tcl $extD]
+        set extT [apply $checkTeaishTcl 1 teaish.tcl $extD]
         set ::teaish__Config(extension-dir) $extD
       }
       --help {
         incr gotHelpArg
+        lappend largv $arg
       }
       default {
         lappend largv $arg
@@ -802,9 +900,7 @@ proc teaish__find_extension {} {
   }
   set ::argv $largv
 
-  set dirExt [proj-coalesce \
-                $::teaish__Config(extension-dir) \
-                $dirBld]; # dir with the extension
+  set dirExt $::teaish__Config(extension-dir); # dir with the extension
   #
   # teaish.tcl is a TCL script which implements various
   # interfaces described by this framework.
@@ -812,14 +908,13 @@ proc teaish__find_extension {} {
   # We use the first one we find in the builddir or srcdir.
   #
   if {"" eq $extT} {
-    set flist [list $dirExt/teaish.tcl]
-    if {$dirExt ne $dirSrc} {
-      lappend flist $dirSrc/teaish.tcl
-    }
+    set flist [list]
+    proj-assert {$dirExt eq ""}
+    lappend flist $dirBld/teaish.tcl $dirSrc/teaish.tcl
     if {![proj-first-file-found extT $flist]} {
       if {$gotHelpArg} {
         # Tell teaish-configure-core that the lack of extension is not
-        # an error when --help is used.
+        # an error when --help or --teaish-install is used.
         return 0;
       }
       proj-indented-notice -error "
@@ -833,17 +928,14 @@ If you are attempting an out-of-tree build, use
     proj-error "extension tcl file is not readable: $extT"
   }
   set ::teaish__Config(teaish.tcl) $extT
-
-  if {"" eq $dirExt} {
-    # If this wasn't set via --teaish-extension-dir then derive it from
-    # $extT.
-    #puts "extT=$extT dirExt=$dirExt"
-    set dirExt [file dirname $extT]
-  }
+  set dirExt [file dirname $extT]
 
   set ::teaish__Config(extension-dir) $dirExt
   set ::teaish__Config(blddir-is-extdir) [expr {$dirBld eq $dirExt}]
   set ::teaish__Config(dist-enabled) $::teaish__Config(blddir-is-extdir); # may change later
+  set ::teaish__Config(dist-full-enabled) \
+    [expr {[file-normalize $::autosetup(srcdir)]
+           eq [file-normalize $::teaish__Config(extension-dir)]}]
 
   set addDist {{file} {
     teaish-dist-add [file tail $file]
@@ -863,55 +955,65 @@ If you are attempting an out-of-tree build, use
   # $dirExt.
   #
   if {[proj-first-file-found extM \
-         [list $dirExt/teaish.make.in $dirExt/teaish.make]]} {
+         [list \
+            $dirExt/teaish.make.in \
+            $dirExt/teaish.make \
+         ]]} {
     if {[string match *.in $extM]} {
       define TEAISH_MAKEFILE_IN $extM
       define TEAISH_MAKEFILE [file rootname [file tail $extM]]
-      proj-dot-ins-append $extM [get-define TEAISH_MAKEFILE]
     } else {
       define TEAISH_MAKEFILE_IN ""
       define TEAISH_MAKEFILE $extM
     }
     apply $addDist $extM
-    teaish__verbose 1 msg-result "Extension makefile      = $extM"
+    teaish__verbose 1 msg-result "Extension makefile       = $extM"
   } else {
     define TEAISH_MAKEFILE_IN ""
     define TEAISH_MAKEFILE ""
   }
 
   # Look for teaish.pkginit.tcl[.in]
+  set piPolicy 0
   if {[proj-first-file-found extI \
-         [list $dirExt/teaish.pkginit.tcl.in $dirExt/teaish.pkginit.tcl]]} {
+         [list \
+            $dirExt/teaish.pkginit.tcl.in \
+            $dirExt/teaish.pkginit.tcl \
+           ]]} {
     if {[string match *.in $extI]} {
-      proj-dot-ins-append $extI
+      # Generate teaish.pkginit.tcl from $extI.
       define TEAISH_PKGINIT_TCL_IN $extI
-      define TEAISH_PKGINIT_TCL [file tail [file rootname $extI]]
+      define TEAISH_PKGINIT_TCL [file rootname [file tail $extI]]
+      set piPolicy 0x01
     } else {
+      # Assume static $extI.
       define TEAISH_PKGINIT_TCL_IN ""
       define TEAISH_PKGINIT_TCL $extI
+      set piPolicy 0x10
     }
     apply $addDist $extI
     teaish__verbose 1 msg-result "Extension post-load init = $extI"
     define TEAISH_PKGINIT_TCL_TAIL \
       [file tail [get-define TEAISH_PKGINIT_TCL]]; # for use in pkgIndex.tcl.in
   }
+  set ::teaish__Config(pkginit-policy) $piPolicy
 
   # Look for pkgIndex.tcl[.in]...
   set piPolicy 0
   if {[proj-first-file-found extPI $dirExt/pkgIndex.tcl.in]} {
-    # Generate ./pkgIndex.tcl from it.
+    # Generate ./pkgIndex.tcl from $extPI.
     define TEAISH_PKGINDEX_TCL_IN $extPI
     define TEAISH_PKGINDEX_TCL [file rootname [file tail $extPI]]
     apply $addDist $extPI
     set piPolicy 0x01
   } elseif {$dirExt ne $dirSrc
             && [proj-first-file-found extPI $dirSrc/pkgIndex.tcl.in]} {
-    # Generate ./pkgIndex.tcl from it.
+    # Generate ./pkgIndex.tcl from $extPI.
     define TEAISH_PKGINDEX_TCL_IN $extPI
     define TEAISH_PKGINDEX_TCL [file rootname [file tail $extPI]]
     set piPolicy 0x02
   } elseif {[proj-first-file-found extPI $dirExt/pkgIndex.tcl]} {
-    # Assume it's a static file and use it.
+    # Assume $extPI's a static file and use it.
     define TEAISH_PKGINDEX_TCL_IN ""
     define TEAISH_PKGINDEX_TCL $extPI
     apply $addDist $extPI
@@ -932,7 +1034,6 @@ If you are attempting an out-of-tree build, use
       file delete -force -- $xt; # ensure no stale copy is used
       define TEAISH_TEST_TCL $xt
       define TEAISH_TEST_TCL_IN $ttt
-      proj-dot-ins-append $ttt $xt
     } else {
       define TEAISH_TEST_TCL $ttt
       define TEAISH_TEST_TCL_IN ""
@@ -951,18 +1052,21 @@ If you are attempting an out-of-tree build, use
     file delete -force -- $xt; # ensure no stale copy is used
     define TEAISH_TESTER_TCL $xt
     define TEAISH_TESTER_TCL_IN $ttt
-    proj-dot-ins-append $ttt $xt
     if {[lindex $flist 0] eq $ttt} {
       apply $addDist $ttt
     }
+    unset ttt xt
   } else {
-    set ttt [file join $dirSrc teaish.tester.tcl.in]
-    set xt [file rootname [file tail $ttt]]
-    proj-dot-ins-append $ttt $xt
-    define TEAISH_TESTER_TCL $xt
-    define TEAISH_TESTER_TCL_IN $ttt
+    if {[file exists [set ttt [file join $dirSrc teaish.tester.tcl.in]]]} {
+      set xt [file rootname [file tail $ttt]]
+      define TEAISH_TESTER_TCL $xt
+      define TEAISH_TESTER_TCL_IN $ttt
+    } else {
+      define TEAISH_TESTER_TCL ""
+      define TEAISH_TESTER_TCL_IN ""
+    }
   }
-  unset flist xt ttt
+  unset flist
 
   # TEAISH_OUT_OF_EXT_TREE = 1 if we're building from a dir other
   # than the extension's home dir.
@@ -982,14 +1086,73 @@ proc teaish-cflags-add {args} {
 }
 
 #
-# @teaish-define-to-cflag defineName...
+# @teaish-define-to-cflag ?flags? defineName...|{defineName...}
 #
 # Uses [proj-define-to-cflag] to expand a list of [define] keys, each
 # one a separate argument, to CFLAGS-style -D... form then appends
 # that to the current TEAISH_CFLAGS.
 #
+# It accepts these flags from proj-define-to-cflag: -quote,
+# -zero-undef. It does _not_ support its -list flag.
+#
+# It accepts its non-flag argument(s) in 2 forms: (1) each arg is a
+# single [define] key or (2) its one arg is a list of such keys.
+#
+# TODO: document teaish's well-defined (as it were) defines for this
+# purpose. At a bare minimum:
+#
+#  - TEAISH_NAME
+#  - TEAISH_PKGNAME
+#  - TEAISH_VERSION
+#  - TEAISH_LIBDIR_NAME
+#  - TEAISH_LOAD_PREFIX
+#  - TEAISH_URL
+#
 proc teaish-define-to-cflag {args} {
-  teaish-cflags-add [proj-define-to-cflag {*}$args]
+  set flags {}
+  while {[string match -* [lindex $args 0]]} {
+    set arg [lindex $args 0]
+    switch -exact -- $arg {
+      -quote -
+      -zero-undef {
+        lappend flags $arg
+        set args [lassign $args -]
+      }
+      default break
+    }
+  }
+  if {1 == [llength $args]} {
+    set args [list {*}[lindex $args 0]]
+  }
+  #puts "***** flags=$flags args=$args"
+  teaish-cflags-add [proj-define-to-cflag {*}$flags {*}$args]
+}
+
+#
+# @teaish-cflags-for-tea ?...CFLAGS?
+#
+# Adds several -DPACKAGE_... CFLAGS using the extension's metadata,
+# all as quoted strings. Those symbolic names are commonly used in
+# TEA-based builds, and this function is intended to simplify porting
+# of such builds. The -D... flags added are:
+#
+#  -DPACKAGE_VERSION=...
+#  -DPACKAGE_NAME=...
+#  -DPACKAGE_URL=...
+#  -DPACKAGE_STRING=...
+#
+# Any arguments are passed-on as-is to teaish-cflags-add.
+#
+proc teaish-cflags-for-tea {args} {
+  set name $::teaish__PkgInfo(-name)
+  set version $::teaish__PkgInfo(-version)
+  set pstr [join [list $name $version]]
+  teaish-cflags-add \
+    {*}$args \
+    '-DPACKAGE_VERSION="$version"' \
+    '-DPACKAGE_NAME="$name"' \
+    '-DPACKAGE_STRING="$pstr"' \
+    '-DPACKAGE_URL="[teaish-get -url]"'
 }
 
 #
@@ -1020,17 +1183,18 @@ proc teaish-ldflags-prepend {args} {
 #
 # @teaish-src-add ?-dist? ?-dir? src-files...
 #
-# Appends all non-empty $args to the project's list of C/C++ source
-# files.
+# Appends all non-empty $args to the project's list of C/C++ source or
+# (in some cases) object files.
 #
 # If passed -dist then it also passes each filename, as-is, to
 # [teaish-dist-add].
 #
 # If passed -dir then each src-file has [teaish-get -dir] prepended to
-# it for before they're added to the list. As often as not, that will
-# be the desired behavior so that out-of-tree builds can find the
+# it before they're added to the list. As often as not, that will be
+# the desired behavior so that out-of-tree builds can find the
 # sources, but there are cases where it's not desired (e.g. when using
-# a source file from outside of the extension's dir).
+# a source file from outside of the extension's dir, or when adding
+# object files (which are typically in the build tree)).
 #
 proc teaish-src-add {args} {
   set i 0
@@ -1070,6 +1234,7 @@ proc teaish-dist-add {args} {
     # ^^^ reminder: we ignore $::teaish__Config(dist-enabled) here
     # because the client might want to implement their own dist
     # rules.
+    #proj-warn "**** args=$args"
     lappend ::teaish__Config(dist-files) {*}$args
   }
 }
@@ -1089,18 +1254,19 @@ proc teaish-dist-add {args} {
 # -tab: emit a literal tab
 # -nl: emit a literal newline
 # -nltab: short for -nl -tab
-# -eol: emit a backslash-escaped end-of-line
-# -eoltab: short for -eol -tab
+# -bnl: emit a backslash-escaped end-of-line
+# -bnltab: short for -eol -tab
 #
 # Anything else is appended verbatim. This function adds no additional
 # spacing between each argument nor between subsequent invocations.
-#
+# Generally speaking, a series of calls to this function need to
+# be sure to end the series with a newline.
 proc teaish-make-add {args} {
   set out [get-define TEAISH_MAKEFILE_CODE ""]
   foreach a $args {
     switch -exact -- $a {
-      -eol    { set a " \\\n" }
-      -eoltab { set a " \\\n\t" }
+      -bnl    { set a " \\\n" }
+      -bnltab { set a " \\\n\t" }
       -tab    { set a "\t" }
       -nl     { set a "\n" }
       -nltab  { set a "\n\t" }
@@ -1110,6 +1276,116 @@ proc teaish-make-add {args} {
   define TEAISH_MAKEFILE_CODE $out
 }
 
+# Internal helper to generate a clean/distclean rule name
+proc teaish__cleanup_rule {{tgt clean}} {
+  set x [incr ::teaish__Config(teaish__cleanup_rule-counter-${tgt})]
+  return ${tgt}-_${x}_
+}
+
+# @teaish-make-obj objfile srcfile ?...args?
+#
+# Uses teaish-make-add to inject makefile rules for $objfile from
+# $srcfile, which is assumed to be C code which uses libtcl. Unless
+# -recipe is used (see below) it invokes the compiler using the
+# makefile-defined $(CC.tcl) which, in the default Makefile.in
+# template, includes any flags needed for building against the
+# configured Tcl.
+#
+# This always terminates the resulting code with a newline.
+#
+# Any arguments after the 2nd may be flags described below or, if no
+# -recipe is provided, flags for the compiler call.
+#
+#   -recipe {...}
+#   Uses the trimmed value of {...} as the recipe, prefixing it with
+#   a single hard-tab character.
+#
+#   -deps {...}
+#   List of extra files to list as dependencies of $o. Good luck
+#   escaping non-trivial cases properly.
+#
+#   -clean
+#   Generate cleanup rules as well.
+proc teaish-make-obj {o src args} {
+  set consume 0
+  set clean 0
+  set flag ""
+  array set flags {}
+  set xargs {}
+  foreach arg $args {
+    if {$consume} {
+      set consume 0
+      set flags($flag) $arg
+      continue
+    }
+    switch -exact -- $arg {
+      -clean {incr clean}
+      -recipe -
+      -deps {
+        set flag $arg
+        incr consume
+      }
+      default {
+        lappend xargs $arg
+      }
+    }
+  }
+  teaish-make-add \
+    "# [proj-current-scope 1] -> [proj-current-scope] $o $src" -nl \
+    "$o: $src $::teaish__Config(teaish.tcl)"
+  if {[info exists flags(-deps)]} {
+    teaish-make-add " " [join $flags(-deps)]
+  }
+  teaish-make-add -nltab
+  if {[info exists flags(-recipe)]} {
+    teaish-make-add [string trim $flags(-recipe)] -nl
+  } else {
+    teaish-make-add [join [list \$(CC.tcl) -c $src {*}$xargs]] -nl
+  }
+  if {$clean} {
+    set rule [teaish__cleanup_rule]
+    teaish-make-add \
+      "clean: $rule\n$rule:\n\trm -f \"$o\"\n"
+  }
+}
+
+#
+# @teaish-make-clean ?-r? ?-dist? ...files|{...files}
+#
+# Adds makefile rules for cleaning up the given files via the "make
+# clean" or (if -dist is used) "make distclean" makefile rules. The -r
+# flag uses "rm -fr" instead of "rm -f", so be careful with that.
+#
+# The file names are taken literally as arguments to "rm", so they may
+# be shell wildcards to be resolved at cleanup-time. To clean up whole
+# directories, pass the -r flag. Each name gets quoted in
+# double-quotes, so spaces in names should not be a problem (but
+# double-quotes in names will be).
+#
+proc teaish-make-clean {args} {
+  if {1 == [llength $args]} {
+    set args [list {*}[lindex $args 0]]
+  }
+
+  set tgt clean
+  set rmflags "-f"
+  proj-parse-simple-flags args flags {
+    -dist 0 {
+      set tgt distclean
+    }
+    -r 0 {
+      set rmflags "-fr"
+    }
+  }
+  set rule [teaish__cleanup_rule $tgt]
+  teaish-make-add "# [proj-current-scope 1] -> [proj-current-scope]: [join $args]\n"
+  teaish-make-add "${rule}:\n\trm ${rmflags}"
+  foreach a $args {
+    teaish-make-add " \"$a\""
+  }
+  teaish-make-add "\n${tgt}: ${rule}\n"
+}
+
 #
 # @teaish-make-config-header filename
 #
@@ -1344,7 +1620,7 @@ proc teaish__dump_defs_to_list {args} {
 }
 
 #
-# @teaish__pragma ...flags
+# teaish__pragma ...flags
 #
 # Offers a way to tweak how teaish's core behaves in some cases, in
 # particular those which require changing how the core looks for an
@@ -1365,6 +1641,19 @@ proc teaish__dump_defs_to_list {args} {
 #    no-dll [L]: tells teaish to elide the DLL-building recipe
 #    from the generated Makefile.
 #
+#    no-vsatisfies-error [L]: tells teaish that failure to match the
+#    -vsatisfies value should simply "return" instead of "error".
+#
+#    no-tester [L]: disables automatic generation of teaish.test.tcl
+#    even if a copy of teaish.tester.tcl.in is found.
+#
+#    no-full-dist [L]: changes the "make dist" rules to never include
+#    a copy of teaish itself. By default it will include itself only
+#    if the extension lives in the same directory as teaish.
+#
+#    full-dist [L]: changes the "make dist" rules to always include
+#    a copy of teaish itself.
+#
 # Emits a warning message for unknown arguments.
 #
 proc teaish__pragma {args} {
@@ -1386,10 +1675,27 @@ proc teaish__pragma {args} {
         set ::teaish__Config(dist-enabled) 0
       }
 
+      full-dist {
+        set ::teaish__Config(dist-full-enabled) 1
+      }
+
+      no-full-dist {
+        set ::teaish__Config(dist-full-enabled) 0
+      }
+
       no-dll {
         set ::teaish__Config(dll-enabled) 0
       }
 
+      no-vsatisfies-error {
+        set ::teaish__Config(vsatisfies-error) 0
+      }
+
+      no-tester {
+        define TEAISH_TESTER_TCL_IN ""
+        define TEAISH_TESTER_TCL ""
+      }
+
       default {
         proj-error "Unknown flag: $arg"
       }
@@ -1430,7 +1736,7 @@ proc teaish__pragma {args} {
 #     directory containing the extension. (In TEA this would be the
 #     PACKAGE_NAME, not to be confused with...)
 #
-#    -pkgName pkg-provide-name: The extension's name for purposes of
+#    -name.pkg pkg-provide-name: The extension's name for purposes of
 #     Tcl_PkgProvide(), [package require], and friends. It defaults to
 #     the `-name`, and is normally the same, but some projects (like
 #     SQLite) have a different name here than they do in their
@@ -1441,11 +1747,11 @@ proc teaish__pragma {args} {
 #
 #    -libDir dirName: The base name of the directory into which this
 #     extension should be installed. It defaults to a concatenation of
-#     `-pkgName` and `-version`.
+#     `-name.pkg` and `-version`.
 #
 #    -loadPrefix prefix: For use as the second argument passed to
 #     Tcl's `load` command in the package-loading process. It defaults
-#     to title-cased `-pkgName` because Tcl's `load` plugin system
+#     to title-cased `-name.pkg` because Tcl's `load` plugin system
 #     expects it in that form.
 #
 #    -options {...}: If provided, it must be a list compatible with
@@ -1468,6 +1774,8 @@ proc teaish__pragma {args} {
 #     order. Failure to meet a `vsatisfies` condition triggers an
 #     error.
 #
+#    -url {...}: an optional URL for the extension.
+#
 #    -pragmas {...}  A list of infrequently-needed lower-level
 #     directives which can influence teaish, including:
 #
@@ -1485,10 +1793,26 @@ proc teaish__pragma {args} {
 #      support script-only extensions.
 #
 # Unsupported flags or pragmas will trigger an error.
+#
+# Potential pothole: setting certain state, e.g. -version, after the
+# initial call requires recalculating of some [define]s. Any such
+# changes should be made as early as possible in teaish-configure so
+# that any later use of those [define]s gets recorded properly (not
+# with the old value).  This is particularly relevant when it is not
+# possible to determine the -version or -name until teaish-configure
+# has been called, and it's updated dynamically from
+# teaish-configure. Notably:
+#
+#   - If -version or -name are updated, -libDir will almost certainly
+#     need to be explicitly set along with them.
+#
+#   - If -name is updated, -loadPrefix probably needs to be as well.
+#
 proc teaish-pkginfo-set {args} {
   set doVars 0
   set doCommands 0
   set xargs $args
+  set recalc {}
   foreach arg $args {
     switch -exact -- $arg {
       -vars {
@@ -1529,30 +1853,58 @@ proc teaish-pkginfo-set {args} {
     proj-error -up "Too many (or unknown) arguments to [proj-current-scope]: $args"
   }
   foreach {f d} $::teaish__Config(pkginfo-f2d) {
-    if {$sentinel ne [set v $flags($f)]} {
-      switch -exact -- $f {
-        -options {
-          proj-assert {"" eq $d}
-          options-add $v
-        }
-        -pragmas {
-          foreach p $v {
-            teaish__pragma $p
-          }
-        }
-        -vsatisfies {
-          if {1 == [llength $v] && 1 == [llength [lindex $v 0]]} {
-            # Transform X to {Tcl $X}
-            set v [list [join [list Tcl $v]]]
-          }
-          define $d $v
+    if {$sentinel eq [set v $flags($f)]} continue
+    switch -exact -- $f {
+      -options {
+        proj-assert {"" eq $d}
+        options-add $v
+      }
+      -pragmas {
+        foreach p $v {
+          teaish__pragma $p
         }
-        default {
-          define $d $v
+      }
+      -vsatisfies {
+        if {1 == [llength $v] && 1 == [llength [lindex $v 0]]} {
+          # Transform X to {Tcl $X}
+          set v [list [join [list Tcl $v]]]
         }
+        define $d $v
+      }
+      -pkgInit.tcl.in {
+        # Generate pkginit file X from X.in
+        set ::teaish__Config(pkginit-policy) 0x02
+        set x [file join $::teaish__Config(extension-dir) $v]
+        define TEAISH_PKGINIT_TCL_IN $x
+        set fout [file rootname [file tail $v]]
+        define TEAISH_PKGINIT_TCL $fout
+        define TEAISH_PKGINIT_TCL_TAIL $fout
+        set ::teaish__PkgInfo(-pkgInit.tcl) {}
+        teaish-dist-add $v
+        set v $x
+      }
+      -pkgInit.tcl {
+        # Static pkginit file X
+        set ::teaish__Config(pkginit-policy) 0x20
+        set x [file join $::teaish__Config(extension-dir) $v]
+        define TEAISH_PKGINIT_TCL $x
+        define TEAISH_PKGINIT_TCL_IN ""
+        define TEAISH_PKGINIT_TCL_TAIL [file tail $v]
+        set ::teaish__PkgInfo(-pkgInit.tcl.in) {}
+        teaish-dist-add $v
+        set v $x
+      }
+      default {
+        define $d $v
       }
-      set ::teaish__PkgInfo($f) $v
     }
+    set ::teaish__PkgInfo($f) $v
+    if {$f in {-name -version -libDir -loadPrefix}} {
+      lappend recalc $f
+    }
+  }
+  if {"" ne $recalc} {
+    teaish__define_pkginfo_derived $recalc
   }
 }
 
@@ -1616,12 +1968,40 @@ proc teaish-pkginfo-get {args} {
     }
   }
 
+  set cases [join $cases]
   foreach {flag defName} $::teaish__Config(pkginfo-f2d) {
-    switch -exact -- $flag [join $cases]
+    switch -exact -- $flag $cases
   }
   if {0 == $argc} { return $rv }
 }
 
+# (Re)set some defines based on pkginfo state. $flags is the list of
+# pkginfo -flags which triggered this, or "*" for the initial call.
+proc teaish__define_pkginfo_derived {flags} {
+  set all [expr {{*} in $flags}]
+  if {$all || "-version" in $flags || "-name" in $flags} {
+    set name $::teaish__PkgInfo(-name) ; # _not_ -name.pkg
+    if {[info exists ::teaish__PkgInfo(-version)]} {
+      set pkgver $::teaish__PkgInfo(-version)
+      set libname "lib"
+      if {[string match *-cygwin [get-define host]]} {
+        set libname cyg
+      }
+      define TEAISH_DLL8_BASENAME $libname$name$pkgver
+      define TEAISH_DLL9_BASENAME ${libname}tcl9$name$pkgver
+      set ext [get-define TARGET_DLLEXT]
+      define TEAISH_DLL8 [get-define TEAISH_DLL8_BASENAME]$ext
+      define TEAISH_DLL9 [get-define TEAISH_DLL9_BASENAME]$ext
+    }
+  }
+  if {$all || "-libDir" in $flags} {
+    if {[info exists ::teaish__PkgInfo(-libDir)]} {
+      define TCLLIBDIR \
+        [file dirname [get-define TCLLIBDIR]]/$::teaish__PkgInfo(-libDir)
+    }
+  }
+}
+
 #
 # @teaish-checks-queue -pre|-post args...
 #
@@ -1680,6 +2060,7 @@ proc teaish-checks-run {flag} {
 # Triggers an error if passed an unknown flag.
 #
 proc teaish-get {flag} {
+  #-teaish.tcl {return $::teaish__Config(teaish.tcl)}
   switch -exact -- $flag {
     -dir {
       return $::teaish__Config(extension-dir)
@@ -1690,9 +2071,6 @@ proc teaish-get {flag} {
     -build-dir {
       return $::autosetup(builddir)
     }
-    -teaish.tcl {
-      return $::teaish__Config(teaish.tcl)
-    }
     default {
       if {[info exists ::teaish__PkgInfo($flag)]} {
         return $::teaish__PkgInfo($flag)
@@ -1702,6 +2080,12 @@ proc teaish-get {flag} {
   proj-error "Unhandled flag: $flag"
 }
 
+array set ::teaish__PkgInfoF2D $::teaish__Config(pkginfo-f2d)
+proc teaish__f2d_array {tgtArrayName} {
+  upvar $tgtArrayName tgt
+  set tgt $::teaish__PkgInfoF2D
+}
+
 #
 # Handles --teaish-create-extension=TARGET-DIR
 #
@@ -1710,15 +2094,15 @@ proc teaish__create_extension {dir} {
   if {"" eq $dir} {
     proj-error "--teaish-create-extension=X requires a directory name."
   }
-  file mkdir $dir
+  file mkdir $dir/generic
   set cwd [pwd]
   #set dir [file-normalize [file join $cwd $dir]]
-  msg-result "Created dir $dir"
+  teaish__verbose 1 msg-result "Created dir $dir"
   cd $dir
   if {!$force} {
     # Ensure that we don't blindly overwrite anything
     foreach f {
-      teaish.c
+      generic/teaish.c
       teaish.tcl
       teaish.make.in
       teaish.test.tcl
@@ -1733,15 +2117,35 @@ proc teaish__create_extension {dir} {
   set pkgName $name
   set version 0.0.1
   set loadPrefix [string totitle $pkgName]
-  set content "teaish-pkginfo-set \
-  -name ${name} \
-  -pkgName ${pkgName} \
-  -version ${version} \
-  -loadPrefix $loadPrefix \
-  -libDir ${name}${version}
-  -vsatisfies {{Tcl 8.5-}} \
-  -options { foo=1 => {Disable foo} }
-
+  set content {teaish-pkginfo-set }
+  #puts "0 content=$content"
+  if {[opt-str teaish-extension-pkginfo epi]} {
+    set epi [string trim $epi]
+    if {[string match "*\n*" $epi]} {
+      set epi "{$epi}"
+    } elseif {![string match "{*}" $epi]} {
+      append content "\{" $epi "\}"
+    } else {
+      append content $epi
+    }
+    #puts "2 content=$content\nepi=$epi"
+  } else {
+    append content [subst -nocommands -nobackslashes {{
+      -name ${name}
+      -name.pkg ${pkgName}
+      -name.dist ${pkgName}
+      -version ${version}
+      -loadPrefix $loadPrefix
+      -libDir ${name}${version}
+      -vsatisfies {{Tcl 8.5-}}
+      -url {}
+      -options {}
+      -pragmas {full-dist}
+    }}]
+    #puts "3 content=$content"
+  }
+  #puts "1 content=$content"
+  append content "\n" {
 #proc teaish-options {} {
   # Return a list and/or use \[options-add\] to add new
   # configure flags. This is called before teaish's
@@ -1757,13 +2161,18 @@ proc teaish__create_extension {dir} {
   # not be defined.
 #}
 
+# Called by teaish once bootstrapping is complete.
+# This function is responsible for the client-specific
+# parts of the configuration process.
 proc teaish-configure {} {
-  teaish-src-add -dir -dist teaish.c
+  teaish-src-add -dir -dist generic/teaish.c
+  teaish-define-to-cflag -quote TEAISH_PKGNAME TEAISH_VERSION
+
   # TODO: your code goes here..
 }
-"
+}; # $content
   proj-file-write teaish.tcl $content
-  msg-result "Created teaish.tcl"
+  teaish__verbose 1 msg-result "Created teaish.tcl"
 
   set content "# Teaish test script.
 # When this tcl script is invoked via 'make test' it will have loaded
@@ -1771,7 +2180,7 @@ proc teaish-configure {} {
 # autosetup/teaish/tester.tcl.
 "
   proj-file-write teaish.test.tcl $content
-  msg-result "Created teaish.test.tcl"
+  teaish__verbose 1 msg-result "Created teaish.test.tcl"
 
   set content [subst -nocommands -nobackslashes {
 #include <tcl.h>
@@ -1785,25 +2194,130 @@ extern int DLLEXPORT ${loadPrefix}_Init(Tcl_Interp *interp){
   if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
     return TCL_ERROR;
   }
-  if (Tcl_PkgProvide(interp, "${name}", "${version}") == TCL_ERROR) {
+  if (Tcl_PkgProvide(interp, TEAISH_PKGNAME, TEAISH_VERSION) == TCL_ERROR) {
     return TCL_ERROR;
   }
-  Tcl_CreateObjCommand(interp, "${name}", ${loadPrefix}_Cmd, NULL, NULL);
+  Tcl_CreateObjCommand(interp, TEAISH_PKGNAME, ${loadPrefix}_Cmd, NULL, NULL);
   return TCL_OK;
 }
 }]
-  proj-file-write teaish.c $content
-  msg-result "Created teaish.c"
+  proj-file-write generic/teaish.c $content
+  teaish__verbose 1 msg-result "Created generic/teaish.c"
 
   set content "# teaish makefile for the ${name} extension
-# tx.src      = \$(tx.dir)/teaish.c
+# tx.src      = \$(tx.dir)/generic/teaish.c
 # tx.LDFLAGS  =
 # tx.CFLAGS   =
 "
   proj-file-write teaish.make.in $content
-  msg-result "Created teaish.make.in"
+  teaish__verbose 1 msg-result "Created teaish.make.in"
 
-  msg-result "Created new extension $name in \[$dir]"
+  msg-result "Created new extension $name in \[$dir]."
 
   cd $cwd
+  set ::teaish__Config(install-ext-dir) $dir
+}
+
+#
+# Internal helper for teaish__install
+#
+proc teaish__install_file {f destDir force} {
+  set dest $destDir/[file tail $f]
+  if {[file isdirectory $f]} {
+    file mkdir $dest
+  } elseif {!$force && [file exists $dest]} {
+    array set st1 [file stat $f]
+    array set st2 [file stat $dest]
+    if {($st1(mtime) == $st2(mtime))
+        && ($st1(size) == $st2(size))} {
+      if {[file tail $f] in {
+        pkgIndex.tcl.in
+        teaish.tester.tcl.in
+      }} {
+        # Assume they're the same. In the scope of the "make dist"
+        # rules, this happens legitimately when an extension with a
+        # copy of teaish installed in the same dir assumes that the
+        # pkgIndex.tcl.in and teaish.tester.tcl.in belong to the
+        # extension, whereas teaish believes they belong to teaish.
+        # So we end up with dupes of those.
+        return
+      }
+    }
+    proj-error -up "Cowardly refusing to overwrite \[$dest\]." \
+      "Use --teaish-force to enable overwriting."
+  } else {
+    # file copy -force $f $destDir; # loses +x bit
+    #
+    # JimTcl doesn't have [file attribute], so we can't use that here
+    # (in the context of an autosetup configure script).
+    exec cp -p $f $dest
+  }
+}
+
+#
+# Installs a copy of teaish, with autosetup, to $dDest, which defaults
+# to the --teaish-install=X or --teash-create-extension=X dir. Won't
+# overwrite files unless --teaish-force is used.
+#
+proc teaish__install {{dDest ""}} {
+  if {$dDest in {auto ""}} {
+    set dDest [opt-val teaish-install]
+    if {$dDest in {auto ""}} {
+      if {[info exists ::teaish__Config(install-ext-dir)]} {
+        set dDest $::teaish__Config(install-ext-dir)
+      }
+    }
+  }
+  set force [opt-bool teaish-force]
+  if {$dDest in {auto ""}} {
+    proj-error "Cannot determine installation directory."
+  } elseif {!$force && [file exists $dDest/auto.def]} {
+    proj-error \
+      "Target dir looks like it already contains teaish and/or autosetup: $dDest" \
+      "\nUse --teaish-force to overwrite it."
+  }
+
+  set dSrc $::autosetup(srcdir)
+  set dAS $::autosetup(libdir)
+  set dAST $::teaish__Config(core-dir)
+  set dASTF $dAST/feature
+  teaish__verbose 1 msg-result "Installing teaish to \[$dDest\]..."
+  if {$::teaish__Config(verbose)>1} {
+    msg-result "dSrc  = $dSrc"
+    msg-result "dAS   = $dAS"
+    msg-result "dAST  = $dAST"
+    msg-result "dASTF = $dASTF"
+    msg-result "dDest = $dDest"
+  }
+
+  # Dest subdirs...
+  set ddAS   $dDest/autosetup
+  set ddAST  $ddAS/teaish
+  set ddASTF $ddAST/feature
+  foreach {srcDir destDir} [list \
+                              $dAS   $ddAS \
+                              $dAST  $ddAST \
+                              $dASTF $ddASTF \
+                             ] {
+    teaish__verbose 1 msg-result "Copying files to $destDir..."
+    file mkdir $destDir
+    foreach f  [glob -directory $srcDir *] {
+      if {[string match {*~} $f] || [string match "#*#" [file tail $f]]} {
+        # Editor-generated backups and emacs lock files
+        continue
+      }
+      teaish__verbose 2 msg-result "\t$f"
+      teaish__install_file $f $destDir $force
+    }
+  }
+  teaish__verbose 1 msg-result "Copying files to $dDest..."
+  foreach f {
+    auto.def configure Makefile.in pkgIndex.tcl.in
+    teaish.tester.tcl.in
+  } {
+    teaish__verbose 2 msg-result "\t$f"
+    teaish__install_file $dSrc/$f $dDest $force
+  }
+  set ::teaish__Config(install-self-dir) $dDest
+  msg-result "Teaish $::teaish__Config(version) installed in \[$dDest\]."
 }
index 5f5e1f1555d0d1ec811a2e3eb1dbc29f4d86a3b7..5c546e841d7cd240bf417d31847e95f2eeee2ab1 100644 (file)
@@ -115,12 +115,15 @@ proc test-assert {testId script {msg ""}} {
 # @test-expect testId script result
 #
 # Runs $script in the calling scope and compares its result to
-# $result.  If they differ, it triggers an [assert].
+# $result, minus any leading or trailing whitespace.  If they differ,
+# it triggers an [assert].
 #
 proc test-expect {testId script result} {
   puts "test $testId"
-  set x [uplevel 1 $script]
-  test__assert 1 {$x eq $result} "\nEXPECTED: <<$result>>\nGOT:      <<$x>>"
+  set x [string trim [uplevel 1 $script]]
+  set result [string trim $result]
+  test__assert 1 {$x eq $result} \
+    "\nEXPECTED: <<$result>>\nGOT:      <<$x>>"
 }
 
 #
index 99db68e2497868a60a2a4ad2a5ae5b42610ac993..87d059c32826d1419b3b446fee17a83c8f2b46fe 100644 (file)
@@ -1,30 +1,74 @@
 # Teaish configure script for the SQLite Tcl extension
 
-apply {{} {
-  set version [proj-file-content -trim [teaish-get -dir]/../VERSION]
-  proj-assert {[string match 3.*.* $version]}
-  teaish-pkginfo-set -vars {
-    -name sqlite
-    -pkgName sqlite3
-    -version $version
-    -loadPrefix Sqlite3
-    -vsatisfies 8.6-
-    -libDir sqlite$version
-    -pragmas {no-dist}
-  }
-}}
-
 #
-# Object for communicating certain config-time state across various
-# auto.def-related pieces.
+# State for disparate config-time pieces.
 #
-array set sqliteConfig [subst [proj-strip-hash-comments {
+array set sqlite__Config [proj-strip-hash-comments {
   #
   # The list of feature --flags which the --all flag implies. This
   # requires special handling in a few places.
   #
   all-flag-enables {fts3 fts4 fts5 rtree geopoly}
-}]]
+
+  # >0 if building in the canonical tree. -1=undetermined
+  is-canonical -1
+}]
+
+#
+# Set up the package info for teaish...
+#
+apply {{dir} {
+  # Figure out the version number...
+  set version ""
+  if {[file exists $dir/../VERSION]} {
+    # The canonical SQLite TEA(ish) build
+    set version [proj-file-content -trim $dir/../VERSION]
+    set ::sqlite__Config(is-canonical) 1
+    set distname sqlite-tcl
+  } elseif {[file exists $dir/generic/tclsqlite3.c]} {
+    # The copy from the teaish tree, used as a dev/test bed before
+    # updating SQLite's tree.
+    set ::sqlite__Config(is-canonical) 0
+    set fd [open $dir/generic/tclsqlite3.c rb]
+    while {[gets $fd line] >=0} {
+      if {[regexp {^#define[ ]+SQLITE_VERSION[ ]+"(3.+)"} \
+             $line - version]} {
+        set distname sqlite-teaish
+        break
+      }
+    }
+    close $fd
+  }
+
+  if {"" eq $version} {
+    proj-fatal "Cannot determine the SQLite version number"
+  }
+
+  proj-assert {$::sqlite__Config(is-canonical) > -1}
+  proj-assert {[string match 3.*.* $version]} \
+    "Unexpected SQLite version: $version"
+
+  set pragmas {}
+  if {$::sqlite__Config(is-canonical)} {
+    # Disable "make dist" in the canonical tree.  That tree is
+    # generated from several pieces and creating/testing working
+    # "dist" rules for that sub-build currently feels unnecessary. The
+    # copy in the teaish tree, though, should be able to "make dist".
+    lappend pragmas no-dist
+  } else {
+    lappend pragmas full-dist
+  }
+
+  teaish-pkginfo-set -vars {
+    -name sqlite
+    -name.pkg sqlite3
+    -version $version
+    -name.dist $distname
+    -vsatisfies 8.6-
+    -libDir sqlite$version
+    -pragmas $pragmas
+  }
+}} [teaish-get -dir]
 
 #
 # Must return either an empty string or a list in the form accepted by
@@ -52,7 +96,7 @@ proc teaish-options {} {
     geopoly              => {Enable the GEOPOLY extension}
     rtree                => {Enable the RTREE extension}
     session              => {Enable the SESSION extension}
-    all=1                => {Disable $::sqliteConfig(all-flag-enables)}
+    all=1                => {Disable $::sqlite__Config(all-flag-enables)}
     with-icu-ldflags:LDFLAGS
       => {Enable SQLITE_ENABLE_ICU and add the given linker flags for the
           ICU libraries. e.g. on Ubuntu systems, try '-licui18n -licuuc -licudata'.}
@@ -75,8 +119,8 @@ proc teaish-options {} {
 proc teaish-configure {} {
   use teaish/feature-tests
 
-  set srcdir [teaish-get -dir]
   teaish-src-add -dist -dir generic/tclsqlite3.c
+
   if {[proj-opt-was-provided override-sqlite-version]} {
     teaish-pkginfo-set -version [opt-val override-sqlite-version]
     proj-warn "overriding sqlite version number:" [teaish-pkginfo-get -version]
@@ -105,8 +149,8 @@ proc teaish-configure {} {
     msg-result "Using system-level sqlite3."
     teaish-cflags-add -DUSE_SYSTEM_SQLITE
     teaish-ldflags-add -lsqlite3
-  } else {
-    teaish-cflags-add -I${srcdir}/..
+  } elseif {$::sqlite__Config(is-canonical)} {
+    teaish-cflags-add -I[teaish-get -dir]/..
   }
 
   teaish-check-librt
@@ -157,7 +201,7 @@ proc sqlite-handle-common-feature-flags {} {
   msg-result "Feature flags..."
   if {![opt-bool all]} {
     # Special handling for --disable-all
-    foreach flag $::sqliteConfig(all-flag-enables) {
+    foreach flag $::sqlite__Config(all-flag-enables) {
       if {![proj-opt-was-provided $flag]} {
         proj-opt-set $flag 0
       }
@@ -178,7 +222,7 @@ proc sqlite-handle-common-feature-flags {} {
       # The --geopoly flag, though, will automatically re-enable
       # --rtree, so --disable-rtree won't actually disable anything in
       # that case.
-      foreach k $::sqliteConfig(all-flag-enables) {
+      foreach k $::sqlite__Config(all-flag-enables) {
         if {![proj-opt-was-provided $k]} {
           proj-opt-set $k 1
         }
@@ -500,9 +544,6 @@ proc sqlite-munge-cflags {} {
   # -DSQLITE_ENABLE* to OPT_FEATURE_FLAGS. This behavior is derived
   # from the pre-3.48 build.
   #
-  # Handling of CPPFLAGS, as well as removing ENABLE/OMIT from
-  # CFLAGS/CPPFLAGS, was missing in the 3.49.0 release as well.
-  #
   # If any configure flags for features are in conflict with
   # CFLAGS/CPPFLAGS-specified feature flags, all bets are off.  There
   # are no guarantees about which one will take precedence.
index bdc593cd4398ac052333c3678961741465a2d5aa..7690486cf24874f4ad3848c572203b87dd029890 100644 (file)
@@ -85,7 +85,7 @@ set proj__Config(isatty) [isatty? stdout]
 #
 proc proj-warn {args} {
   show-notices
-  puts stderr [join [list "WARNING:" {*}$args] " "]
+  puts stderr [join [list "WARNING: \[[proj-current-scope 1]\]: " {*}$args] " "]
 }
 
 #
@@ -1762,8 +1762,8 @@ proc proj-validate-no-unresolved-ats {args} {
 #
 # @proj-first-file-found tgtVar fileList
 #
-# Searches $fileList for an existing file. If one is found, its name is
-# assigned to tgtVar and 1 is returned, else tgtVar is not modified
+# Searches $fileList for an existing file. If one is found, its name
+# is assigned to tgtVar and 1 is returned, else tgtVar is set to ""
 # and 0 is returned.
 #
 proc proj-first-file-found {tgtVar fileList} {
@@ -1774,6 +1774,7 @@ proc proj-first-file-found {tgtVar fileList} {
       return 1
     }
   }
+  set tgt ""
   return 0
 }
 
index 15e4fa0d6b0ae0bea935863ca362883c527ee778..f6282811e996863ee11a44cef55c41cef98bb6ba 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C proj.tcl:\scorrect\sthe\sauto-reconfigure\srules\sto\sinclude\sany\sX=Y\spassed\sto\sconfigure.\sImprove\shandling\sof\squoted\sCFLAGS.
-D 2025-04-27T06:01:26.900
+C tea:\spull\sin\supstream\steaish.\sConsolidate\sthe\sbuild\sdefinition\sfrom\sthe\supstream\sbuild\sand\sthis\sone\sto\sease\smaintenace.\sImprove\scompatibility\swith\shistorical\sTEA\susage\sof\s--with-tcl=...\s(it\sinsists\son\sa\s/lib\ssuffix\sfor\sthat\spath).
+D 2025-04-28T09:25:19.852
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -22,18 +22,18 @@ F autoconf/Makefile.msc 5bc67d3912444c40c6f96d003e5c90663e51abb83d204a520110b1b2
 F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d64849094c1fd136
 F autoconf/README.txt b749816b8452b3af994dc6d607394bef3df1736d7e09359f1087de8439a52807
 F autoconf/auto.def 3d994f3a9cc9b712dbce92a5708570ddcf3b988141b6eb738f2ed16127a9f0ac
-F autoconf/tea/Makefile.in bb66da485861af82a45e7c135fcf89270f5c0989dbfbb17912c745440b2f9c6c
+F autoconf/tea/Makefile.in 6aebb3d820c8aab94f7599e8594d5f2ecea63894d08f36ba4141040b322042bc
 F autoconf/tea/README.txt 656d4686c509d375f5988ff3deda94f65fe6cd8358cd55d1f1dcc7b6e2ff73aa
 F autoconf/tea/auto.def ce95b9450e2fa4ba5dc857e208fe10f4e6f2d737796ac3278aee6079db417529
 F autoconf/tea/autosetup/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
-F autoconf/tea/autosetup/core.tcl 603506c76d1bdf3cf12be0ed87e11fb77aeae3b0598b97e3989e6fabb60de01a
+F autoconf/tea/autosetup/core.tcl f0eebd4aa416df44f0c22f7be1a2b5b05e8fe4f64e53b0d06a21f328963c5109
 F autoconf/tea/autosetup/feature-tests.tcl 307cac35806817fc87bd0d92004364ee682c0e99f2ab505291500493ab6c7a5f
-F autoconf/tea/autosetup/tester.tcl 93cff35afc5cabc8f855fad114fae58b435fa47cbab5f8cbd4dc694ff0c26107
+F autoconf/tea/autosetup/tester.tcl c293695a0ab5d9e8d0ceeb0ee422f90e8a6aa9f0c7c51acd0b6d9f09d8edfed3
 F autoconf/tea/configure d0b12b984edca6030d1976375b80157ac78b5b90a5b4f0dcee39357f63f4a80b x
 F autoconf/tea/doc/sqlite3.n 9a97f4f717ceab73004ea412af7960625c1cb24b5c25e4ae4c8b5d8fa4300f4e
 F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
 F autoconf/tea/pkgIndex.tcl.in e07da6b94561f4aa382bab65b1ccceb04701b97bf59d007c1d1f20a222b22d07
-F autoconf/tea/teaish.tcl 172fd9d6e06e5874db58e3384cfa9a7d52325634302eed189bb60f6cbf40bbd9
+F autoconf/tea/teaish.tcl 8e124f33cbaf9309f3e49be4e7018a03b8f3a52f8c8d9e1e5419f4f7b0eae59e
 F autoconf/tea/teaish.test.tcl cfe94e1fb79dd078f650295be59843d470125e0cc3a17a1414c1fb8d77f4aea6
 F autoconf/tea/teaish.tester.tcl.in 0d048e5569ad9bbaffbe5123c2084f9084d424a7719d06f5ca941caafbcca320
 F autosetup/LICENSE 41a26aebdd2cd185d1e2b210f71b7ce234496979f6b35aef2cbf6b80cbed4ce4
@@ -51,7 +51,7 @@ F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e
 F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1821baf61bc86a7e
 F autosetup/jimsh0.c 563b966c137a4ce3c9333e5196723b7ac0919140a9d7989eb440463cd855c367
 F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
-F autosetup/proj.tcl d2c0c6da22b4b6e0da6d054851079477815f8acc265e718f16879f3e88ffd819
+F autosetup/proj.tcl 4deaa5bba71390367a55fe4f0dbdc0e0ddbefb5c24a0ee4a5a54bbf288a3285d
 F autosetup/sqlite-config.tcl 54c88abadda1a42c6276186afcf6534e9bcb08350d96676c4ec08b99f2ada484
 F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
 F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x
@@ -2216,8 +2216,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 4aeec30443b282f10353cdb9415fdce436287280f0f5d5d6b9917da831744898
-R d75d037808a96903ea777bfc48335881
+P 7a2f4f319c90b768c6acc96671a3173c0ef0493180f3c4d5443f1ca03d92f6b4
+R 9db6b397f54d671a4320cc5ce752e15a
 U stephan
-Z 7e9da962d1e2273ff3dad52e3e71aeeb
+Z a79c230793c16373c3792db45c1c451d
 # Remove this line to create a well-formed Fossil manifest.
index 6428295eb6ea25cbe5968743274458cc161cf371..9d9b32d403fb88d7ef9bda4a913ea5592be804fe 100644 (file)
@@ -1 +1 @@
-7a2f4f319c90b768c6acc96671a3173c0ef0493180f3c4d5443f1ca03d92f6b4
+0ea5993dd8549056d73f3d5447e0a810495ece23a75be8add78fba6842125d85