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