aboutsummaryrefslogtreecommitdiff
path: root/autoconf
diff options
context:
space:
mode:
Diffstat (limited to 'autoconf')
-rw-r--r--autoconf/tea/Makefile.in73
-rw-r--r--autoconf/tea/_teaish.tester.tcl.in (renamed from autoconf/tea/teaish.tester.tcl.in)8
-rw-r--r--autoconf/tea/autosetup/README.txt4
-rw-r--r--autoconf/tea/autosetup/core.tcl2368
-rw-r--r--autoconf/tea/autosetup/feature-tests.tcl214
-rw-r--r--autoconf/tea/autosetup/tester.tcl193
-rw-r--r--autoconf/tea/teaish.tcl2
7 files changed, 64 insertions, 2798 deletions
diff --git a/autoconf/tea/Makefile.in b/autoconf/tea/Makefile.in
index ad71c8b3e..5b2ad4c69 100644
--- a/autoconf/tea/Makefile.in
+++ b/autoconf/tea/Makefile.in
@@ -1,5 +1,9 @@
all:
#
+# Unless this file is named Makefile.in, you are probably looking
+# at an automatically generated/filtered copy and should probably not
+# edit it.
+#
# This makefile is part of the teaish framework, a tool for building
# Tcl extensions, conceptually related to TEA/tclconfig but using the
# Autosetup configuration system instead of the GNU Autotools.
@@ -47,6 +51,12 @@ tx.dll8 = @TEAISH_DLL8@
tx.dll9 = @TEAISH_DLL9@
tx.dll = $(tx.dll$(TCL_MAJOR_VERSION))
tx.dir = @TEAISH_EXT_DIR@
+@if TEAISH_TM_TCL
+# Input filename for tcl::tm-style module
+tx.tm = @TEAISH_TM_TCL@
+# Target filename for tcl::tm-style installation
+tx.tm.tgt = $(tx.name.pkg)-$(tx.version).tm
+@endif
@if TEAISH_DIST_NAME
tx.name.dist = @TEAISH_DIST_NAME@
@@ -157,23 +167,12 @@ tx.LDFLAGS =
#
tx.dist.files = @TEAISH_DIST_FILES@
-#
-# May get amended with generated file names. They are cleaned up by
-# the 'clean' rules. Client code which wants to clean up extra stuff
-# should do so by adding their cleanup target (e.g. clean-extension)
-# as a dependency to the 'clean' target, like so:
-#
-# clean: distclean-extension
-# distclean: distclean-extension
-#
-teaish__cleanExtra =
-
# List of deps which may trigger an auto-reconfigure.
#
teaish__autogen.deps = \
$(tx.makefile.in) $(teaish.makefile.in) \
$(tx.tcl) \
- @TEAISH_PKGINDEX_TCL_IN@ \
+ @TEAISH_PKGINDEX_TCL_IN@ @TEAISH_TM_TCL_IN@ \
@AUTODEPS@
@if TEAISH_MAKEFILE_IN
@@ -271,10 +270,10 @@ test: test-post
# Cleanup rules...
#
#.PHONY: clean-pre clean-core clean-post clean-extension
-clean-extension: # this name is reserved for use by teaish.make
+#
clean-pre:
clean-core: clean-pre
- rm -f $(tx.dll8) $(tx.dll9) tclsh $(teaish__cleanExtra)
+ rm -f $(tx.dll8) $(tx.dll9) tclsh
clean-post: clean-core
clean: clean-post
@@ -300,26 +299,59 @@ 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
+#
+# The (dist)clean-extension targets are reserved for use by
+# client-side teaish.make.
+#
+# Client code which wants to clean up extra stuff should do so by
+# adding their cleanup target (e.g. clean-extension) as a dependency
+# to the 'clean' target, like so:
+#
+# clean: distclean-extension
+# distclean: distclean-extension
+#
+distclean-extension:
+clean-extension:
#
# Installation rules...
#
+@if TEAISH_ENABLE_INSTALL
.PHONY: install-pre install-core install-post install-test install-prepre install-extension
install-extension: # this name is reserved for use by teaish.make
+
+@if TEAISH_ENABLE_DLL
install-prepre: $(tx.dll)
+@else
+install-prepre:
+@endif
+
+@if TEAISH_TM_TCL
+install-core.tmdir = $(DESTDIR)@TEAISH_TCL_TM_DIR@
+@endif
+
install-pre: install-prepre
install-core: install-pre
@if [ ! -d "$(DESTDIR)$(TCLLIBDIR)" ]; then \
set -x; $(INSTALL) -d "$(DESTDIR)$(TCLLIBDIR)"; \
fi
# ^^^^ on some platforms, install -d fails if the target already exists.
+@if TEAISH_ENABLE_DLL
$(INSTALL) $(tx.dll) "$(DESTDIR)$(TCLLIBDIR)"
- $(INSTALL.noexec) pkgIndex.tcl "$(DESTDIR)$(TCLLIBDIR)"
+@endif
+@if TEAISH_PKGINDEX_TCL
+ $(INSTALL.noexec) "@TEAISH_PKGINDEX_TCL@" "$(DESTDIR)$(TCLLIBDIR)"
+@endif
@if TEAISH_PKGINIT_TCL
- $(INSTALL.noexec) @TEAISH_PKGINIT_TCL@ "$(DESTDIR)$(TCLLIBDIR)"
+ $(INSTALL.noexec) "@TEAISH_PKGINIT_TCL@" "$(DESTDIR)$(TCLLIBDIR)"
+@endif
+@if TEAISH_TM_TCL
+ @if [ ! -d "$(install-core.tmdir)" ]; then \
+ set -x; $(INSTALL) -d "$(install-core.tmdir)"; \
+ fi
+ $(INSTALL.noexec) "@TEAISH_TM_TCL@" "$(install-core.tmdir)/$(tx.tm.tgt)"
@endif
install-test: install-core
@echo "Post-install test of [package require $(tx.name.pkg) $(tx.version)]..."; \
@@ -344,10 +376,17 @@ install: install-post
uninstall-extension: # this name is reserved for use by teaish.make
uninstall-pre:
uninstall-core: uninstall-pre
+@if TEAISH_ENABLE_DLL
rm -fr "$(DESTDIR)$(TCLLIBDIR)"
+@endif
+@if TEAISH_TM_TCL
+ rm -f "$(DESTDIR)$(install-core.tmdir)/$(tx.tm.tgt)"
+@endif
+
uninstall-post: uninstall-core
@echo "Uninstalled Tcl extension $(tx.name) $(tx.version)"
uninstall: uninstall-post
+@endif # TEAISH_ENABLE_INSTALL
@if TEAISH_MAKEFILE_IN
Makefile: $(tx.makefile.in)
diff --git a/autoconf/tea/teaish.tester.tcl.in b/autoconf/tea/_teaish.tester.tcl.in
index 4e203cd78..59d11f0a8 100644
--- a/autoconf/tea/teaish.tester.tcl.in
+++ b/autoconf/tea/_teaish.tester.tcl.in
@@ -1,6 +1,6 @@
# -*- tcl -*-
#
-# Unless this file is named teaish.tester.tcl.in, you are probably
+# Unless this file is named _teaish.tester.tcl.in, you are probably
# looking at an automatically generated/filtered copy and should
# probably not edit it.
#
@@ -28,6 +28,12 @@ apply {{file} {
source -encoding utf-8 $file
}} [join {@TEAISH_PKGINIT_TCL@}]
@endif
+@if TEAISH_TM_TCL
+apply {{file} {
+ set dir [file dirname $::argv0]
+ source -encoding utf-8 $file
+}} [join {@TEAISH_TM_TCL@}]
+@endif
@if TEAISH_TEST_TCL
apply {{file} {
# Populate state for [tester.tcl::teaish-build-flag*]
diff --git a/autoconf/tea/autosetup/README.txt b/autoconf/tea/autosetup/README.txt
deleted file mode 100644
index e11519b04..000000000
--- a/autoconf/tea/autosetup/README.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-The *.tcl files in this directory are part of the SQLite's "autoconf"
-bundle which are specific to the TEA(-ish) build. During the tarball
-generation process, they are copied into <TOP>/autoconf/autosetup/teaish
-(which itself is created as part of that process).
diff --git a/autoconf/tea/autosetup/core.tcl b/autoconf/tea/autosetup/core.tcl
deleted file mode 100644
index 4b3eb9a82..000000000
--- a/autoconf/tea/autosetup/core.tcl
+++ /dev/null
@@ -1,2368 +0,0 @@
-########################################################################
-# 2025 April 5
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# * May you do good and not evil.
-# * May you find forgiveness for yourself and forgive others.
-# * May you share freely, never taking more than you give.
-#
-########################################################################
-# ----- @module teaish.tcl -----
-# @section TEA-ish ((TCL Extension Architecture)-ish)
-#
-# Functions in this file with a prefix of teaish__ are
-# private/internal APIs. Those with a prefix of teaish- are
-# public APIs.
-#
-# Teaish has a hard dependency on proj.tcl, and any public API members
-# of that module are considered legal for use by teaish extensions.
-#
-# Project home page: https://fossil.wanderinghorse.net/r/teaish
-
-use proj
-
-#
-# API-internal settings and shared state.
-array set teaish__Config [proj-strip-hash-comments {
- #
- # Teaish's version number, not to be confused with
- # teaish__PkgInfo(-version).
- #
- version 0.1-beta
-
- # 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
- # 0x02 = found srcdir/pkgIndex.tcl.in
- # 0x10 = found TEAISH_EXT_DIR/pkgIndex.tcl (static file)
- # 0x20 = static-pkgIndex.tcl pragma: behave as if 0x10
- #
- # Reminder: it's significant that the bottom 4 bits be
- # cases where teaish manages ./pkgIndex.tcl.
- #
- 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.
- #
- verbose 0
-
- #
- # Mapping of pkginfo -flags to their TEAISH_xxx define (if any).
- # This must not be modified.
- #
- pkginfo-f2d {
- -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 {}
- }
-
- #
- # Queues for use with teaish-checks-queue and teaish-checks-run.
- #
- queued-checks-pre {}
- queued-checks-post {}
-
- # Whether or not "make dist" parts are enabled. They get enabled
- # when building from an extension's dir, disabled when building
- # elsewhere.
- dist-enabled 1
-
- # By default we enable compilation of a native extension but if the
- # extension has no native code or the user wants to take that over
- # via teaish.make.in or provide a script-only extension, we will
- # elide the default compilation rules if this is 0.
- dll-enabled 1
-
- # Files to include in the "make dist" bundle.
- dist-files {}
-
- # List of source files for the extension.
- extension-src {}
-
- # Path to the teaish.tcl file.
- teaish.tcl {}
-
- # 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
-
-#
-# Array of info managed by teaish-pkginfo-get and friends. Has the
-# same set of keys as $teaish__Config(pkginfo-f2d).
-#
-array set teaish__PkgInfo {}
-
-#
-# Runs {*}$args if $lvl is <= the current verbosity level, else it has
-# no side effects.
-#
-proc teaish__verbose {lvl args} {
- if {$lvl <= $::teaish__Config(verbose)} {
- {*}$args
- }
-}
-
-#
-# @teaish-argv-has flags...
-#
-# Returns true if any arg in $::argv matches any of the given globs,
-# else returns false.
-#
-proc teaish-argv-has {args} {
- foreach glob $args {
- foreach arg $::argv {
- if {[string match $glob $arg]} {
- return 1
- }
- }
- }
- return 0
-}
-
-if {[teaish-argv-has --teaish-verbose --t-v]} {
- # Check this early so that we can use verbose-only messages in the
- # pre-options-parsing steps.
- set ::teaish__Config(verbose) 1
- #teaish__verbose 1 msg-result "--teaish-verbose activated"
-}
-
-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-configure-core
-#
-# Main entry point for the TEA-ish configure process. auto.def's primary
-# (ideally only) job should be to call this.
-#
-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__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]
- }
-
- #
- # Set up the core --flags. This needs to come before teaish.tcl is
- # sourced so that that file can use teaish-pkginfo-set to append
- # options.
- #
- options-add [proj-strip-hash-comments {
- with-tcl:DIR
- => {Directory containing tclConfig.sh or a directory one level up from
- that, from which we can derive a directory containing tclConfig.sh.
- Defaults to the $TCL_HOME environment variable.}
-
- with-tclsh:PATH
- => {Full pathname of tclsh to use. It is used for trying to find
- tclConfig.sh. Warning: if its containing dir has multiple tclsh
- versions, it may select the wrong tclConfig.sh!
- Defaults to the $TCLSH environment variable.}
-
- # TEA has --with-tclinclude but it appears to only be useful for
- # building an extension against an uninstalled copy of TCL's own
- # source tree. The policy here is that either we get that info
- # from tclConfig.sh or we give up.
- #
- # with-tclinclude:DIR
- # => {Specify the directory which contains the tcl.h. This should not
- # normally be required, as that information comes from tclConfig.sh.}
-
- # We _generally_ want to reduce the possibility of flag collisions with
- # extensions, and thus use a teaish-... prefix on most flags. However,
- # --teaish-extension-dir is frequently needed, so...
- #
- # As of this spontaneous moment, we'll settle on using --t-A-X to
- # abbreviate --teaish-A...-X... flags when doing so is
- # unambiguous...
- ted: t-e-d:
- teaish-extension-dir:DIR
- => {Looks for an extension in the given directory instead of the current
- dir.}
-
- t-c-e:
- teaish-create-extension:TARGET_DIRECTORY
- => {Writes stub files for creating an extension. Will refuse to overwrite
- existing files without --teaish-force.}
-
- t-f
- teaish-force
- => {Has a context-dependent meaning (autosetup defines --force for its
- own use).}
-
- t-d-d
- teaish-dump-defines
- => {Dump all configure-defined vars to config.defines.txt}
-
- t-v:=0
- teaish-verbose:=0
- => {Enable more (often extraneous) messages from the teaish core.}
-
- t-d
- 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 {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.
- array set f2d $::teaish__Config(pkginfo-f2d)
- foreach {pflag key type val} {
- - TEAISH_CFLAGS -v ""
- - TEAISH_LDFLAGS -v ""
- - TEAISH_MAKEFILE -v ""
- - TEAISH_MAKEFILE_CODE -v ""
- - TEAISH_MAKEFILE_IN -v ""
- - TEAISH_PKGINDEX_TCL -v ""
- - TEAISH_PKGINDEX_TCL_IN -v ""
- - TEAISH_TEST_TCL -v ""
- - TEAISH_TEST_TCL_IN -v ""
-
- -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 -name.pkg] \
- [teaish-pkginfo-get -version]] ""
- }
- -loadPrefix :f2d: -e {
- string totitle [teaish-get -name.pkg]
- }
- -vsatisfies :f2d: -v {{Tcl 8.5-}}
- -pkgInit.tcl :f2d: -v ""
- -pkgInit.tcl.in :f2d: -v ""
- -url :f2d: -v ""
- } {
- 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 {"<nope>" ne $got} {
- # Was already set - skip it.
- continue
- }
- switch -exact -- $type {
- -v {}
- -e { set val [eval $val] }
- default { proj-error "Invalid type flag: $type" }
- }
- #puts "***** defining default $pflag $key {$val} isPIFlag=$isPIFlag got=$got"
- define $key $val
- if {$isPIFlag} {
- set ::teaish__PkgInfo($pflag) $val
- }
- }
- unset isPIFlag pflag key type val
- array unset f2d
- }; # sourcing extension's teaish.tcl
-
- if {[llength [info proc teaish-options]] > 0} {
- # Add options defined by teaish-options, which is assumed to be
- # imported via [teaish-get -teaish-tcl].
- set o [teaish-options]
- if {"" ne $o} {
- options-add $o
- }
- }
- #set opts [proj-options-combine]
- #lappend opts teaish-debug => {x}; #testing dupe entry handling
- if {[catch {options {}} msg xopts]} {
- # Workaround for <https://github.com/msteveb/autosetup/issues/73>
- # where [options] behaves oddly on _some_ TCL builds when it's
- # called from deeper than the global scope.
- dict incr xopts -level
- return {*}$xopts $msg
- }
-
- proj-xfer-options-aliases {
- t-c-e => teaish-create-extension
- t-d => teaish-debug
- 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
- }
-
- 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"
-
- teaish__configure_phase1
-}
-
-
-#
-# Internal config-time debugging output routine. It is not legal to
-# call this from the global scope.
-#
-proc teaish-debug {msg} {
- if {$::teaish__Config(debug-enabled)} {
- puts stderr [proj-bold "** DEBUG: \[[proj-scope 1]\]: $msg"]
- }
-}
-
-#
-# Runs "phase 1" of the configuration, immediately after processing
-# --flags. This is what will import the client-defined teaish.tcl.
-#
-proc teaish__configure_phase1 {} {
- msg-result \
- [join [list "Configuring build of Tcl extension" \
- [proj-bold [teaish-pkginfo-get -name] \
- [teaish-pkginfo-get -version]] "..."]]
-
- uplevel 1 {
- use cc cc-db cc-shared cc-lib; # pkg-config
- }
- teaish__check_tcl
- apply {{} {
- #
- # If --prefix or --exec-prefix are _not_ provided, use their
- # TCL_... counterpart from tclConfig.sh. Caveat: by the time we can
- # reach this point, autosetup's system.tcl will have already done
- # some non-trivial amount of work with these to create various
- # derived values from them, so we temporarily end up with a mishmash
- # of autotools-compatibility var values. That will be straightened
- # out in the final stage of the configure script via
- # [proj-remap-autoconf-dir-vars].
- #
- foreach {flag uflag tclVar} {
- prefix prefix TCL_PREFIX
- exec-prefix exec_prefix TCL_EXEC_PREFIX
- } {
- if {![proj-opt-was-provided $flag]} {
- if {"exec-prefix" eq $flag} {
- # If --exec-prefix was not used, ensure that --exec-prefix
- # derives from the --prefix we may have just redefined.
- set v {${prefix}}
- } else {
- set v [get-define $tclVar "???"]
- teaish__verbose 1 msg-result "Using \$$tclVar for --$flag=$v"
- }
- proj-assert {"???" ne $v} "Expecting teaish__check_tcl to have defined $tclVar"
- #puts "*** $flag $uflag $tclVar = $v"
- proj-opt-set $flag $v
- define $uflag $v
-
- # ^^^ As of here, all autotools-compatibility vars which derive
- # from --$flag, e.g. --libdir, still derive from the default
- # --$flag value which was active when system.tcl was
- # included. So long as those flags are not explicitly passed to
- # the configure script, those will be straightened out via
- # [proj-remap-autoconf-dir-vars].
- }
- }
- }}; # --[exec-]prefix defaults
- teaish__check_common_bins
- #
- # Set up library file names
- #
- proj-file-extensions
- teaish__define_pkginfo_derived *
-
- teaish-checks-run -pre
- if {[llength [info proc teaish-configure]] > 0} {
- # teaish-configure is assumed to be imported via
- # teaish.tcl
- teaish-configure
- }
- teaish-checks-run -post
-
- 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"
- }
- 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
- # Msys2.
- msg-result "Using USE_TCL_STUBS for Unix(ish)-on-Windows environment"
- teaish-cflags-add -DUSE_TCL_STUBS=1
- }
-
- #define AS_LIBDIR $::autosetup(libdir)
- define TEAISH_TESTUTIL_TCL $::teaish__Config(core-dir)/tester.tcl
-
- apply {{} {
- #
- # Ensure we have a pkgIndex.tcl and don't have a stale generated one
- # when rebuilding for different --with-tcl=... values.
- #
- if {!$::teaish__Config(pkgindex-policy)} {
- proj-error "Cannot determine which pkgIndex.tcl to use"
- }
- set tpi [proj-coalesce \
- [get-define TEAISH_PKGINDEX_TCL_IN] \
- [get-define TEAISH_PKGINDEX_TCL]]
- proj-assert {$tpi ne ""} \
- "TEAISH_PKGINDEX_TCL should have been set up by now"
- teaish__verbose 1 msg-result "Using pkgIndex from $tpi"
- if {0x0f & $::teaish__Config(pkgindex-policy)} {
- # Don't leave stale pkgIndex.tcl laying around yet don't delete
- # or overwrite a user-managed static pkgIndex.tcl.
- file delete -force -- [get-define TEAISH_PKGINDEX_TCL]
- proj-dot-ins-append [get-define TEAISH_PKGINDEX_TCL_IN]
- } else {
- teaish-dist-add [file tail $tpi]
- }
- }}; # $::teaish__Config(pkgindex-policy)
-
- #
- # 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 {{} {
- # 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
- }
- }
- }}
-
- 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_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)]
- proj-setup-autoreconfig TEAISH_AUTORECONFIG
- foreach f {
- TEAISH_CFLAGS
- TEAISH_LDFLAGS
- } {
- # Ensure that any of these lists are flattened
- define $f [join [get-define $f]]
- }
- define TEAISH__DEFINES_MAP \
- [teaish__dump_defs_to_list]; # injected into teaish.tester.tcl
- proj-remap-autoconf-dir-vars
- proj-dot-ins-process -validate; # do not [define] after this point
- proj-if-opt-truthy teaish-dump-defines {
- make-config-header config.defines.txt \
- -none {TEAISH__* TEAISH_*_CODE} \
- -str {
- BIN_* CC LD AR INSTALL LDFLAG* CFLAGS* *_LDFLAGS *_CFLAGS
- } \
- -bare {HAVE_*} \
- -auto {*}
- }
-
- #
- # If these are set up before call [options], it triggers an
- # "option already defined" error.
- #
- #proj-opt-set teaish.tcl [get-define ]
- #proj-opt-set teaish.make.in [get-define ]
-
- #
- # $::autosetup(builddir)/.configured is a workaround to prevent
- # concurrent executions of TEAISH_AUTORECONFIG. MUST come last in
- # the configure process.
- #
- #proj-file-write $::autosetup(builddir)/.configured ""
-}; # teaish__configure_phase1
-
-#
-# Run checks for required binaries.
-#
-proc teaish__check_common_bins {} {
- if {"" eq [proj-bin-define install]} {
- proj-warn "Cannot find install binary, so 'make install' will not work."
- define BIN_INSTALL false
- }
- if {"" eq [proj-bin-define zip]} {
- proj-warn "Cannot find zip, so 'make dist.zip' will not work."
- }
- if {"" eq [proj-bin-define tar]} {
- proj-warn "Cannot find tar, so 'make dist.tgz' will not work."
- }
-}
-
-#
-# TCL...
-#
-# teaish__check_tcl performs most of the --with-tcl and --with-tclsh
-# handling. Some related bits and pieces are performed before and
-# after that function is called.
-#
-# Important [define]'d vars:
-#
-# - TCLSH_CMD is the path to the canonical tclsh or "".
-#
-# - TCL_CONFIG_SH is the path to tclConfig.sh or "".
-#
-# - TCLLIBDIR is the dir to which the extension library gets
-# - installed.
-#
-proc teaish__check_tcl {} {
- define TCLSH_CMD false ; # Significant is that it exits with non-0
- define TCLLIBDIR "" ; # Installation dir for TCL extension lib
- define TCL_CONFIG_SH ""; # full path to tclConfig.sh
-
- # Clear out all vars which would harvest from tclConfig.sh so that
- # the late-config validation of @VARS@ works even if --disable-tcl
- # is used.
- proj-tclConfig-sh-to-autosetup ""
-
- # TODO: better document the steps this is taking.
- set srcdir $::autosetup(srcdir)
- msg-result "Checking for a suitable tcl... "
- set use_tcl 1
- 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 $tclHome} {
- set tclHome [get-define prefix]
- }
- }
- teaish-debug "use_tcl ${use_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 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 $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 $withSh]} {
- proj-error "TCL shell $withSh is not executable"
- } else {
- define TCLSH_CMD $withSh
- #msg-result "Using tclsh: $withSh"
- }
- if {$doConfigLookup &&
- [catch {exec $withSh $::autosetup(libdir)/find_tclconfig.tcl} result] == 0} {
- set tclHome $result
- }
- if {"" ne $tclHome && [file isdirectory $tclHome]} {
- teaish__verbose 1 msg-result "$withSh recommends the tclConfig.sh from $tclHome"
- } else {
- proj-warn "$withSh is unable to recommend a tclConfig.sh"
- set use_tcl 0
- }
- }
- set cfg ""
- set tclSubdirs {tcl9.1 tcl9.0 tcl8.6 tcl8.5 lib}
- while {$use_tcl} {
- if {"" ne $tclHome} {
- # Ensure that we can find tclConfig.sh under ${tclHome}/...
- if {$doConfigLookup} {
- if {[file readable "${tclHome}/tclConfig.sh"]} {
- set cfg "${tclHome}/tclConfig.sh"
- } else {
- foreach i $tclSubdirs {
- if {[file readable "${tclHome}/$i/tclConfig.sh"]} {
- set cfg "${tclHome}/$i/tclConfig.sh"
- break
- }
- }
- }
- }
- if {"" eq $cfg} {
- proj-error "No tclConfig.sh found under ${tclHome}"
- }
- } else {
- # If we have not yet found a tclConfig.sh file, look in $libdir
- # which is set automatically by autosetup or via the --prefix
- # command-line option. See
- # https://sqlite.org/forum/forumpost/e04e693439a22457
- set libdir [get-define libdir]
- if {[file readable "${libdir}/tclConfig.sh"]} {
- set cfg "${libdir}/tclConfig.sh"
- } else {
- foreach i $tclSubdirs {
- if {[file readable "${libdir}/$i/tclConfig.sh"]} {
- set cfg "${libdir}/$i/tclConfig.sh"
- break
- }
- }
- }
- if {![file readable $cfg]} {
- break
- }
- }
- 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 $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]
- proj-assert {"" ne $tclExecPrefix}
- set tryThese [list \
- $tclExecPrefix/bin/tclsh[get-define TCL_VERSION] \
- $tclExecPrefix/bin/tclsh ]
- foreach trySh $tryThese {
- if {[file-isexec $trySh]} {
- set withSh $trySh
- break
- }
- }
- if {![file-isexec $withSh]} {
- proj-warn "Cannot find a usable tclsh (tried: $tryThese)"
- }
- }
- 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 $withSh &&
- [catch {exec echo "puts stdout \$auto_path" | "$withSh"} result] == 0} {
- foreach i $result {
- if {[file isdirectory $i]} {
- set tcllibdir $i/$extDirName
- break
- }
- }
- } else {
- proj-error "Cannot determine TCLLIBDIR."
- }
- }
- define TCLLIBDIR $tcllibdir
- }; # find TCLLIBDIR
-
- if {[file-isexec $withSh]} {
- teaish__verbose 1 msg-result "Using tclsh = $withSh"
- if {$cfg ne ""} {
- define HAVE_TCL 1
- } else {
- proj-warn "Found tclsh but no tclConfig.sh."
- }
- }
- show-notices
- # If TCL is not found: if it was explicitly requested then fail
- # 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 $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 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] from [get-define TCL_PREFIX]."
- teaish__tcl_platform_quirks
-}; # teaish__check_tcl
-
-#
-# Perform last-minute platform-specific tweaks to account for quirks.
-#
-proc teaish__tcl_platform_quirks {} {
- define TEAISH_POSTINST_PREREQUIRE ""
- switch -glob -- [get-define host] {
- *-haiku {
- # Haiku's default TCLLIBDIR is "all wrong": it points to a
- # read-only virtual filesystem mount-point. We bend it back to
- # fit under $TCL_PACKAGE_PATH here.
- foreach {k d} {
- vj TCL_MAJOR_VERSION
- vn TCL_MINOR_VERSION
- pp TCL_PACKAGE_PATH
- ld TCLLIBDIR
- } {
- set $k [get-define $d]
- }
- if {[string match /packages/* $ld]} {
- set old $ld
- set tail [file tail $ld]
- if {8 == $vj} {
- set ld "${pp}/tcl${vj}.${vn}/${tail}"
- } else {
- proj-assert {9 == $vj}
- set ld "${pp}/${tail}"
- }
- define TCLLIBDIR $ld
- # [load foo.so], without a directory part, does not work via
- # automated tests on Haiku (but works when run
- # manually). Similarly, the post-install [package require ...]
- # test fails, presumably for a similar reason. We work around
- # the former in teaish.tester.tcl.in. We work around the
- # latter by amending the post-install check's ::auto_path (in
- # Makefile.in). This code MUST NOT contain any single-quotes.
- define TEAISH_POSTINST_PREREQUIRE \
- [join [list set ::auto_path \
- \[ linsert \$::auto_path 0 $ld \] \; \
- ]]
- proj-indented-notice [subst -nocommands -nobackslashes {
- Haiku users take note: patching target installation dir to match
- Tcl's home because Haiku's is not writable.
-
- Original : $old
- Substitute: $ld
- }]
- }
- }
- }
-}; # teaish__tcl_platform_quirks
-
-#
-# Searches $::argv and/or the build dir and/or the source dir for
-# teaish.tcl and friends. Fails if it cannot find teaish.tcl or if
-# there are other irreconcilable problems. If it returns 0 then it did
-# 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 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 checkTeaishTcl {{mustHave fid dir} {
- if {[file isdirectory $dir]} {
- set f [file join $dir $fid]
- if {[file readable $f]} {
- return [file-normalize $f]
- } elseif {$mustHave} {
- proj-error "Missing required $dir/$fid"
- }
- } elseif {$mustHave} {
- proj-error "--teaish-extension-dir=$dir does not reference a directory"
- }
- 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 dirBld $::autosetup(builddir); # dir we're configuring under
- set dirSrc $::autosetup(srcdir); # where teaish's configure script lives
- set extT ""; # teaish.tcl
- set largv {}; # rewritten $::argv
- set gotHelpArg 0; # got the --help
- foreach arg $::argv {
- #puts "*** arg=$arg"
- switch -glob -- $arg {
- --ted=* -
- --t-e-d=* -
- --teaish-extension-dir=* {
- # Ensure that $extD refers to a directory and contains a
- # teaish.tcl.
- regexp -- {--[^=]+=(.+)} $arg - extD
- set extD [file-normalize $extD]
- if {![file isdirectory $extD]} {
- proj-error "--teaish-extension-dir value is not a directory: $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
- }
- }
- }
- set ::argv $largv
-
- set dirExt $::teaish__Config(extension-dir); # dir with the extension
- #
- # teaish.tcl is a TCL script which implements various
- # interfaces described by this framework.
- #
- # We use the first one we find in the builddir or srcdir.
- #
- if {"" eq $extT} {
- 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 or --teaish-install is used.
- return 0;
- }
- proj-indented-notice -error "
-Did not find any of: $flist
-
-If you are attempting an out-of-tree build, use
- --teaish-extension-dir=/path/to/extension"
- }
- }
- if {![file readable $extT]} {
- proj-error "extension tcl file is not readable: $extT"
- }
- set ::teaish__Config(teaish.tcl) $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]
- }}
- apply $addDist $extT
-
- teaish__verbose 1 msg-result "Extension dir = [teaish-get -dir]"
- teaish__verbose 1 msg-result "Extension config = $extT"
-
- teaish-pkginfo-set -name [file tail [file dirname $extT]]
-
- #
- # teaish.make[.in] provides some of the info for the main makefile,
- # like which source(s) to build and their build flags.
- #
- # We use the first one of teaish.make.in or teaish.make we find in
- # $dirExt.
- #
- if {[proj-first-file-found extM \
- [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]]
- } else {
- define TEAISH_MAKEFILE_IN ""
- define TEAISH_MAKEFILE $extM
- }
- apply $addDist $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 \
- ]]} {
- if {[string match *.in $extI]} {
- # Generate teaish.pkginit.tcl from $extI.
- define TEAISH_PKGINIT_TCL_IN $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 $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 $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 $extPI's a static file and use it.
- define TEAISH_PKGINDEX_TCL_IN ""
- define TEAISH_PKGINDEX_TCL $extPI
- apply $addDist $extPI
- set piPolicy 0x10
- }
- # Reminder: we have to delay removal of stale TEAISH_PKGINDEX_TCL
- # and the proj-dot-ins-append of TEAISH_PKGINDEX_TCL_IN until much
- # later in the process.
- set ::teaish__Config(pkgindex-policy) $piPolicy
-
- # Look for teaish.test.tcl[.in]
- proj-assert {"" ne $dirExt}
- set flist [list $dirExt/teaish.test.tcl.in $dirExt/teaish.test.tcl]
- if {[proj-first-file-found ttt $flist]} {
- if {[string match *.in $ttt]} {
- # Generate teaish.test.tcl from $ttt
- set xt [file rootname [file tail $ttt]]
- file delete -force -- $xt; # ensure no stale copy is used
- define TEAISH_TEST_TCL $xt
- define TEAISH_TEST_TCL_IN $ttt
- } else {
- define TEAISH_TEST_TCL $ttt
- define TEAISH_TEST_TCL_IN ""
- }
- apply $addDist $ttt
- } else {
- define TEAISH_TEST_TCL ""
- define TEAISH_TEST_TCL_IN ""
- }
-
- # Look for teaish.tester.tcl[.in]
- set flist [list $dirExt/teaish.tester.tcl.in $dirSrc/teaish.tester.tcl.in]
- if {[proj-first-file-found ttt $flist]} {
- # Generate teaish.test.tcl from $ttt
- set xt [file rootname [file tail $ttt]]
- file delete -force -- $xt; # ensure no stale copy is used
- define TEAISH_TESTER_TCL $xt
- define TEAISH_TESTER_TCL_IN $ttt
- if {[lindex $flist 0] eq $ttt} {
- apply $addDist $ttt
- }
- unset ttt xt
- } else {
- 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
-
- # TEAISH_OUT_OF_EXT_TREE = 1 if we're building from a dir other
- # than the extension's home dir.
- define TEAISH_OUT_OF_EXT_TREE \
- [expr {[file-normalize $::autosetup(builddir)] ne \
- [file-normalize $::teaish__Config(extension-dir)]}]
- return 1
-}; # teaish__find_extension
-
-#
-# @teaish-cflags-add ?-p|prepend? ?-define? cflags...
-#
-# Equivalent to [proj-define-amend TEAISH_CFLAGS {*}$args].
-#
-proc teaish-cflags-add {args} {
- proj-define-amend TEAISH_CFLAGS {*}$args
-}
-
-#
-# @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} {
- 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]"'
-}
-
-#
-# @teaish-ldflags-add ?-p|-prepend? ?-define? ldflags...
-#
-# Equivalent to [proj-define-amend TEAISH_LDFLAGS {*}$args].
-#
-# Typically, -lXYZ flags need to be in "reverse" order, with each -lY
-# resolving symbols for -lX's to its left. This order is largely
-# historical, and not relevant on all environments, but it is
-# technically correct and still relevant on some environments.
-#
-# See: teaish-ldflags-prepend
-#
-proc teaish-ldflags-add {args} {
- proj-define-amend TEAISH_LDFLAGS {*}$args
-}
-
-#
-# @teaish-ldflags-prepend args...
-#
-# Functionally equivalent to [teaish-ldflags-add -p {*}$args]
-#
-proc teaish-ldflags-prepend {args} {
- teaish-ldflags-add -p {*}$args
-}
-
-#
-# @teaish-src-add ?-dist? ?-dir? src-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 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, or when adding
-# object files (which are typically in the build tree)).
-#
-proc teaish-src-add {args} {
- set i 0
- proj-parse-simple-flags args flags {
- -dist 0 {expr 1}
- -dir 0 {expr 1}
- }
- if {$flags(-dist)} {
- teaish-dist-add {*}$args
- }
- if {$flags(-dir)} {
- set xargs {}
- foreach arg $args {
- if {"" ne $arg} {
- lappend xargs [file join $::teaish__Config(extension-dir) $arg]
- }
- }
- set args $xargs
- }
- lappend ::teaish__Config(extension-src) {*}$args
-}
-
-#
-# @teaish-dist-add files-or-dirs...
-#
-# Adds the given files to the list of files to include with the "make
-# dist" rules.
-#
-# This is a no-op when the current build is not in the extension's
-# directory, as dist support is disabled in out-of-tree builds.
-#
-# It is not legal to call this until [teaish-get -dir] has been
-# reliably set (via teaish__find_extension).
-#
-proc teaish-dist-add {args} {
- if {$::teaish__Config(blddir-is-extdir)} {
- # ^^^ 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
- }
-}
-
-# teaish-install-add files...
-# Equivalent to [proj-define-apend TEAISH_INSTALL_FILES ...].
-#proc teaish-install-add {args} {
-# proj-define-amend TEAISH_INSTALL_FILES {*}$args
-#}
-
-#
-# @teash-make-add args...
-#
-# Appends makefile code to the TEAISH_MAKEFILE_CODE define. Each
-# arg may be any of:
-#
-# -tab: emit a literal tab
-# -nl: emit a literal newline
-# -nltab: short for -nl -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 {
- -bnl { set a " \\\n" }
- -bnltab { set a " \\\n\t" }
- -tab { set a "\t" }
- -nl { set a "\n" }
- -nltab { set a "\n\t" }
- }
- append out $a
- }
- 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-scope 1] -> [proj-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-scope 1] -> [proj-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
-#
-# Invokes autosetup's [make-config-header] and passes it $filename and
-# a relatively generic list of options for controlling which defined
-# symbols get exported. Clients which need more control over the
-# exports can copy/paste/customize this.
-#
-# The exported file is then passed to [proj-touch] because, in
-# practice, that's sometimes necessary to avoid build dependency
-# issues.
-#
-proc teaish-make-config-header {filename} {
- make-config-header $filename \
- -none {HAVE_CFLAG_* LDFLAGS_* SH_* TEAISH__* TEAISH_*_CODE} \
- -auto {SIZEOF_* HAVE_* TEAISH_* TCL_*} \
- -none *
- proj-touch $filename; # help avoid frequent unnecessary auto-reconfig
-}
-
-#
-# @teaish-feature-cache-set ?$key? value
-#
-# Sets a feature-check cache entry with the given key.
-# See proj-cache-set for the key's semantics.
-#
-proc teaish-feature-cache-set {{key 0} val} {
- proj-cache-set $key 1 $val
-}
-
-#
-# @teaish-feature-cache-check ?$key? tgtVarName
-#
-# Checks for a feature-check cache entry with the given key.
-# See proj-cache-set for the key's semantics.
-#
-# If the feature-check cache has a matching entry then this function
-# assigns its value to tgtVar and returns 1, else it assigns tgtVar to
-# "" and returns 0.
-#
-# See proj-cache-check for $key's semantics.
-#
-proc teaish-feature-cache-check {{key 0} tgtVar} {
- upvar $tgtVar tgt
- proj-cache-check $key 1 tgt
-}
-
-#
-# @teaish-check-cached@ ?-nostatus? msg script
-#
-# A proxy for feature-test impls which handles caching of a feature
-# flag check on per-function basis, using the calling scope's name as
-# the cache key.
-#
-# It emits [msg-checking $msg]. If $msg is empty then it defaults to
-# the name of the caller's scope. At the end, it will [msg-result "ok"]
-# [msg-result "no"] unless -nostatus is used, in which case the caller
-# is responsible for emitting at least a newline when it's done.
-#
-# This function checks for a cache hit before running $script and
-# caching the result. If no hit is found then $script is run in the
-# calling scope and its result value is stored in the cache. This
-# routine will intercept a 'return' from $script.
-#
-# Flags:
-#
-# -nostatus = do not emit "ok" or "no" at the end. This presumes
-# that the caller will emit at least one newline before turning.
-#
-proc teaish-check-cached {args} {
- proj-parse-simple-flags args flags {
- -nostatus 0 {expr 1}
- }
- lassign $args msg script
- if {"" eq $msg} {
- set msg [proj-scope 1]
- }
- msg-checking "${msg} ... "
- if {[teaish-feature-cache-check 1 check]} {
- msg-checking "(cached) "
- if {$check} {msg-result "ok"} else {msg-result "no"}
- return $check
- } else {
- set code [catch {uplevel 1 $script} rc xopt]
- #puts "***** cached-check got code=$code rc=$rc"
- if {$code in {0 2}} {
- teaish-feature-cache-set 1 $rc
- if {!$flags(-nostatus)} {
- if {$rc} {
- msg-result "ok"
- } else {
- msg-result "no"
- }
- }
- } else {
- #puts "**** code=$code rc=$rc xopt=$xopt"
- teaish-feature-cache-set 1 0
- }
- #puts "**** code=$code rc=$rc"
- return {*}$xopt $rc
- }
-}
-
-#
-# Internal helper for teaish__defs_format_: returns a JSON-ish quoted
-# form of the given string-type values.
-#
-# If $asList is true then the return value is in {$value} form. If
-# $asList is false it only performs the most basic of escaping and
-# the input must not contain any control characters.
-#
-proc teaish__quote_str {asList value} {
- if {$asList} {
- return [join [list "\{" $value "\}"] ""]
- }
- return \"[string map [list \\ \\\\ \" \\\"] $value]\"
-}
-
-#
-# Internal helper for teaish__dump_defs_to_list. Expects to be passed
-# a name and the variadic $args which are passed to
-# teaish__dump_defs_to_list.. If it finds a pattern match for the
-# given $name in the various $args, it returns the type flag for that
-# $name, e.g. "-str" or "-bare", else returns an empty string.
-#
-proc teaish__defs_type {name spec} {
- foreach {type patterns} $spec {
- foreach pattern $patterns {
- if {[string match $pattern $name]} {
- return $type
- }
- }
- }
- return ""
-}
-
-#
-# An internal impl detail. Requires a data type specifier, as used by
-# make-config-header, and a value. Returns the formatted value or the
-# value $::teaish__Config(defs-skip) if the caller should skip
-# emitting that value.
-#
-# In addition to -str, -auto, etc., as defined by make-config-header,
-# it supports:
-#
-# -list {...} will cause non-integer values to be quoted in {...}
-# instead of quotes.
-#
-# -autolist {...} works like -auto {...} except that it falls back to
-# -list {...} type instead of -str {...} style for non-integers.
-#
-# -array {...} emits the output in something which, for conservative
-# inputs, will be a valid JSON array. It can only handle relatively
-# simple values with no control characters in them.
-#
-set teaish__Config(defs-skip) "-teaish__defs_format sentinel"
-proc teaish__defs_format {type value} {
- switch -exact -- $type {
- -bare {
- # Just output the value unchanged
- }
- -none {
- set value $::teaish__Config(defs-skip)
- }
- -str {
- set value [teaish__quote_str 0 $value]
- }
- -auto {
- # Automatically determine the type
- if {![string is integer -strict $value]} {
- set value [teaish__quote_str 0 $value]
- }
- }
- -autolist {
- if {![string is integer -strict $value]} {
- set value [teaish__quote_str 1 $value]
- }
- }
- -list {
- set value [teaish__quote_str 1 $value]
- }
- -array {
- set ar {}
- foreach v $value {
- set v [teaish__defs_format -auto $v]
- if {$::teaish__Config(defs-skip) ne $v} {
- lappend ar $v
- }
- }
- set value "\[ [join $ar {, }] \]"
- }
- "" {
- set value $::teaish__Config(defs-skip)
- }
- default {
- proj-error \
- "Unknown [project-current-scope] -type ($type) called from" \
- [proj-scope 1]
- }
- }
- return $value
-}
-
-#
-# Returns Tcl code in the form of code which evaluates to a list of
-# configure-time DEFINEs in the form {key val key2 val...}. It may
-# misbehave for values which are not numeric or simple strings.
-#
-proc teaish__dump_defs_to_list {args} {
- set lines {}
- lappend lines "\{"
- set skipper $::teaish__Config(defs-skip)
- lappend args \
- -none {
- TEAISH__*
- TEAISH_MAKEFILE_CODE
- AM_* AS_*
- } \
- -auto {
- SIZEOF_* HAVE_*
- } \
- -autolist *
- foreach n [lsort [dict keys [all-defines]]] {
- set type [teaish__defs_type $n $args]
- set value [teaish__defs_format $type [get-define $n]]
- if {$skipper ne $value} {
- lappend lines "$n $value"
- }
- }
- lappend lines "\}"
- return [join $lines "\n"]
-}
-
-#
-# 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
-# extension and its files.
-#
-# Accepts the following flags. Those marked with [L] are safe to use
-# during initial loading of tclish.tcl (recall that most teaish APIs
-# cannot be used until [teaish-configure] is called).
-#
-# static-pkgIndex.tcl [L]: Tells teaish that ./pkgIndex.tcl is not
-# a generated file, so it will not try to overwrite or delete
-# it. Errors out if it does not find pkgIndex.tcl in the
-# extension's dir.
-#
-# no-dist [L]: tells teaish to elide the 'make dist' recipe
-# from the generated Makefile.
-#
-# 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} {
- foreach arg $args {
- switch -exact -- $arg {
-
- static-pkgIndex.tcl {
- set tpi [file join $::teaish__Config(extension-dir) pkgIndex.tcl]
- if {[file exists $tpi]} {
- define TEAISH_PKGINDEX_TCL_IN ""
- define TEAISH_PKGINDEX_TCL $tpi
- set ::teaish__Config(pkgindex-policy) 0x20
- } else {
- proj-error "$arg: found no package-local pkgIndex.tcl\[.in]"
- }
- }
-
- no-dist {
- 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"
- }
- }
- }
-}
-
-#
-# @teaish-pkginfo-set ...flags
-#
-# The way to set up the initial package state. Used like:
-#
-# teaish-pkginfo-set -name foo -version 0.1.2
-#
-# Or:
-#
-# teaish-pkginfo-set ?-vars|-subst? {-name foo -version 0.1.2}
-#
-# The latter may be easier to write for a multi-line invocation.
-#
-# For the second call form, passing the -vars flag tells it to perform
-# a [subst] of (only) variables in the {...} part from the calling
-# scope. The -subst flag will cause it to [subst] the {...} with
-# command substitution as well (but no backslash substitution). When
-# using -subst for string concatenation, e.g. with -libDir
-# foo[get-version-number], be sure to wrap the value in braces:
-# -libDir {foo[get-version-number]}.
-#
-# Each pkginfo flag corresponds to one piece of extension package
-# info. Teaish provides usable default values for all of these flags,
-# but at least the -name and -version should be set by clients.
-# e.g. the default -name is the directory name the extension lives in,
-# which may change (e.g. when building it from a "make dist" bundle).
-#
-# The flags:
-#
-# -name theName: The extension's name. It defaults to the name of the
-# directory containing the extension. (In TEA this would be the
-# PACKAGE_NAME, not to be confused with...)
-#
-# -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
-# historical TEA PACKAGE_NAME.
-#
-# -version version: The extension's package version. Defaults to
-# 0.0.0.
-#
-# -libDir dirName: The base name of the directory into which this
-# extension should be installed. It defaults to a concatenation of
-# `-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 `-name.pkg` because Tcl's `load` plugin system
-# expects it in that form.
-#
-# -options {...}: If provided, it must be a list compatible with
-# Autosetup's `options-add` function. These can also be set up via
-# `teaish-options`.
-#
-# -vsatisfies {{...} ...}: Expects a list-of-lists of conditions
-# for Tcl's `package vsatisfies` command: each list entry is a
-# sub-list of `{PkgName Condition...}`. Teaish inserts those
-# checks via its default pkgIndex.tcl.in and teaish.tester.tcl.in
-# templates to verify that the system's package dependencies meet
-# these requirements. The default value is `{{Tcl 8.5-}}` (recall
-# that it's a list-of-lists), as 8.5 is the minimum Tcl version
-# teaish will run on, but some extensions may require newer
-# versions or dependencies on other packages. As a special case,
-# if `-vsatisfies` is given a single token, e.g. `8.6-`, then it
-# is transformed into `{Tcl $thatToken}`, i.e. it checks the Tcl
-# version which the package is being run with. If given multiple
-# lists, each `package provides` check is run in the given
-# 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:
-#
-# static-pkgIndex.tcl: tells teaish that the client manages their
-# own pkgIndex.tcl, so that teaish won't try to overwrite it
-# using a template.
-#
-# no-dist: tells teaish to elide the "make dist" recipe from the
-# makefile so that the client can implement it.
-#
-# no-dll: tells teaish to elide the makefile rules which build
-# the DLL, as well as any templated test script and pkgIndex.tcl
-# references to them. The intent here is to (A) support
-# client-defined build rules for the DLL and (B) eventually
-# 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 {
- incr doVars
- set xargs [lassign $xargs -]
- }
- -subst {
- incr doVars
- incr doCommands
- set xargs [lassign $xargs -]
- }
- default {
- break
- }
- }
- }
- set args $xargs
- unset xargs
- if {1 == [llength $args] && [llength [lindex $args 0]] > 1} {
- # Transform a single {...} arg into the canonical call form
- set a [list {*}[lindex $args 0]]
- if {$doVars || $doCommands} {
- set sflags -nobackslashes
- if {!$doCommands} {
- lappend sflags -nocommands
- }
- set a [uplevel 1 [list subst {*}$sflags $a]]
- }
- set args $a
- }
- set sentinel "<nope>"
- set flagDefs [list]
- foreach {f d} $::teaish__Config(pkginfo-f2d) {
- lappend flagDefs $f => $sentinel
- }
- proj-parse-simple-flags args flags $flagDefs
- if {[llength $args]} {
- proj-error -up "Too many (or unknown) arguments to [proj-scope]: $args"
- }
- foreach {f d} $::teaish__Config(pkginfo-f2d) {
- 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
- }
- }
- -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
- if {$f in {-name -version -libDir -loadPrefix}} {
- lappend recalc $f
- }
- }
- if {"" ne $recalc} {
- teaish__define_pkginfo_derived $recalc
- }
-}
-
-#
-# @teaish-pkginfo-get ?arg?
-#
-# If passed no arguments, it returns the extension config info in the
-# same form accepted by teaish-pkginfo-set.
-#
-# If passed one -flagname arg then it returns the value of that config
-# option.
-#
-# Else it treats arg as the name of caller-scoped variable to
-# which this function assigns an array containing the configuration
-# state of this extension, in the same structure accepted by
-# teaish-pkginfo-set. In this case it returns an empty string.
-#
-proc teaish-pkginfo-get {args} {
- set cases {}
- set argc [llength $args]
- set rv {}
- switch -exact $argc {
- 0 {
- # Return a list of (-flag value) pairs
- lappend cases default {{
- if {[info exists ::teaish__PkgInfo($flag)]} {
- lappend rv $flag $::teaish__PkgInfo($flag)
- } else {
- lappend rv $flag [get-define $defName]
- }
- }}
- }
-
- 1 {
- set arg $args
- if {[string match -* $arg]} {
- # Return the corresponding -flag's value
- lappend cases $arg {{
- if {[info exists ::teaish__PkgInfo($flag)]} {
- return $::teaish__PkgInfo($flag)
- } else {
- return [get-define $defName]
- }
- }}
- } else {
- # Populate target with an array of (-flag value).
- upvar $arg tgt
- array set tgt {}
- lappend cases default {{
- if {[info exists ::teaish__PkgInfo($flag)]} {
- set tgt($flag) $::teaish__PkgInfo($flag)
- } else {
- set tgt($flag) [get-define $defName]
- }
- }}
- }
- }
-
- default {
- proj-error "invalid arg count from [proj-scope 1]"
- }
- }
-
- foreach {flag defName} $::teaish__Config(pkginfo-f2d) {
- switch -exact -- $flag [join $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...
-#
-# Queues one or more arbitrary "feature test" functions to be run when
-# teaish-checks-run is called. $flag must be one of -pre or -post to
-# specify whether the tests should be run before or after
-# teaish-configure is run. Each additional arg is the name of a
-# feature-test proc.
-#
-proc teaish-checks-queue {flag args} {
- if {$flag ni {-pre -post}} {
- proj-error "illegal flag: $flag"
- }
- lappend ::teaish__Config(queued-checks${flag}) {*}$args
-}
-
-#
-# @teaish-checks-run -pre|-post
-#
-# Runs all feature checks queued using teaish-checks-queue
-# then cleares the queue.
-#
-proc teaish-checks-run {flag} {
- if {$flag ni {-pre -post}} {
- proj-error "illegal flag: $flag"
- }
- #puts "*** running $flag: $::teaish__Config(queued-checks${flag})"
- set foo 0
- foreach f $::teaish__Config(queued-checks${flag}) {
- if {![teaish-feature-cache-check $f foo]} {
- set v [$f]
- teaish-feature-cache-set $f $v
- }
- }
- set ::teaish__Config(queued-checks${flag}) {}
-}
-
-#
-# A general-purpose getter for various teaish state. Requires one
-# flag, which determines its result value. Flags marked with [L] below
-# are safe for using at load-time, before teaish-pkginfo-set is called
-#
-# -dir [L]: returns the extension's directory, which may differ from
-# the teaish core dir or the build dir.
-#
-# -teaish-home [L]: the "home" dir of teaish itself, which may
-# differ from the extension dir or build dir.
-#
-# -build-dir [L]: the build directory (typically the current working
-# -dir).
-#
-# Any of the teaish-pkginfo-get/get flags: returns the same as
-# teaish-pkginfo-get. Not safe for use until teaish-pkginfo-set has
-# been called.
-#
-# 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)
- }
- -teaish-home {
- return $::autosetup(srcdir)
- }
- -build-dir {
- return $::autosetup(builddir)
- }
- default {
- if {[info exists ::teaish__PkgInfo($flag)]} {
- return $::teaish__PkgInfo($flag)
- }
- }
- }
- proj-error "Unhandled flag: $flag"
-}
-
-#
-# Handles --teaish-create-extension=TARGET-DIR
-#
-proc teaish__create_extension {dir} {
- set force [opt-bool teaish-force]
- if {"" eq $dir} {
- proj-error "--teaish-create-extension=X requires a directory name."
- }
- file mkdir $dir/generic
- set cwd [pwd]
- #set dir [file-normalize [file join $cwd $dir]]
- teaish__verbose 1 msg-result "Created dir $dir"
- cd $dir
- if {!$force} {
- # Ensure that we don't blindly overwrite anything
- foreach f {
- generic/teaish.c
- teaish.tcl
- teaish.make.in
- teaish.test.tcl
- } {
- if {[file exists $f]} {
- error "Cowardly refusing to overwrite $dir/$f. Use --teaish-force to overwrite."
- }
- }
- }
-
- set name [file tail $dir]
- set pkgName $name
- set version 0.0.1
- set loadPrefix [string totitle $pkgName]
- 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
- # bootstrapping is finished, so only teaish-*
- # APIs which are explicitly noted as being safe
- # early on may be used here. Any autosetup-related
- # APIs may be used here.
- #
- # Return an empty string if there are no options to
- # add or if they are added using \[options-add\].
- #
- # If there are no options to add, this proc need
- # 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 generic/teaish.c
- teaish-define-to-cflag -quote TEAISH_PKGNAME TEAISH_VERSION
-
- # TODO: your code goes here..
-}
-}; # $content
- proj-file-write teaish.tcl $content
- 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
-# the package, run any teaish.pkginit.tcl code, and loaded
-# autosetup/teaish/tester.tcl.
-"
- proj-file-write teaish.test.tcl $content
- teaish__verbose 1 msg-result "Created teaish.test.tcl"
-
- set content [subst -nocommands -nobackslashes {
-#include <tcl.h>
-static int
-${loadPrefix}_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]){
- Tcl_SetObjResult(interp, Tcl_NewStringObj("this is the ${name} extension", -1));
- return TCL_OK;
-}
-
-extern int DLLEXPORT ${loadPrefix}_Init(Tcl_Interp *interp){
- if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
- return TCL_ERROR;
- }
- if (Tcl_PkgProvide(interp, TEAISH_PKGNAME, TEAISH_VERSION) == TCL_ERROR) {
- return TCL_ERROR;
- }
- Tcl_CreateObjCommand(interp, TEAISH_PKGNAME, ${loadPrefix}_Cmd, NULL, NULL);
- return TCL_OK;
-}
-}]
- 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)/generic/teaish.c
-# tx.LDFLAGS =
-# tx.CFLAGS =
-"
- proj-file-write teaish.make.in $content
- teaish__verbose 1 msg-result "Created teaish.make.in"
-
- 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\]."
-}
diff --git a/autoconf/tea/autosetup/feature-tests.tcl b/autoconf/tea/autosetup/feature-tests.tcl
deleted file mode 100644
index 6c927d1a7..000000000
--- a/autoconf/tea/autosetup/feature-tests.tcl
+++ /dev/null
@@ -1,214 +0,0 @@
-########################################################################
-# 2025 April 7
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# * May you do good and not evil.
-# * May you find forgiveness for yourself and forgive others.
-# * May you share freely, never taking more than you give.
-#
-########################################################################
-# ----- @module feature-tests.tcl -----
-# @section TEA-ish collection of feature tests.
-#
-# Functions in this file with a prefix of teaish__ are
-# private/internal APIs. Those with a prefix of teaish- are
-# public APIs.
-
-
-# @teaish-check-libz
-#
-# Checks for zlib.h and the function deflate in libz. If found,
-# prepends -lz to the extension's ldflags and returns 1, else returns
-# 0. It also defines LDFLAGS_LIBZ to the libs flag.
-#
-proc teaish-check-libz {} {
- teaish-check-cached "Checking for libz" {
- set rc 0
- if {[msg-quiet cc-check-includes zlib.h] && [msg-quiet proj-check-function-in-lib deflate z]} {
- teaish-ldflags-prepend [define LDFLAGS_LIBZ [get-define lib_deflate]]
- undefine lib_deflate
- incr rc
- }
- expr $rc
- }
-}
-
-# @teaish-check-librt ?funclist?
-#
-# Checks whether -lrt is needed for any of the given functions. If
-# so, appends -lrt via [teaish-ldflags-prepend] and returns 1, else
-# returns 0. It also defines LDFLAGS_LIBRT to the libs flag or an
-# empty string.
-#
-# Some systems (ex: SunOS) require -lrt in order to use nanosleep.
-#
-proc teaish-check-librt {{funclist {fdatasync nanosleep}}} {
- teaish-check-cached -nostatus "Checking whether ($funclist) need librt" {
- define LDFLAGS_LIBRT ""
- foreach func $funclist {
- if {[msg-quiet proj-check-function-in-lib $func rt]} {
- set ldrt [get-define lib_${func}]
- undefine lib_${func}
- if {"" ne $ldrt} {
- teaish-ldflags-prepend -r [define LDFLAGS_LIBRT $ldrt]
- msg-result $ldrt
- return 1
- } else {
- msg-result "no lib needed"
- return 1
- }
- }
- }
- msg-result "not found"
- return 0
- }
-}
-
-# @teaish-check-stdint
-#
-# A thin proxy for [cc-with] which checks for <stdint.h> and the
-# various fixed-size int types it declares. It defines HAVE_STDINT_T
-# to 0 or 1 and (if it's 1) defines HAVE_XYZ_T for each XYZ int type
-# to 0 or 1, depending on whether its available.
-proc teaish-check-stdint {} {
- teaish-check-cached "Checking for stdint.h" {
- msg-quiet cc-with {-includes stdint.h} \
- {cc-check-types int8_t int16_t int32_t int64_t intptr_t \
- uint8_t uint16_t uint32_t uint64_t uintptr_t}
- }
-}
-
-# @teaish-is-mingw
-#
-# Returns 1 if building for mingw, else 0.
-proc teaish-is-mingw {} {
- return [expr {
- [string match *mingw* [get-define host]] &&
- ![file exists /dev/null]
- }]
-}
-
-# @teaish-check-libdl
-#
-# Checks for whether dlopen() can be found and whether it requires
-# -ldl for linking. If found, returns 1, defines LDFLAGS_DLOPEN to the
-# linker flags (if any), and passes those flags to
-# teaish-ldflags-prepend. It unconditionally defines HAVE_DLOPEN to 0
-# or 1 (the its return result value).
-proc teaish-check-dlopen {} {
- teaish-check-cached -nostatus "Checking for dlopen()" {
- set rc 0
- set lfl ""
- if {[cc-with {-includes dlfcn.h} {
- cctest -link 1 -declare "extern char* dlerror(void);" -code "dlerror();"}]} {
- msg-result "-ldl not needed"
- incr rc
- } elseif {[cc-check-includes dlfcn.h]} {
- incr rc
- if {[cc-check-function-in-lib dlopen dl]} {
- set lfl [get-define lib_dlopen]
- undefine lib_dlopen
- msg-result " dlopen() needs $lfl"
- } else {
- msg-result " - dlopen() not found in libdl. Assuming dlopen() is built-in."
- }
- } else {
- msg-result "not found"
- }
- teaish-ldflags-prepend [define LDFLAGS_DLOPEN $lfl]
- define HAVE_DLOPEN $rc
- }
-}
-
-#
-# @teaish-check-libmath
-#
-# Handles the --enable-math flag. Returns 1 if found, else 0.
-# If found, it prepends -lm (if needed) to the linker flags.
-proc teaish-check-libmath {} {
- teaish-check-cached "Checking for libc math library" {
- set lfl ""
- set rc 0
- if {[msg-quiet proj-check-function-in-lib ceil m]} {
- incr rc
- set lfl [get-define lib_ceil]
- undefine lib_ceil
- teaish-ldflags-prepend $lfl
- msg-checking "$lfl "
- }
- define LDFLAGS_LIBMATH $lfl
- expr $rc
- }
-}
-
-# @teaish-import-features ?-flags? feature-names...
-#
-# For each $name in feature-names... it invokes:
-#
-# use teaish/feature/$name
-#
-# to load TEAISH_AUTOSETUP_DIR/feature/$name.tcl
-#
-# By default, if a proc named teaish-check-${name}-options is defined
-# after sourcing a file, it is called and its result is passed to
-# proj-append-options. This can be suppressed with the -no-options
-# flag.
-#
-# Flags:
-#
-# -no-options: disables the automatic running of
-# teaish-check-NAME-options,
-#
-# -run: if the function teaish-check-NAME exists after importing
-# then it is called. This flag must not be used when calling this
-# function from teaish-options. This trumps both -pre and -post.
-#
-# -pre: if the function teaish-check-NAME exists after importing
-# then it is passed to [teaish-checks-queue -pre].
-#
-# -post: works like -pre but instead uses[teaish-checks-queue -post].
-proc teaish-import-features {args} {
- set pk ""
- set doOpt 1
- proj-parse-simple-flags args flags {
- -no-options 0 {set doOpt 0}
- -run 0 {expr 1}
- -pre 0 {set pk -pre}
- -post 0 {set pk -post}
- }
- #
- # TODO: never import the same module more than once. The "use"
- # command is smart enough to not do that but we would need to
- # remember whether or not any teaish-check-${arg}* procs have been
- # called before, and skip them.
- #
- if {$flags(-run) && "" ne $pk} {
- proj-error "Cannot use both -run and $pk" \
- " (called from [proj-scope 1])"
- }
-
- foreach arg $args {
- uplevel "use teaish/feature/$arg"
- if {$doOpt} {
- set n "teaish-check-${arg}-options"
- if {[llength [info proc $n]] > 0} {
- if {"" ne [set x [$n]]} {
- options-add $x
- }
- }
- }
- if {$flags(-run)} {
- set n "teaish-check-${arg}"
- if {[llength [info proc $n]] > 0} {
- uplevel 1 $n
- }
- } elseif {"" ne $pk} {
- set n "teaish-check-${arg}"
- if {[llength [info proc $n]] > 0} {
- teaish-checks-queue {*}$pk $n
- }
- }
- }
-}
diff --git a/autoconf/tea/autosetup/tester.tcl b/autoconf/tea/autosetup/tester.tcl
deleted file mode 100644
index 5c546e841..000000000
--- a/autoconf/tea/autosetup/tester.tcl
+++ /dev/null
@@ -1,193 +0,0 @@
-########################################################################
-# 2025 April 5
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# * May you do good and not evil.
-# * May you find forgiveness for yourself and forgive others.
-# * May you share freely, never taking more than you give.
-#
-########################################################################
-#
-# Helper routines for running automated tests on teaish extensions
-#
-########################################################################
-# ----- @module teaish-tester.tcl -----
-#
-# @section TEA-ish Testing APIs.
-#
-# Though these are part of the autosup dir hierarchy, they are not
-# intended to be run from autosetup code. Rather, they're for
-# use with/via teaish.tester.tcl.
-
-#
-# @test-current-scope ?lvl?
-#
-# Returns the name of the _calling_ proc from ($lvl + 1) levels up the
-# call stack (where the caller's level will be 1 up from _this_
-# call). If $lvl would resolve to global scope "global scope" is
-# returned and if it would be negative then a string indicating such
-# is returned (as opposed to throwing an error).
-#
-proc test-current-scope {{lvl 0}} {
- #uplevel [expr {$lvl + 1}] {lindex [info level 0] 0}
- set ilvl [info level]
- set offset [expr {$ilvl - $lvl - 1}]
- if { $offset < 0} {
- return "invalid scope ($offset)"
- } elseif { $offset == 0} {
- return "global scope"
- } else {
- return [lindex [info level $offset] 0]
- }
-}
-
-# @test-msg
-#
-# Emits all arugments to stdout.
-#
-proc test-msg {args} {
- puts "$args"
-}
-
-# @test-warn
-#
-# Emits all arugments to stderr.
-#
-proc test-warn {args} {
- puts stderr "WARNING: $args"
-}
-
-#
-# @test-error msg
-#
-# Triggers a test-failed error with a string describing the calling
-# scope and the provided message.
-#
-proc test-fail {args} {
- #puts stderr "ERROR: \[[test-current-scope 1]]: $msg"
- #exit 1
- error "FAIL: \[[test-current-scope 1]]: $args"
-}
-
-#
-# Internal impl for assert-likes. Should not be called directly by
-# client code.
-#
-proc test__assert {lvl script {msg ""}} {
- set src "expr \{ $script \}"
- # puts "XXXX evalling $src";
- if {![uplevel $lvl $src]} {
- if {"" eq $msg} {
- set msg $script
- }
- set caller1 [test-current-scope $lvl]
- incr lvl
- set caller2 [test-current-scope $lvl]
- error "Assertion failed in: \[$caller2 -> $caller1]]: $msg"
- }
-}
-
-#
-# @assert script ?message?
-#
-# Kind of like a C assert: if uplevel (eval) of [expr {$script}] is
-# false, a fatal error is triggered. The error message, by default,
-# includes the body of the failed assertion, but if $msg is set then
-# that is used instead.
-#
-proc assert {script {msg ""}} {
- test__assert 1 $script $msg
-}
-
-#
-# @test-assert testId script ?msg?
-#
-# Works like [assert] but emits $testId to stdout first.
-#
-proc test-assert {testId script {msg ""}} {
- puts "test $testId"
- test__assert 2 $script $msg
-}
-
-#
-# @test-expect testId script result
-#
-# Runs $script in the calling scope and compares its result to
-# $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 [string trim [uplevel 1 $script]]
- set result [string trim $result]
- test__assert 1 {$x eq $result} \
- "\nEXPECTED: <<$result>>\nGOT: <<$x>>"
-}
-
-#
-# @test-catch cmd ?...args?
-#
-# Runs [cmd ...args], repressing any exception except to possibly log
-# the failure. Returns 1 if it caught anything, 0 if it didn't.
-#
-proc test-catch {cmd args} {
- if {[catch {
- $cmd {*}$args
- } rc xopts]} {
- puts "[test-current-scope] ignoring failure of: $cmd [lindex $args 0]: $rc"
- return 1
- }
- return 0
-}
-
-if {![array exists ::teaish__BuildFlags]} {
- array set ::teaish__BuildFlags {}
-}
-
-#
-# @teaish-build-flag3 flag tgtVar ?dflt?
-#
-# If the current build has the configure-time flag named $flag set
-# then tgtVar is assigned its value and 1 is returned, else tgtVal is
-# assigned $dflt and 0 is returned.
-#
-# Caveat #1: only valid when called in the context of teaish's default
-# "make test" recipe, e.g. from teaish.test.tcl. It is not valid from
-# a teaish.tcl configure script because (A) the state it relies on
-# doesn't fully exist at that point and (B) that level of the API has
-# more direct access to the build state. This function requires that
-# an external script have populated its internal state, which is
-# normally handled via teaish.tester.tcl.in.
-#
-# Caveat #2: defines in the style of HAVE_FEATURENAME with a value of
-# 0 are, by long-standing configure script conventions, treated as
-# _undefined_ here.
-#
-proc teaish-build-flag3 {flag tgtVar {dflt ""}} {
- upvar $tgtVar tgt
- if {[info exists ::teaish__BuildFlags($flag)]} {
- set tgt $::teaish__BuildFlags($flag)
- return 1;
- } elseif {0==[array size ::teaish__BuildFlags]} {
- test-warn \
- "\[[test-current-scope]] was called from " \
- "[test-current-scope 1] without the build flags imported."
- }
- set tgt $dflt
- return 0
-}
-
-#
-# @teaish-build-flag flag ?dflt?
-#
-# Convenience form of teaish-build-flag3 which returns the
-# configure-time-defined value of $flag or "" if it's not defined (or
-# if it's an empty string).
-#
-proc teaish-build-flag {flag {dflt ""}} {
- set tgt ""
- teaish-build-flag3 $flag tgt $dflt
- return $tgt
-}
diff --git a/autoconf/tea/teaish.tcl b/autoconf/tea/teaish.tcl
index 87d059c32..9333495aa 100644
--- a/autoconf/tea/teaish.tcl
+++ b/autoconf/tea/teaish.tcl
@@ -117,7 +117,7 @@ proc teaish-options {} {
# work needed for this extension.
#
proc teaish-configure {} {
- use teaish/feature-tests
+ use teaish/feature
teaish-src-add -dist -dir generic/tclsqlite3.c