# CFLAGS.configure = CFLAGS as known at configure-time.
#
# This ordering is deliberate: flags populated via tcl's
-# [teaish-add-cflags] should preceed CFLAGS and CPPFLAGS (which
+# [teaish-cflags-add] should preceed CFLAGS and CPPFLAGS (which
# typically come from the ./configure command-line invocation).
#
CFLAGS.configure = @SH_CFLAGS@ @TEAISH_CFLAGS@ @CFLAGS@ @CPPFLAGS@ $(TCL_INCLUDE_SPEC)
# LDFLAGS.configure = LDFLAGS as known at configure-time.
#
# This ordering is deliberate: flags populated via tcl's
-# [teaish-add-ldflags] should preceed LDFLAGS (which typically
+# [teaish-ldflags-add] should preceed LDFLAGS (which typically
# comes from the ./configure command-line invocation).
#
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-add-src], but may also be appended to
+# sources passed to [teaish-src-add], but may also be appended to
# by teaish.make.
#
tx.src =@TEAISH_SRC@
#
# The list of 'dist' files may be appended to from teaish.make.in.
-# It can also be set up from teaish.tcl using [teaish-add-dist]
-# and/or [teaish-add-src -dist ...].
+# It can also be set up from teaish.tcl using [teaish-dist-add]
+# and/or [teaish-src-add -dist ...].
#
tx.dist.files = @TEAISH_DIST_FILES@
$(teaish.makefile): $(teaish__auto.def) $(teaish.makefile.in) \
@AUTODEPS@
-@if TEAISH_TEST_TCL_IN
-#config.log: @TEAISH_TEST_TCL_IN@
-#@TEAISH_TEST_TCL_IN@:
-#@TEAISH_TEST_TCL@: @TEAISH_TEST_TCL_IN@
-@endif
-
@TEAISH_TESTER_TCL_IN@:
@TEAISH_TESTER_TCL@: @TEAISH_TESTER_TCL_IN@
config.log: @TEAISH_TESTER_TCL@
all: $(tx.dll)
tclsh: $(teaish.makefile) config.log
- @{ echo "#!/bin/sh"; echo "exec $(TCLSH) \"\$$@\""; } > $@
+ @{ echo "#!/bin/sh"; echo 'exec $(TCLSH) "$$@"'; } > $@
@chmod +x $@
@echo "Created $@"
# - tx.src = list of the extension's source files, being sure to
# prefix each with $(tx.dir) (if it's in the same dir as the
# extension) so that out-of-tree builds can find them. Optionally,
-# [define] TEAISH_SRC or pass them to [teaish-add-src].
+# [define] TEAISH_SRC or pass them to [teaish-src-add].
#
# It may optionally set the following vars:
#
# - tx.CFLAGS = CFLAGS/CPPFLAGS. Optionally, [define] TEAISH_CFLAGS
-# or pass them to [teaish-add-cflags].
+# or pass them to [teaish-cflags-add].
#
# - tx.LDFLAGS = LDFLAGS. Optionally, [define] TEAISH_LDFLAGS or
-# pass them to [teaish-add-ldflags].
+# pass them to [teaish-ldflags-add].
#
# It may optionally hook into various targets as documented in
# /doc/extensions.md in the canonical teaish source tree.
#
# TEAISH_MAKEFILE_CODE may contain literal makefile code, which
# gets pasted verbatim here. Either [define TEAISH_MAKEFILE_CODE
-# ...] or use [teaish-add-make] to incrementally build up this
+# ...] or use [teaish-make-add] to incrementally build up this
# content.
#
@if TEAISH_MAKEFILE_CODE
use proj
-define TEAISH_VERSION 0.1-beta
-use system ; # Will output "Host System" and "Build System" lines
-if {"--help" ni $::argv} {
- proj-tweak-default-env-dirs
- msg-result "TEA(ish) Version = [get-define TEAISH_VERSION]"
- msg-result "Source dir = $::autosetup(srcdir)"
- msg-result "Build dir = $::autosetup(builddir)"
-}
+define TEAISH_CORE_VERSION 0.1-beta
#
# API-internal settings and shared state.
#
# This might no longer be needed.
pkgindex-policy 0
+
+ #
+ # If 1+ then teaish__verbose will emit messages.
+ #
+ verbose 0
+
+ #
+ # Mapping of pkginfo -flags to their TEAISH_xxx define (if any).
+ #
+ pkginfo-f2d {
+ -name TEAISH_NAME
+ -pkgName TEAISH_PKGNAME
+ -libDir TEAISH_LIBDIR_NAME
+ -loadPrefix TEAISH_LOAD_PREFIX
+ -version TEAISH_VERSION
+ -vsatisfies TEAISH_VSATISFIES_TCL
+ -options {}
+ }
+
+ #
+ # Queues for use with teaish-checks-queue and teaish-checks-run.
+ #
+ queued-checks-pre {}
+ queued-checks-post {}
+
}]
set teaish__Config(core-dir) $::autosetup(libdir)/teaish
+#
+# 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} {
+proc teaish-argv-has {args} {
foreach glob $args {
foreach arg $::argv {
if {[string match $glob $arg]} {
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 = [get-define TEAISH_CORE_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 {} {
- #
- # "Declare" some defines...
- #
- foreach {f v} {
- TEAISH_MAKEFILE ""
- TEAISH_MAKEFILE_IN ""
- TEAISH_DIST_FILES ""
- TEAISH_TEST_TCL "" TEAISH_TEST_TCL_IN ""
- TEAISH_PKGINIT_TCL "" TEAISH_PKGINIT_TCL_IN ""
- TEAISH_PKGINDEX_TCL_IN "" TEAISH_PKGINDEX_TCL ""
- TEAISH_TCL ""
- TEAISH_CFLAGS ""
- TEAISH_LDFLAGS ""
- TEAISH_SRC ""
- TEAISH_VSATISFIES_TCL "8.5"
- } {
- define $f $v
- }
+ proj-tweak-default-env-dirs
set gotExt 0; # True if an extension config is found
- if {![teaish__argv_has --teaish-create-extension* --t-c-e*]} {
+ if {![teaish-argv-has --teaish-create-extension=* --t-c-e=*]} {
# Don't look for an extension if we're in --t-c-e mode
set gotExt [teaish__find_extension]
}
- if {$gotExt} {
- set ttcl [get-define TEAISH_TCL]
- proj-assert {[file exists $ttcl]} "Expecting to have found teaish.tcl by now"
- uplevel 1 "source $ttcl"
- if {"" eq [get-define TEAISH_NAME ""]} {
- proj-fatal "$ttcl did not define TEAISH_NAME"
- } elseif {"" eq [get-define TEAISH_VERSION ""]} {
- proj-fatal "$ttcl did not define TEAISH_VERSION"
- }
- unset ttcl
- }; # sourcing extension's teaish.tcl
-
#
- # Set up the --flags...
+ # 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.}
+ 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!}
+ 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
t-d-d
teaish-dump-defines => {Dump all configure-defined vars to config.defines.txt}
+ t-v
+ teaish-verbose=0
+ => {Enable more (often extraneous) messages from the teaish core.}
+
t-d
teaish-debug => {Enable teaish-specific debug output}
}]; # main options.
+ if {$gotExt} {
+ set ttcl [get-define TEAISH_TCL]
+ proj-assert {[file exists $ttcl]} "Expecting to have found teaish.tcl by now"
+ uplevel 1 [list source $ttcl]
+ proj-assert {"" ne [teaish-pkginfo-get -name]}
+ unset ttcl
+ # Set up some default values if the extension did not set them.
+ # This must happen _after_ it's sourced.
+ foreach {pflag key type val} {
+ - TEAISH_CFLAGS -v ""
+ - TEAISH_DIST_FILES -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_PKGINIT_TCL -v ""
+ - TEAISH_PKGINIT_TCL_IN -v ""
+ - TEAISH_SRC -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 {join [list \
+ [teaish-pkginfo-get -pkgName] \
+ [teaish-pkginfo-get -version]]}
+ -loadPrefix TEAISH_LOAD_PREFIX -e {string totitle [get-define TEAISH_PKGNAME ""]}
+ -vsatisfies TEAISH_VSATISFIES_TCL -v 8.5-
+ } {
+ set isDefOnly [expr {"-" eq $pflag}]
+ if {!$isDefOnly && [info exists ::teaish__Config($pflag)]} {
+ continue;
+ }
+ set got [get-define $key "<nope>"]
+ if {$isDefOnly && "<nope>" ne $got} {
+ continue
+ }
+ switch -exact -- $type {
+ -v {}
+ -e { set val [eval $val] }
+ default { proj-error "Invalid type flag: $type" }
+ }
+ #puts "***** defining default $pflag $key {$val} isDefOnly=$isDefOnly got=$got"
+ define $key $val
+ if {!$isDefOnly} {
+ set ::teaish__Config($pflag) $val
+ }
+ }
+ unset key type val
+ }; # 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_TCL.
ted => teaish-extension-dir
t-e-d => teaish-extension-dir
t-f => teaish-force
+ t-v => teaish-verbose
}
+ set ::teaish__Config(verbose) [opt-bool teaish-verbose]
set ::teaish__Config(debug-enabled) [opt-bool teaish-debug]
if {[proj-opt-was-provided teaish-create-extension]} {
# --flags. This is what will import the client-defined teaish.tcl.
#
proc teaish__configure-phase1 {} {
- # Set up some default values if the user did not set them.
- foreach {key val} [list \
- TEAISH_PKGNAME [get-define TEAISH_NAME] \
- TEAISH_VERSION 0.0.0 \
- TEAISH_MAKEFILE_CODE ""] {
- if {"<nope>" eq [get-define $key "<nope>"]} {
- #puts "***** defining default $key $val"
- define $key $val
- }
- }
- # Do it again for vars which rely on defaults derived from other
- # vars.
- foreach {key val} [list \
- TEAISH_LIBDIR_NAME \
- [join [list \
- [get-define TEAISH_PKGNAME ""] \
- [get-define TEAISH_VERSION ""]] \
- "" ] \
- TEAISH_LOAD_PREFIX [string totitle \
- [get-define TEAISH_PKGNAME ""]] \
- TEAISH_PKGNAME [get-define TEAISH_NAME]] {
- if {"<nope>" eq [get-define $key "<nope>"]} {
- #puts "***** defining default $key $val"
- define $key $val
- }
- }
-
msg-result \
- "Configuring extension [proj-bold [get-define TEAISH_NAME] [get-define TEAISH_VERSION]]..."
+ [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
- teaish__check_common_bins
apply {{} {
#
# If --prefix or --exec-prefix are _not_ provided, use their
exec-prefix exec_prefix TCL_EXEC_PREFIX
} {
if {![proj-opt-was-provided $flag]} {
- set v [get-define $tclVar "???"]
- proj-assert {"???" ne $v} "Expecting teach-check-tcl to have defined $tclVar"
+ 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].
- msg-result "Using \$$tclVar for --$flag=$v"
}
}
}}; # --[exec-]prefix defaults
+ teaish__check_common_bins
+ #
+ # Set up library file names
+ #
proj-file-extensions
apply {{} {
- set pkgname [get-define TEAISH_NAME]
- set pkgver [get-define TEAISH_VERSION]
+ 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$pkgname$pkgver
- define TEAISH_DLL9_BASENAME ${libname}tcl9$pkgname$pkgver
+ 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
}}
- define TEAISH_AUTOSETUP_DIR $::teaish__Config(core-dir)
-# We'd need to import feature-tests.tcl too
-# foreach ft [glob -nocomplain [get-define TEAISH_AUTOSETUP_DIR]/feature/*.tcl] {
-# puts "Loading external feature test: $ft"
-# upscope 1 "source $ft"
-# }
-
+ 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
if {0} {
# Reminder: we cannot do a TEAISH_VSATISFIES_TCL check like the following
if {$vsat ne ""
&& ![package vsatisfies [package provide Tcl] $vsat]} {
error [join [list "Tcl package vsatisfies failed for" \
- [get-define TEAISH_NAME] \
- [get-define TEAISH_VERSION] \
+ [teaish-pkginfo-get -name] \
+ [teaish-pkginfo-get -version] \
": expecting vsatisfies to match ($vsat)"]]
}
unset vsat
# 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-add-cflags -DUSE_TCL_STUBS=1
+ teaish-cflags-add -DUSE_TCL_STUBS=1
}
#define AS_LIBDIR $::autosetup(libdir)
# when rebuilding for different --with-tcl=... values.
#
if {!$::teaish__Config(pkgindex-policy)} {
- proj-fatal "Cannot determine which pkgIndex.tcl to use"
+ 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"
- msg-result "Using pkgIndex from $tpi"
+ teaish__verbose 1 msg-result "Using pkgIndex from $tpi"
}}; # $::teaish__Config(pkgindex-policy)
set dEx $::teaish__Config(teaish-dir)
proj-dot-ins-append $dSrc/Makefile.in
proj-dot-ins-append $dSrc/teaish.tester.tcl.in
- if {[get-define TEAISH_OUT_OF_EXT_TREE]} {
- define TEAISH_ENABLE_DIST 0
- } else {
- define TEAISH_ENABLE_DIST 1
- }
-
+ define TEAISH_ENABLE_DIST [expr {![get-define TEAISH_OUT_OF_EXT_TREE]}]
+ define TEAISH_AUTOSETUP_DIR $::teaish__Config(core-dir)
proj-setup-autoreconfig TEAISH_AUTORECONFIG
foreach f {
TEAISH_CFLAGS
set srcdir $::autosetup(srcdir)
msg-result "Checking for a suitable tcl... "
set use_tcl 1
- set with_tclsh [opt-val with-tclsh]
- set with_tcl [opt-val with-tcl]
+ set with_tclsh [opt-val with-tclsh [proj-get-env TCLSH]]
+ set with_tcl [opt-val with-tcl [proj-get-env TCL_HOME]]
if {0} {
# This misinteracts with the $TCL_PREFIX default: it will use the
# autosetup-defined --prefix default
# --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-fatal "TCL shell $with_tclsh is not executable"
+ proj-error "TCL shell $with_tclsh is not executable"
} else {
define TCLSH_CMD $with_tclsh
#msg-result "Using tclsh: $with_tclsh"
[catch {exec $with_tclsh $::autosetup(libdir)/find_tclconfig.tcl} result] == 0} {
set with_tcl $result
}
- if {"" ne $with_tcl && [file isdir $with_tcl]} {
- msg-result "$with_tclsh recommends the tclConfig.sh from $with_tcl"
+ if {"" ne $with_tcl && [file isdirectory $with_tcl]} {
+ teaish__verbose 1 msg-result "$with_tclsh recommends the tclConfig.sh from $with_tcl"
} else {
proj-warn "$with_tclsh is unable to recommend a tclConfig.sh"
set use_tcl 0
}
}
if {"" eq $cfg} {
- proj-fatal "No tclConfig.sh found under ${with_tcl}"
+ proj-error "No tclConfig.sh found under ${with_tcl}"
}
} else {
# If we have not yet found a tclConfig.sh file, look in $libdir
break
}
}
- msg-result "Using tclConfig.sh: $cfg"
+ teaish__verbose 1 msg-result "Using tclConfig.sh = $cfg"
break
}
define TCL_CONFIG_SH $cfg
if {"" ne $with_tclsh &&
[catch {exec echo "puts stdout \$auto_path" | "$with_tclsh"} result] == 0} {
foreach i $result {
- if {[file isdir $i]} {
+ if {[file isdirectory $i]} {
set tcllibdir $i/$extDirName
break
}
}
} else {
- proj-fatal "Cannot determine TCLLIBDIR."
+ proj-error "Cannot determine TCLLIBDIR."
}
}
define TCLLIBDIR $tcllibdir
}; # find TCLLIBDIR
if {[file-isexec $with_tclsh]} {
- msg-result "Using tclsh: $with_tclsh"
+ teaish__verbose 1 msg-result "Using tclsh = $with_tclsh"
if {$cfg ne ""} {
define HAVE_TCL 1
} else {
# 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]} {
- proj-fatal "Did not find tclsh"
+ 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
- found.
+ found, or --with-tclsh=/path/to/tclsh to allow the tclsh binary
+ to locate its tclConfig.sh.
}
}
-}; # teaish-check-tcl
+ msg-result "Using Tcl [get-define TCL_VERSION]."
+}; # teaish__check_tcl
#
# Searches $::argv and/or the build dir and/or the source dir for
#
proc teaish__find_extension {} {
- msg-result "Looking for teaish extension..."
+ teaish__verbose 1 msg-result "Looking for teaish extension..."
# Helper for the foreach loop below.
set lambdaMT {{mustHave fid dir} {
- if {[file isdir $dir]} {
+ if {[file isdirectory $dir]} {
set f [file join $dir $fid]
if {[file readable $f]} {
return [file-normalize $f]
} elseif {$mustHave} {
- proj-fatal "Missing required $dir/$fid"
+ proj-error "Missing required $dir/$fid"
}
} elseif {$mustHave} {
- proj-fatal "--teaish-extension-dir=$dir does not reference a directory"
+ proj-error "--teaish-extension-dir=$dir does not reference a directory"
}
return ""
}}
#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
+ set extT ""; # teaish.tcl
set largv {}; # rewritten $::argv
set gotHelpArg 0; # got the --help
foreach arg $::argv {
# teaish.tcl.
regexp -- {--[^=]+=(.+)} $arg - extD
set extD [file-normalize $extD]
- if {![file isdir $extD]} {
- proj-fatal "--teaish-extension-dir value is not a directory: $extD"
+ if {![file isdirectory $extD]} {
+ proj-error "--teaish-extension-dir value is not a directory: $extD"
}
set extT [apply $lambdaMT 1 teaish.tcl $extD]
define TEAISH_DIR $extD
+ set ::teaish__Config(teaish-dir) $extD
}
--help {
incr gotHelpArg
}
}
if {![file readable $extT]} {
- proj-fatal "extension tcl file is not readable: $extT"
+ proj-error "extension tcl file is not readable: $extT"
}
define TEAISH_TCL $extT
}
define TEAISH_DIR $dirExt
set ::teaish__Config(teaish-dir) $dirExt
- # are we building in-tree vis-a-vis the extension?
set ::teaish__Config(blddir-is-extdir) \
[define TEAISH_ENABLE_DIST [expr {$dirBld eq $dirExt}]]
set addDist {{file} {
- teaish-add-dist [file tail $file]
+ teaish-dist-add [file tail $file]
}}
apply $addDist $extT
- msg-result "Extension dir = [get-define TEAISH_DIR]"
- msg-result "Extension config = $extT"
+ teaish__verbose 1 msg-result "Extension dir = [get-define TEAISH_DIR]"
+ teaish__verbose 1 msg-result "Extension config = $extT"
- define TEAISH_NAME [file tail [file dirname $extT]]
+ teaish-pkginfo-set -name [file tail [file dirname $extT]]
#
# teaish.make[.in] provides some of the info for the main makefile,
define TEAISH_MAKEFILE $extM
}
apply $addDist $extM
- msg-result "Extension makefile = $extM"
+ teaish__verbose 1 msg-result "Extension makefile = $extM"
} else {
define TEAISH_MAKEFILE_IN ""
define TEAISH_MAKEFILE ""
define TEAISH_PKGINIT_TCL $extI
}
apply $addDist $extI
- msg-result "Extension post-load init = $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
}
return 1
}; # teaish__find_extension
-# @teaish-add-cflags ?-p|prepend? ?-define? cflags...
+#
+# @teaish-cflags-add ?-p|prepend? ?-define? cflags...
#
# Equivalent to [proj-define-amend TEAISH_CFLAGS {*}$args].
#
-proc teaish-add-cflags {args} {
+proc teaish-cflags-add {args} {
proj-define-amend TEAISH_CFLAGS {*}$args
}
+#
# @teaish-define-to-cflag defineName...
#
# Uses [proj-define-to-cflag] to expand a list of [define] keys, each
# that to the current TEAISH_CFLAGS.
#
proc teaish-define-to-cflag {args} {
- teaish-add-cflags [proj-define-to-cflag {*}$args]
+ teaish-cflags-add [proj-define-to-cflag {*}$args]
}
-# @teaish-add-ldflags ?-p|-prepend? ?-define? ldflags...
+#
+# @teaish-ldflags-add ?-p|-prepend? ?-define? ldflags...
#
# Equivalent to [proj-define-amend TEAISH_LDFLAGS {*}$args].
#
# historical, and not relevant on all environments, but it is
# technically correct and still relevant on some environments.
#
-# See: teaish-prepend-ldflags
+# See: teaish-ldflags-prepend
#
-proc teaish-add-ldflags {args} {
+proc teaish-ldflags-add {args} {
proj-define-amend TEAISH_LDFLAGS {*}$args
}
-# @teaish-prepend-ldflags args...
#
-# Functionally equivalent to [teaish-add-ldflags -p {*}$args]
+# @teaish-ldflags-prepend args...
#
-proc teaish-prepend-ldflags {args} {
- teaish-add-ldflags -p {*}$args
+# Functionally equivalent to [teaish-ldflags-add -p {*}$args]
+#
+proc teaish-ldflags-prepend {args} {
+ teaish-ldflags-add -p {*}$args
}
-# @teaish-add-src ?-dist? ?-dir? src-files...
+#
+# @teaish-src-add ?-dist? ?-dir? src-files...
#
# Appends all non-empty $args to TEAISH_SRC.
#
# If passed -dist then it also passes each filename, as-is, to
-# [teaish-add-dist].
+# [teaish-dist-add].
#
# If passed -dir then each src-file has the TEAISH_DIR prepended to
# it for before they're added to TEAISH_SRC. As often as not, that
# sources, but there are cases where it's not desired (e.g. when using
# a source file from outside of the extension's dir).
#
-proc teaish-add-src {args} {
+proc teaish-src-add {args} {
set i 0
proj-parse-simple-flags args flags {
-dist 0 {return 1}
-dir 0 {return 1}
}
if {$flags(-dist)} {
- teaish-add-dist {*}$args
+ teaish-dist-add {*}$args
}
if {$flags(-dir)} {
set xargs {}
proj-define-append TEAISH_SRC {*}$args
}
-# @teaish-add-dist files-or-dirs...
+#
+# @teaish-dist-add files-or-dirs...
#
# Equivalent to [proj-define-apend TEAISH_DIST_FILES ...].
#
# It is not legal to call this until TEAISH_DIR has been reliably set
# (via teaish__find_extension).
#
-proc teaish-add-dist {args} {
+proc teaish-dist-add {args} {
if {$::teaish__Config(blddir-is-extdir)} {
proj-define-amend TEAISH_DIST_FILES {*}$args
}
}
-# teaish-add-install files...
+# teaish-install-add files...
# Equivalent to [proj-define-apend TEAISH_INSTALL_FILES ...].
-#proc teaish-add-install {args} {
+#proc teaish-install-add {args} {
# proj-define-amend TEAISH_INSTALL_FILES {*}$args
#}
+#
# @teash-append-make args...
#
# Appends makefile code to the TEAISH_MAKEFILE_CODE define. Each
# Anything else is appended verbatim. This function adds no additional
# spacing between each argument nor between subsequent invocations.
#
-proc teaish-add-make {args} {
+proc teaish-make-add {args} {
set out [get-define TEAISH_MAKEFILE_CODE ""]
foreach a $args {
switch -exact -- $a {
define TEAISH_MAKEFILE_CODE $out
}
+#
# @teaish-make-config-header filename
#
# Invokes autosetup's [make-config-header] and passes it $filename and
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.
proj-cache-set $key 1 $val
}
+#
# @teaish-feature-cache-check ?$key? tgtVarName
#
# Checks for a feature-check cache entry with the given key.
proj-cache-check $key 1 tgt
}
+#
# @teaish-check-cached@ ?-nostatus? msg script
#
# A proxy for feature-test impls which handles caching of a feature
set value $::teaish__Config(defs-skip)
}
default {
- proj-fatal \
+ proj-error \
"Unknown [project-current-scope] -type ($type) called from" \
[proj-current-scope 1]
}
if {[proj-first-file-found $flist tpi]} {
if {[string match *.in $tpi]} {
define TEAISH_PKGINDEX_TCL_IN $tpi
- teaish-add-dist [file tail $tpi]
+ teaish-dist-add [file tail $tpi]
define TEAISH_PKGINDEX_TCL [file rootname [file tail $pi]]
} else {
define TEAISH_PKGINDEX_TCL_IN ""
define TEAISH_PKGINDEX_TCL $tpi
- teaish-add-dist [file tail $tpi]
+ teaish-dist-add [file tail $tpi]
}
} else {
- proj-fatal "teaish-pragma $arg found no package-local pkgIndex.tcl\[.in]"
+ proj-error "teaish-pragma $arg found no package-local pkgIndex.tcl\[.in]"
}
set ::teaish__Config(pkgindex-policy) 0x10
}
}
}
+#
+# @teaish-pkginfo-set ...flags
+#
+# The preferred way to set up the initial package state. Used like:
+#
+# teaish-pkginfo-set -name foo -version 0.1.2
+#
+# Where each flag corresponds to one piece of extension package info.
+#
+# -name TEAISH_NAME
+# -pkgName TEAISH_PKGNAME
+# -libDir TEAISH_LIBDIR_NAME
+# -loadPrefix TEAISH_LOAD_PREFIX
+# -version TEAISH_VERSION
+# -vsatisfies TEAISH_VSATISFIES_TCL
+# -options {...} optional [options-add] value
+#
+proc teaish-pkginfo-set {args} {
+ set sentinel "<nope>"
+ set f2d $::teaish__Config(pkginfo-f2d)
+ set flagDefs [list]
+ foreach {f d} $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-current-scope]: $args"
+ }
+ foreach {f d} $f2d {
+ if {$sentinel ne [set v $flags($f)]} {
+ switch -exact -- $f {
+ -options {
+ options-add $v
+ }
+ default {
+ define $d $v
+ }
+ }
+ set ::teaish__Config($f) $v
+ }
+ }
+}
+
+#
+# @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__Config($flag)]} {
+ lappend rv $flag $::teaish__Config($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__Config($flag)]} {
+ return $::teaish__Config($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__Config($flag)]} {
+ set tgt($flag) $::teaish__Config($flag)
+ } else {
+ set tgt($flag) [get-define $defName]
+ }
+ }}
+ }
+ }
+
+ default {
+ proj-error "invalid arg count from [proj-current-scope 1]"
+ }
+ }
+
+ foreach {flag defName} $::teaish__Config(pkginfo-f2d) {
+ switch -exact -- $flag [join $cases]
+ }
+ if {0 == $argc} { return $rv }
+}
+
+#proc teaish-pget {flag} {
+# teaish-pkginfo-get $flag
+#}
+
#
# @teaish-enable-dist ?yes?
#
define TEAISH_ENABLE_DIST $yes
}
+#
+# @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}) {}
+}
#
# Handles --teaish-create-extension=TARGET-DIR
proc teaish__create_extension {dir} {
set force [opt-bool teaish-force]
if {"" eq $dir} {
- proj-fatal "--teaish-create-extension=X requires a directory name."
+ proj-error "--teaish-create-extension=X requires a directory name."
}
file mkdir $dir
set cwd [pwd]
set pkgName $name
set version 0.0.1
set loadPrefix [string totitle $pkgName]
- set content "define TEAISH_NAME ${name}
-define TEAISH_VERSION ${version}
-# define TEAISH_PKGNAME ${pkgName}
-# define TEAISH_LIBDIR_NAME ${name}${version}
-# define TEAISH_LOAD_PREFIX ${loadPrefix}
-proc teaish-options {} {
- # Return a list and/or use [options-add] to add new
+ set content "teaish-pkginfo-set \
+ -name ${name} \
+ -pkgName ${pkgName} \
+ -version ${version} \
+ -loadPrefix $loadPrefix \
+ -libDir ${name}${version}
+ -vsatisfies 8.5- \
+ -options { foo=1 => {Disable foo} }
+
+#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\].
+#}
+
proc teaish-configure {} {
- set d \[get-define TEAISH_DIR]
- teaish-add-src \$d/teaish.c
- teaish-add-dist teaish.c
+ set d \[get-define TEAISH_DIR\]
+ teaish-src-add \$d/teaish.c
+ teaish-dist-add teaish.c
+
+ # TODO: your code goes here..
}
"
proj-file-write teaish.tcl $content
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
+ msg-result "Created teaish.test.tcl"
+
set content [subst -nocommands -nobackslashes {
#include <tcl.h>
static int
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-prepend-ldflags [define LDFLAGS_LIBZ [get-define lib_deflate]]
+ teaish-ldflags-prepend [define LDFLAGS_LIBZ [get-define lib_deflate]]
undefine lib_deflate
incr rc
}
# @teaish-check-librt ?funclist?
#
# Checks whether -lrt is needed for any of the given functions. If
-# so, appends -lrt via [teaish-prepend-ldflags] and returns 1, else
+# 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.
#
set ldrt [get-define lib_${func}]
undefine lib_${func}
if {"" ne $ldrt} {
- teaish-prepend-ldflags -r [define LDFLAGS_LIBRT $ldrt]
+ teaish-ldflags-prepend -r [define LDFLAGS_LIBRT $ldrt]
msg-result $ldrt
return 1
} else {
# 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-prepend-ldflags. It unconditionally defines HAVE_DLOPEN to 0
+# 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()" {
} else {
msg-result "not found"
}
- teaish-prepend-ldflags [define LDFLAGS_DLOPEN $lfl]
+ teaish-ldflags-prepend [define LDFLAGS_DLOPEN $lfl]
define HAVE_DLOPEN $rc
}
}
incr rc
set lfl [get-define lib_ceil]
undefine lib_ceil
- teaish-prepend-ldflags $lfl
+ teaish-ldflags-prepend $lfl
msg-checking "$lfl "
}
define LDFLAGS_LIBMATH $lfl
}
}
-# @teaish-import-features ?-no-options? feature-names...
+# @teaish-import-features ?-flags? feature-names...
#
# For each $name in feature-names... it invokes:
#
# 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
- if {1} {
- set xopt [list]
- foreach arg $args {
- switch -exact -- $arg {
- -no-options {
- set doOpt 0
- }
- default {
- lappend xopt $arg
- }
- }
- }
- set args $xopt
+ 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-current-scope 1])"
}
+
foreach arg $args {
uplevel "use teaish/feature/$arg"
if {$doOpt} {
set n "teaish-check-${arg}-options"
if {[llength [info proc $n]] > 0} {
- set x [$n]
- if {"" ne $x} {
+ 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
+ }
+ }
}
}
# 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
# @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";
}
}
-########################################################################
+#
# @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. 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>>"
}
-########################################################################
+#
# @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
array set ::teaish__BuildFlags {}
}
+#
# @teaish-build-flag2 flag tgtVar ?dflt?
#
# Caveat #1: only valid when called in the context of teaish's default
return 0
}
+#
# @teaish-build-flag flag ?dflt?
#
# Convenience form of teaish-build-flag2 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-flag2 $flag tgt $dflt
}
@endif
if {[package vsatisfies [package provide Tcl] 9.0-]} {
- package ifneeded @TEAISH_PKGNAME@ @TEAISH_VERSION@ [list apply {{dir} {
- load [file join $dir @TEAISH_DLL9@] @TEAISH_LOAD_PREFIX@
+ package ifneeded {@TEAISH_PKGNAME@} {@TEAISH_VERSION@} [list apply {{dir} {
+ load [file join $dir {@TEAISH_DLL9@}] @TEAISH_LOAD_PREFIX@
@if TEAISH_PKGINIT_TCL_TAIL
- set initScript [file join $dir @TEAISH_PKGINIT_TCL_TAIL@]
+ set initScript [file join $dir {@TEAISH_PKGINIT_TCL_TAIL@}]
if {[file exists $initScript]} {
source -encoding utf-8 $initScript
}
@endif
}} $dir]
} else {
- package ifneeded @TEAISH_PKGNAME@ @TEAISH_VERSION@ [list apply {{dir} {
- if {[string tolower [file extension @TEAISH_DLL8@]] in [list .dll .dylib .so]} {
- load [file join $dir @TEAISH_DLL8@] @TEAISH_LOAD_PREFIX@
+ package ifneeded {@TEAISH_PKGNAME@} {@TEAISH_VERSION@} [list apply {{dir} {
+ if {[string tolower [file extension {@TEAISH_DLL8@}]] in [list .dll .dylib .so]} {
+ load [file join $dir {@TEAISH_DLL8@}] @TEAISH_LOAD_PREFIX@
} else {
load {} @TEAISH_LOAD_PREFIX@
}
@if TEAISH_PKGINIT_TCL_TAIL
- set initScript [file join $dir @TEAISH_PKGINIT_TCL_TAIL@]
+ set initScript [file join $dir {@TEAISH_PKGINIT_TCL_TAIL@}]
if {[file exists $initScript]} {
source -encoding utf-8 $initScript
}
# Teaish configure script for the SQLite TCL extension
-define TEAISH_NAME sqlite; # name used in dist tarballs and as the libdir prefix
-define TEAISH_PKGNAME sqlite3; # name for purposes of Tcl_PkgProvide()
-define TEAISH_LOAD_PREFIX Sqlite3; # 2nd arg to [load]
-define TEAISH_VSATISFIES_TCL 8.6-; # builds with 8.5 but some tests fail
-define TEAISH_VERSION [proj-file-content -trim [get-define TEAISH_DIR]/../VERSION]
-proj-assert {[string match 3.*.* [get-define TEAISH_VERSION]]}
-define TEAISH_LIBDIR_NAME \
- [join [list [get-define TEAISH_NAME] [get-define TEAISH_VERSION]] ""]
+apply {{} {
+ set version [proj-file-content -trim [get-define TEAISH_DIR]/../VERSION]
+ proj-assert {[string match 3.*.* $version]}
+ teaish-pkginfo-set \
+ -name sqlite \
+ -pkgName sqlite3 \
+ -version $version \
+ -loadPrefix Sqlite3 \
+ -vsatisfies 8.6- \
+ -libDir sqlite$version
+}}
#
# Object for communicating certain config-time state across various
use teaish/feature-tests
set srcdir [get-define TEAISH_DIR]
- teaish-add-src -dist -dir generic/tclsqlite3.c
- teaish-add-cflags -I${srcdir}/.. ; # for sqlite3.[ch]
+ teaish-src-add -dist -dir generic/tclsqlite3.c
+ teaish-cflags-add -I${srcdir}/..
if {[proj-opt-was-provided override-sqlite-version]} {
- define TEAISH_VERSION [opt-val override-sqlite-version]
- proj-warn "overriding sqlite version number: [get-define TEAISH_VERSION]"
+ teaish-pkginfo-set -version [opt-val override-sqlite-version]
+ proj-warn "overriding sqlite version number:" [teaish-pkginfo-get -version]
} elseif {[proj-opt-was-provided with-system-sqlite]
&& [opt-val with-system-sqlite] ne "0"} {
- proj-fatal "when using --with-system-sqlite also use"\
+ proj-fatal "when using --with-system-sqlite also use" \
"--override-sqlite-version to specify a library version number."
}
if {[opt-bool with-system-sqlite]} {
msg-result "Using system-level sqlite3."
- teaish-add-cflags -DUSE_SYSTEM_SQLITE
- teaish-add-ldflags -lsqlite3
+ teaish-cflags-add -DUSE_SYSTEM_SQLITE
+ teaish-ldflags-add -lsqlite3
}
teaish-check-librt
user-notice "Forcing requirement of $lfl for $featureName"
}
define LDFLAGS_MATH $lfl
- teaish-prepend-ldflags $lfl
+ teaish-ldflags-prepend $lfl
}
}
if {[lsearch [get-define TARGET_DEBUG ""] -DSQLITE_DEBUG=1] > -1} {
msg-result "Note: this is a debug build, so performance will suffer."
}
- teaish-add-cflags -define OPT_FEATURE_FLAGS
+ teaish-cflags-add -define OPT_FEATURE_FLAGS
}; # sqlite-handle-common-feature-flags
########################################################################
incr enable
set ldf [get-define lib_pthread_create]
define LDFLAGS_PTHREAD $ldf
- teaish-prepend-ldflags $ldf
+ teaish-ldflags-prepend $ldf
undefine lib_pthread_create
undefine lib_pthread_mutexattr_init
} elseif {[proj-opt-was-provided threadsafe]} {
if {$found} {
set ldf [get-define lib_dlopen]
define LDFLAGS_DLOPEN $ldf
- teaish-prepend-ldflags $ldf
+ teaish-ldflags-prepend $ldf
undefine lib_dlopen
} else {
if {[proj-opt-was-provided load-extension]} {
msg-result "Enabling ICU collations."
sqlite-add-feature-flag -DSQLITE_ENABLE_ICU_COLLATIONS
}
- teaish-prepend-ldflags $ldflags
- teaish-add-cflags $cflags
+ teaish-ldflags-prepend $ldflags
+ teaish-cflags-add $cflags
} elseif {[opt-bool icu-collations]} {
proj-warn "ignoring --enable-icu-collations because neither --with-icu-ldflags nor --with-icu-config provided any linker flags"
} else {
set lfl [get-define lib_ceil]
undefine lib_ceil
define LDFLAGS_MATH $lfl
- teaish-prepend-ldflags $lfl
+ teaish-ldflags-prepend $lfl
sqlite-add-feature-flag -DSQLITE_ENABLE_MATH_FUNCTIONS
msg-result "Enabling math SQL functions"
} {
# ----- @module proj.tcl -----
# @section Project Helper APIs
-########################################################################
+#
# $proj__Config is an internal-use-only array for storing whatever generic
# internal stuff we need stored.
+#
array set proj__Config {
self-tests 0
}
set proj__Config(dot-in-files) [list]
set proj__Config(isatty) [isatty? stdout]
-########################################################################
+#
# @proj-warn msg
#
# Emits a warning message to stderr. All args are appended with a
# space between each.
+#
proc proj-warn {args} {
show-notices
puts stderr [join [list "WARNING:" {*}$args] " "]
}
-########################################################################
-# @proj-error ?-up...? msg
+#
+# @proj-fatal ?-up...? msg...
#
# Emits an error message to stderr and exits with non-0. All args are
# appended with a space between each.
# The calling scope's name is used in the error message. To instead
# use the name of a call higher up in the stack, use -up once for each
# additional level.
+#
proc proj-fatal {args} {
show-notices
set lvl 1
set args [lassign $args -]
incr lvl
}
- puts stderr [join [list "ERROR: \[[proj-current-scope $lvl]]:" {*}$args] " "]
+ puts stderr [join [list "FATAL: \[[proj-current-scope $lvl]]: " {*}$args]]
exit 1
}
-########################################################################
+#
+# @proj-error ?-up...? msg...
+#
+# Works like prop-fatal but uses [error] intead of [exit].
+#
+proc proj-error {args} {
+ show-notices
+ set lvl 1
+ while {"-up" eq [lindex $args 0]} {
+ set args [lassign $args -]
+ incr lvl
+ }
+ error [join [list "\[[proj-current-scope $lvl]]:" {*}$args]]
+}
+
+#
# @proj-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 proj-assert {script {msg ""}} {
if {1 == [get-env proj-assert 0]} {
msg-result [proj-bold "asserting: $script"]
}
}
-########################################################################
+#
# @proj-bold str
#
# If this function believes that the current console might support
# ANSI escape sequences then this returns $str wrapped in a sequence
# to bold that text, else it returns $str as-is.
+#
proc proj-bold {args} {
if {$::autosetup(iswin) || !$::proj__Config(isatty)} {
return [join $args]
return "\033\[1m${args}\033\[0m"
}
-########################################################################
+#
# @proj-indented-notice ?-error? ?-notice? msg
#
# Takes a multi-line message and emits it with consistent indentation.
#
# If neither -notice nor -error are used, the message will be sent to
# stdout without delay.
+#
proc proj-indented-notice {args} {
set fErr ""
set outFunc "puts"
}
}
-########################################################################
+#
# @proj-is-cross-compiling
#
# Returns 1 if cross-compiling, else 0.
+#
proc proj-is-cross-compiling {} {
return [expr {[get-define host] ne [get-define build]}]
}
-########################################################################
+#
# @proj-strip-hash-comments value
#
# Expects to receive string input, which it splits on newlines, strips
# a '#', and returns a value containing the [append]ed results of each
# remaining line with a \n between each. It does not strip out
# comments which appear after the first non-whitespace character.
+#
proc proj-strip-hash-comments {val} {
set x {}
foreach line [split $val \n] {
return $x
}
-########################################################################
+#
# @proj-cflags-without-werror
#
# Fetches [define $var], strips out any -Werror entries, and returns
# the new value. This is intended for temporarily stripping -Werror
# from CFLAGS or CPPFLAGS within the scope of a [define-push] block.
+#
proc proj-cflags-without-werror {{var CFLAGS}} {
set rv {}
foreach f [get-define $var ""] {
return [join $rv " "]
}
-########################################################################
+#
# @proj-check-function-in-lib
#
# A proxy for cc-check-function-in-lib with the following differences:
# Returns the result of cc-check-function-in-lib (i.e. true or false).
# The resulting linker flags are stored in the [define] named
# lib_${function}.
+#
proc proj-check-function-in-lib {function libs {otherlibs {}}} {
set found 0
define-push {LIBS CFLAGS} {
return $found
}
-########################################################################
+#
# @proj-search-for-header-dir ?-dirs LIST? ?-subdirs LIST? header
#
# Searches for $header in a combination of dirs and subdirs, specified
# by the -dirs {LIST} and -subdirs {LIST} flags (each of which have
# sane defaults). Returns either the first matching dir or an empty
# string. The return value does not contain the filename part.
+#
proc proj-search-for-header-dir {header args} {
set subdirs {include}
set dirs {/usr /usr/local /mingw}
return ""
}
-########################################################################
+#
# @proj-find-executable-path ?-v? binaryName
#
# Works similarly to autosetup's [find-executable-path $binName] but:
# - If the first arg is -v, it's verbose about searching, else it's quiet.
#
# Returns the full path to the result or an empty string.
+#
proc proj-find-executable-path {args} {
set binName $args
set verbose 0
return $check
}
-########################################################################
+#
# @proj-bin-define binName ?defName?
#
# Uses [proj-find-executable-path $binName] to (verbosely) search for
# The define'd name is: If $defName is not empty, it is used as-is. If
# $defName is empty then "BIN_X" is used, where X is the upper-case
# form of $binName with any '-' characters replaced with '_'.
+#
proc proj-bin-define {binName {defName {}}} {
set check [proj-find-executable-path -v $binName]
if {"" eq $defName} {
return $check
}
-########################################################################
+#
# @proj-first-bin-of bin...
#
# Looks for the first binary found of the names passed to this
# any define'd name that function stores for the result (because the
# caller has no sensible way of knowing which result it was unless
# they pass only a single argument).
+#
proc proj-first-bin-of {args} {
set rc ""
foreach b $args {
return $rc
}
-########################################################################
+#
# @proj-opt-was-provided key
#
# Returns 1 if the user specifically provided the given configure flag
# that new options set via that function will cause this function to
# return true. (That's an unintended and unavoidable side-effect, not
# specifically a feature which should be made use of.)
+#
proc proj-opt-was-provided {key} {
dict exists $::autosetup(optset) $key
}
-########################################################################
+#
# @proj-opt-set flag ?val?
#
# Force-set autosetup option $flag to $val. The value can be fetched
# later with [opt-val], [opt-bool], and friends.
#
# Returns $val.
+#
proc proj-opt-set {flag {val 1}} {
if {$flag ni $::autosetup(options)} {
# We have to add this to autosetup(options) or else future calls
return $val
}
-########################################################################
+#
# @proj-opt-exists flag
#
# Returns 1 if the given flag has been defined as a legal configure
# option, else returns 0.
+#
proc proj-opt-exists {flag} {
expr {$flag in $::autosetup(options)};
}
-########################################################################
+#
# @proj-val-truthy val
#
# Returns 1 if $val appears to be a truthy value, else returns
# 0. Truthy values are any of {1 on true yes enabled}
+#
proc proj-val-truthy {val} {
expr {$val in {1 on true yes enabled}}
}
-########################################################################
+#
# @proj-opt-truthy flag
#
# Returns 1 if [opt-val $flag] appears to be a truthy value or
# [opt-bool $flag] is true. See proj-val-truthy.
+#
proc proj-opt-truthy {flag} {
if {[proj-val-truthy [opt-val $flag]]} { return 1 }
set rc 0
return $rc
}
-########################################################################
+#
# @proj-if-opt-truthy boolFlag thenScript ?elseScript?
#
# If [proj-opt-truthy $flag] is true, eval $then, else eval $else.
+#
proc proj-if-opt-truthy {boolFlag thenScript {elseScript {}}} {
if {[proj-opt-truthy $boolFlag]} {
uplevel 1 $thenScript
}
}
-########################################################################
+#
# @proj-define-for-opt flag def ?msg? ?iftrue? ?iffalse?
#
# If [proj-opt-truthy $flag] then [define $def $iftrue] else [define
# $def $iffalse]. If $msg is not empty, output [msg-checking $msg] and
# a [msg-results ...] which corresponds to the result. Returns 1 if
# the opt-truthy check passes, else 0.
+#
proc proj-define-for-opt {flag def {msg ""} {iftrue 1} {iffalse 0}} {
if {"" ne $msg} {
msg-checking "$msg "
return $rc
}
-########################################################################
+#
# @proj-opt-define-bool ?-v? optName defName ?descr?
#
# Checks [proj-opt-truthy $optName] and calls [define $defName X]
# If args[0] is -v then the boolean semantics are inverted: if
# the option is set, it gets define'd to 0, else 1. Returns the
# define'd value.
+#
proc proj-opt-define-bool {args} {
set invert 0
if {[lindex $args 0] eq "-v"} {
return $rc
}
-########################################################################
+#
# @proj-check-module-loader
#
# Check for module-loading APIs (libdl/libltdl)...
#
# Note that if it finds LIBLTDL it does not look for LIBDL, so will
# report only that is has LIBLTDL.
+#
proc proj-check-module-loader {} {
msg-checking "Looking for module-loader APIs... "
if {99 ne [get-define LDFLAGS_MODULE_LOADER 99]} {
return $rc
}
-########################################################################
+#
# @proj-no-check-module-loader
#
# Sets all flags which would be set by proj-check-module-loader to
# empty/falsy values, as if those checks had failed to find a module
# loader. Intended to be called in place of that function when
# a module loader is explicitly not desired.
+#
proc proj-no-check-module-loader {} {
define HAVE_LIBDL 0
define HAVE_LIBLTDL 0
define LDFLAGS_MODULE_LOADER ""
}
-########################################################################
+#
# @proj-file-conent ?-trim? filename
#
# Opens the given file, reads all of its content, and returns it. If
# the first arg is -trim, the contents of the file named by the second
# argument are trimmed before returning them.
+#
proc proj-file-content {args} {
set trim 0
set fname $args
return $rc
}
-########################################################################
+#
# @proj-file-conent filename
#
# Returns the contents of the given file as an array of lines, with
# the EOL stripped from each input line.
+#
proc proj-file-content-list {fname} {
set fp [open $fname rb]
set rc {}
return $rc
}
-########################################################################
+#
# @proj-file-write ?-ro? fname content
#
# Works like autosetup's [writefile] but explicitly uses binary mode
# to avoid EOL translation on Windows. If $fname already exists, it is
# overwritten, even if it's flagged as read-only.
+#
proc proj-file-write {args} {
if {"-ro" eq [lindex $args 0]} {
lassign $args ro fname content
}
}
-########################################################################
+#
# @proj-check-compile-commands ?configFlag?
#
# Checks the compiler for compile_commands.json support. If passed an
#
# ACHTUNG: this test has a long history of false positive results
# because of compilers reacting differently to the -MJ flag.
+#
proc proj-check-compile-commands {{configFlag {}}} {
msg-checking "compile_commands.json support... "
if {"" ne $configFlag && ![proj-opt-truthy $configFlag]} {
}
}
-########################################################################
+#
# @proj-touch filename
#
# Runs the 'touch' external command on one or more files, ignoring any
# errors.
+#
proc proj-touch {filename} {
catch { exec touch {*}$filename }
}
-########################################################################
+#
# @proj-make-from-dot-in ?-touch? infile ?outfile?
#
# Uses [make-template] to create makefile(-like) file(s) $outfile from
# please the build process.
#
# Failures when running chmod or touch are silently ignored.
+#
proc proj-make-from-dot-in {args} {
set fIn ""
set fOut ""
}
}
-########################################################################
+#
# @proj-check-profile-flag ?flagname?
#
# Checks for the boolean configure option named by $flagname. If set,
# order to avoid potential problems with escaping, space-containing
# tokens, and interfering with autosetup's use of these vars, this
# routine does not directly modify CFLAGS or LDFLAGS.
+#
proc proj-check-profile-flag {{flagname profile}} {
#puts "flagname=$flagname ?[proj-opt-truthy $flagname]?"
if {[proj-opt-truthy $flagname]} {
return 0
}
-########################################################################
+#
# @proj-looks-like-windows ?key?
#
# Returns 1 if this appears to be a Windows environment (MinGw,
# machine, i.e. the local host). If $key == "build" then some
# additional checks may be performed which are not applicable when
# $key == "host".
+#
proc proj-looks-like-windows {{key host}} {
global autosetup
switch -glob -- [get-define $key] {
return 0
}
-########################################################################
+#
# @proj-looks-like-mac ?key?
#
# Looks at either the 'host' (==compilation target platform) or
# 'build' (==the being-built-on platform) define value and returns if
# if that value seems to indicate that it represents a Mac platform,
# else returns 0.
+#
proc proj-looks-like-mac {{key host}} {
switch -glob -- [get-define $key] {
*apple* {
}
}
-########################################################################
+#
# @proj-exe-extension
#
# Checks autosetup's "host" and "build" defines to see if the build
# build environment is then BUILD_EXEEXT is [define]'d to ".exe", else
# "". If the target, a.k.a. "host", is then TARGET_EXEEXT is
# [define]'d to ".exe", else "".
+#
proc proj-exe-extension {} {
set rH ""
set rB ""
define TARGET_EXEEXT $rH
}
-########################################################################
+#
# @proj-dll-extension
#
# Works like proj-exe-extension except that it defines BUILD_DLLEXT
#
# Trivia: for .dylib files, the linker needs the -dynamiclib flag
# instead of -shared.
+#
proc proj-dll-extension {} {
set inner {{key} {
switch -glob -- [get-define $key] {
define TARGET_DLLEXT [apply $inner host]
}
-########################################################################
+#
# @proj-lib-extension
#
# Static-library counterpart of proj-dll-extension. Defines
# BUILD_LIBEXT and TARGET_LIBEXT to the conventional static library
# extension for the being-built-on resp. the target platform.
+#
proc proj-lib-extension {} {
set inner {{key} {
switch -glob -- [get-define $key] {
define TARGET_LIBEXT [apply $inner host]
}
-########################################################################
+#
# @proj-file-extensions
#
# Calls all of the proj-*-extension functions.
+#
proc proj-file-extensions {} {
proj-exe-extension
proj-dll-extension
proj-lib-extension
}
-########################################################################
+#
# @proj-affirm-files-exist ?-v? filename...
#
# Expects a list of file names. If any one of them does not exist in
# the filesystem, it fails fatally with an informative message.
# Returns the last file name it checks. If the first argument is -v
# then it emits msg-checking/msg-result messages for each file.
+#
proc proj-affirm-files-exist {args} {
set rc ""
set verbose 0
return rc
}
-########################################################################
+#
# @proj-check-emsdk
#
# Emscripten is used for doing in-tree builds of web-based WASM stuff,
# but BIN_EMCC is then emcc was not found in the EMSDK_HOME, in which
# case we have to rely on the fact that sourcing $EMSDK_ENV_SH from a
# shell will add emcc to the $PATH.
+#
proc proj-check-emsdk {} {
set emsdkHome [opt-val with-emsdk]
define EMSDK_HOME ""
return $rc
}
-########################################################################
+#
# @proj-cc-check-Wl-flag ?flag ?args??
#
# Checks whether the given linker flag (and optional arguments) can be
#
# If so, that flag string is returned, else an empty string is
# returned.
+#
proc proj-cc-check-Wl-flag {args} {
cc-with {-link 1} {
# Try -Wl,flag,...args
}
}
-########################################################################
+#
# @proj-check-rpath
#
# Tries various approaches to handling the -rpath link-time
# --exec-prefix=... or --libdir=... are explicitly passed to
# configure then [get-define libdir] is used (noting that it derives
# from exec-prefix by default).
+#
proc proj-check-rpath {} {
if {[proj-opt-was-provided libdir]
|| [proj-opt-was-provided exec-prefix]} {
expr {"" ne [get-define LDFLAGS_RPATH]}
}
-########################################################################
+#
# @proj-check-soname ?libname?
#
# Checks whether CC supports the -Wl,soname,lib... flag. If so, it
# LDFLAGS_SONAME_PREFIX. It is provided so that clients may
# potentially avoid some end-user confusion by using their own lib's
# name here (which shows up in the "checking..." output).
+#
proc proj-check-soname {{libname "libfoo.so.0"}} {
cc-with {-link 1} {
if {[cc-check-flags "-Wl,-soname,${libname}"]} {
}
}
-########################################################################
+#
# @proj-check-fsanitize ?list-of-opts?
#
# Checks whether CC supports -fsanitize=X, where X is each entry of
#
# Will, on many systems, resolve to "-fsanitize=address,bounds-check",
# but may also resolve to "-fsanitize=address".
+#
proc proj-check-fsanitize {{opts {address bounds-strict}}} {
set sup {}
foreach opt $opts {
return ""
}
-########################################################################
+#
# Internal helper for proj-dump-defs-json. Expects to be passed a
# [define] name and the variadic $args which are passed to
# proj-dump-defs-json. 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 proj-defs-type_ {name spec} {
foreach {type patterns} $spec {
foreach pattern $patterns {
return ""
}
-########################################################################
+#
# Internal helper for proj-defs-format_: returns a JSON-ish quoted
# form of the given string-type values. It only performs the most
# basic of escaping. The input must not contain any control
# characters.
+#
proc proj-quote-str_ {value} {
return \"[string map [list \\ \\\\ \" \\\"] $value]\"
}
-########################################################################
+#
# An internal impl detail of proj-dump-defs-json. Requires a data
# type specifier, as used by make-config-header, and a value. Returns
# the formatted value or the value $::proj__Config(defs-skip) if the caller
# should skip emitting that value.
+#
set proj__Config(defs-skip) "-proj-defs-format_ sentinel"
proc proj-defs-format_ {type value} {
switch -exact -- $type {
return $value
}
-########################################################################
+#
# This function works almost identically to autosetup's
# make-config-header but emits its output in JSON form. It is not a
# fully-functional JSON emitter, and will emit broken JSON for
# Neither is especially satisfactory (and the second is useless), and
# handling of such values is subject to change if any such values ever
# _really_ need to be processed by our source trees.
+#
proc proj-dump-defs-json {file args} {
file mkdir [file dirname $file]
set lines {}
}
}
-########################################################################
+#
# @proj-xfer-option-aliases map
#
# Expects a list of pairs of configure flags which have been
# requires that the caller know all possible aliases. It's simpler, in
# terms of options handling, if there's only a single canonical name
# which each down-stream call of [opt-...] has to know.
+#
proc proj-xfer-options-aliases {mapping} {
foreach {hidden - canonical} [proj-strip-hash-comments $mapping] {
if {[proj-opt-was-provided $hidden]} {
}
}
-########################################################################
+#
# Arguable/debatable...
#
# When _not_ cross-compiling and CC_FOR_BUILD is _not_ explicitly
# Sidebar: if we do this before the cc package is installed, it gets
# reverted by that package. Ergo, the cc package init will tell the
# user "Build C compiler...cc" shortly before we tell them otherwise.
+#
proc proj-redefine-cc-for-build {} {
if {![proj-is-cross-compiling]
&& [get-define CC] ne [get-define CC_FOR_BUILD]
}
}
-########################################################################
+#
# @proj-which-linenoise headerFile
#
# Attempts to determine whether the given linenoise header file is of
# the "antirez" or "msteveb" flavor. It returns 2 for msteveb, else 1
# (it does not validate that the header otherwise contains the
# linenoise API).
+#
proc proj-which-linenoise {dotH} {
set srcHeader [proj-file-content $dotH]
if {[string match *userdata* $srcHeader]} {
}
}
-########################################################################
+#
# @proj-remap-autoconf-dir-vars
#
# "Re-map" the autoconf-conventional --XYZdir flags into something
# post-processing, libdir would be cemented in as FOO/lib at
# configure-time, so could be tedious to override properly via a make
# invocation.
+#
proc proj-remap-autoconf-dir-vars {} {
set prefix [get-define prefix]
set exec_prefix [get-define exec_prefix $prefix]
}
}
-########################################################################
+#
# @proj-env-file flag ?default?
#
# If a file named .env-$flag exists, this function returns a
# trimmed copy of its contents, else it returns $dflt. The intended
# usage is that things like developer-specific CFLAGS preferences can
# be stored in .env-CFLAGS.
+#
proc proj-env-file {flag {dflt ""}} {
set fn ".env-${flag}"
if {[file readable $fn]} {
return $dflt
}
-########################################################################
+#
# @proj-get-env var ?default?
#
# Extracts the value of "environment" variable $var from the first of
# - A file named .env-$var (see [proj-env-file])
#
# If none of those are set, $dflt is returned.
+#
proc proj-get-env {var {dflt ""}} {
return [get-env $var [proj-env-file $var $dflt]]
}
-########################################################################
+#
# @proj-current-scope ?lvl?
#
# Returns the name of the _calling_ proc from ($lvl + 1) levels up the
# 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 proj-current-scope {{lvl 0}} {
#uplevel [expr {$lvl + 1}] {lindex [info level 0] 0}
set ilvl [info level]
}
-########################################################################
+#
# Converts parts of tclConfig.sh to autosetup [define]s.
#
# Expects to be passed the name of a value tclConfig.sh or an empty
# string. It converts certain parts of that file's contents to
# [define]s (see the code for the whole list). If $tclConfigSh is an
# empty string then it [define]s the various vars as empty strings.
+#
proc proj-tclConfig-sh-to-autosetup {tclConfigSh} {
set shBody {}
set tclVars {
}
}
-########################################################################
+#
# @proj-tweak-default-env-dirs
#
# This function is not useful before [use system] is called to set up
# Similar modifications may be made for --mandir.
#
# Returns 1 if it modifies the environment, else 0.
+#
proc proj-tweak-default-env-dirs {} {
set rc 0
switch -glob -- [get-define host] {
return $rc
}
-########################################################################
+#
# @proj-dot-ins-append file ?fileOut ?postProcessScript??
#
# Queues up an autosetup [make-template]-style file to be processed
# executable or perform validation on its contents.
#
# See [proj-dot-ins-process], [proj-dot-ins-list]
+#
proc proj-dot-ins-append {fileIn args} {
set srcdir $::autosetup(srcdir)
switch -exact -- [llength $args] {
lappend ::proj__Config(dot-in-files) $fileIn
}
-########################################################################
+#
# @proj-dot-ins-list
#
# Returns the current list of [proj-dot-ins-append]'d files, noting
# that each entry is a 3-element list of (inputFileName,
# outputFileName, postProcessScript).
+#
proc proj-dot-ins-list {} {
return $::proj__Config(dot-in-files)
}
-########################################################################
+#
# @proj-dot-ins-process ?-touch? ?-validate? ?-clear?
#
# Each file which has previously been passed to [proj-dot-ins-append]
#
# -clear: after processing, empty the dot-ins list. This effectively
# makes proj-dot-ins-append available for re-use.
+#
proc proj-dot-ins-process {args} {
proj-parse-simple-flags args flags {
-touch "" {return "-touch"}
}
}
-########################################################################
+#
# @proj-validate-no-unresolved-ats filenames...
#
# For each filename given to it, it validates that the file has no
# validation to fail, as it's sometimes convenient to comment out
# sections during development of a configure script and its
# corresponding makefile(s).
+#
proc proj-validate-no-unresolved-ats {args} {
foreach f $args {
set lnno 1
}
}
-########################################################################
+#
# @proj-first-found fileList tgtVar
#
# 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
# and 0 is returned.
+#
proc proj-first-file-found {fileList tgtVar} {
upvar $tgtVar tgt
foreach f $fileList {
return 0
}
-########################################################################
+#
# Defines $defName to contain makefile recipe commands for re-running
# the configure script with its current set of $::argv flags. This
# can be used to automatically reconfigure.
+#
proc proj-setup-autoreconfig {defName} {
set squote {{arg} {
# Wrap $arg in single-quotes if it looks like it might need that
}
}
-########################################################################
+#
# @prop-append-to defineName args...
#
# A proxy for Autosetup's [define-append]. Appends all non-empty $args
# to [define-append $defineName].
+#
proc proj-define-append {defineName args} {
foreach a $args {
if {"" ne $a} {
}
}
-########################################################################
+#
# @prod-define-amend ?-p|-prepend? ?-define? FLAG args...
#
# A proxy for Autosetup's [define-append].
# technically correct and still relevant on some environments.
#
# See: proj-append-to
+#
proc proj-define-amend {args} {
set defName ""
set prepend 0
}
}
+#
# @proj-define-to-cflag ?-list? defineName...
#
# Treat each argument as the name of a [define]
# By default it returns the result as string of all -D... flags,
# but if passed the -list flag it will return a list of the
# individual CFLAGS.
+#
proc proj-define-to-cflag {args} {
set rv {}
set xargs {}
# Internal cache for use via proj-cache-*.
array set proj__Cache {}
+#
# @proj-cache-key ?addLevel? arg
#
# Helper to generate cache keys for [proj-cache-*].
return $arg
}
+#
# @proj-cache-set ?key? ?addLevel? value
#
# Sets a feature-check cache entry with the given key.
set ::proj__Cache($key) $val
}
+#
# @proj-cache-remove ?key? ?addLevel?
#
# Removes an entry from the proj-cache.
return $rv;
}
+#
# @proj-cache-check ?$key? ?addLevel? tgtVarName
#
# Checks for a feature-check cache entry with the given key.
return $rc
}
+#
# @proj-coalesce ...args
#
# Returns the first argument which is not empty (eq ""), or an empty
return ""
}
+#
# @proj-parse-simple-flags ...
#
# An experiment. Do not use.
set rv {}
set skipMode 0
set n [llength $argv]
- for {set i 0} {$i < $n} {} {
+ for {set i 0} {$i < $n} {incr i} {
set arg [lindex $argv $i]
if {$skipMode} {
lappend rv $arg
set tgt($arg) ""
} else {
#puts "**** running scripts($arg) $scripts($arg)"
- set code [catch {uplevel 1 $scripts($arg)} rc xopt]
+ set code [catch {uplevel 1 $scripts($arg)} xrc xopt]
#puts "**** tgt($arg)=$scripts($arg) code=$code rc=$rc"
if {$code in {0 2}} {
- set tgt($arg) $rc
+ set tgt($arg) $xrc
} else {
- return {*}$xopt $rc
+ return {*}$xopt $xrc
}
}
incr rc
incr skipMode
lappend rv $arg
}
- incr i
}
set argv $rv
return $rc
-C When\slogging\serrors\susing\ssqlite3_log()\sand\sthe\serror\stext\sincludes\sthe\ntext\sof\san\sSQL\sstatement,\sbut\sthe\sSQL\sstatement\stext\sat\sthe\send\sso\sthat\sif\nthe\serror\smessage\sbuffer\soverflows\sit\sis\sthe\sSQL\sstatement\stext\sthat\sgets\ntruncated,\snot\sthe\sstatement\sof\sthe\sproblem.
-D 2025-04-17T19:01:54.977
+C Upstream\steaish,\swhich\ssimplifies\show\sextension\smetadata\sare\sinitialized\sand\sshrinks\sproj.tcl\sby\s4k.
+D 2025-04-17T19:41:37.075
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d64849094c1fd136
F autoconf/README.txt b749816b8452b3af994dc6d607394bef3df1736d7e09359f1087de8439a52807
F autoconf/auto.def 3d994f3a9cc9b712dbce92a5708570ddcf3b988141b6eb738f2ed16127a9f0ac
-F autoconf/tea/Makefile.in 2f716371a21f2d2ad1244c932f9ba12c083c9b4bd066590a51cb20c08f8b7ca6
+F autoconf/tea/Makefile.in 41159d167c3b1a9bab7253f268d1ad1dc71ab8a9a6ccc9744a313aba40249a6a
F autoconf/tea/README.txt 656d4686c509d375f5988ff3deda94f65fe6cd8358cd55d1f1dcc7b6e2ff73aa
F autoconf/tea/auto.def 81e2617cfb90d53c19b53b3ec632cd2893bf32f2e5dd272b1116fadf2ea86c2d
F autoconf/tea/autosetup/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
-F autoconf/tea/autosetup/core.tcl 94b4f452606f75249aba667e4a4a577112a181112c24201856c8dbef8424f134
-F autoconf/tea/autosetup/feature-tests.tcl 3ccf2fd1cad368c7ed958a869d8b915fada7f164a6b382c7381540c4892476f8
-F autoconf/tea/autosetup/tester.tcl 610b158c12112bfcbfe3a0eb18cacaccd914241a37a7a38a7fdd73822b7b3cab
+F autoconf/tea/autosetup/core.tcl dea4684df6c5765a8fa866b4a6d79c73ba413ad37bb7c70e1be3631cd9eb2831
+F autoconf/tea/autosetup/feature-tests.tcl 307cac35806817fc87bd0d92004364ee682c0e99f2ab505291500493ab6c7a5f
+F autoconf/tea/autosetup/tester.tcl a201ef9e91dde182e73015d09f94a3c40dd534ce38642167ebfd5884801d1e5a
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 dc80c325c47095f278c7b4cf0784382fa0048cde44836bbd778aea0c7e23ed1a
-F autoconf/tea/teaish.tcl ee22d09a97dfcf77762942aea5b1b838a284a4a36b124064f1209e241bef6e7e
+F autoconf/tea/pkgIndex.tcl.in a41b98633e184703136914e588638423047eae71244a30061ccd8edf92498436
+F autoconf/tea/teaish.tcl 2bc7ca287baa076daca513ff9342c00f499b1cceb8302a93d4a6231b00b52504
F autoconf/tea/teaish.test.tcl cfe94e1fb79dd078f650295be59843d470125e0cc3a17a1414c1fb8d77f4aea6
F autoconf/tea/teaish.tester.tcl.in 63059e35289ac663c7d0052e6c0089a309fee75225e86e4ec5b3d9f2c1d9290a
F autosetup/LICENSE 41a26aebdd2cd185d1e2b210f71b7ce234496979f6b35aef2cbf6b80cbed4ce4
F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1821baf61bc86a7e
F autosetup/jimsh0.c a57c16e65dcffc9c76e496757cb3f7fb47e01ecbd1631a0a5e01751fc856f049
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
-F autosetup/proj.tcl 5d214dd3e9ffc7cf8dfda0b2f047c76316bbe70ad5bb0d715fee75c8676daeea
+F autosetup/proj.tcl 11e46ff237ca96d07fd14fe96132f8e77fee6442d8baa2e808bbe95016583c56
F autosetup/sqlite-config.tcl bde169c42d5d5331485ae7785f5dd19ca1aa01315787e8306441c472ad4e4201
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P a64e8491c9863f890daa9f5d8f678728dc0d00bc1f3c238b50214ec545450fcf
-R c7314e61baa174725a2a70881e7614ea
-U drh
-Z 6a2f3e45e3ea371afd4913a2a62a4053
+P de0968226effb79f9d25539da7882fa5475e4ff2410870b45a63a6545deb5979
+R ea2362589cd7cb111ab49baa9c4d20ad
+U stephan
+Z c20158b68dfe96121ce3497954c5dd64
# Remove this line to create a well-formed Fossil manifest.
-de0968226effb79f9d25539da7882fa5475e4ff2410870b45a63a6545deb5979
+c72c00d34d70b36f847af19a2382299746448b5dd94a616f6b567389c5694c17