From: stephan Date: Thu, 17 Apr 2025 19:41:37 +0000 (+0000) Subject: Upstream teaish, which simplifies how extension metadata are initialized and shrinks... X-Git-Tag: major-release~77 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=31e08190abee89ec5fa791b29053975416aa1df2;p=thirdparty%2Fsqlite.git Upstream teaish, which simplifies how extension metadata are initialized and shrinks proj.tcl by 4k. FossilOrigin-Name: c72c00d34d70b36f847af19a2382299746448b5dd94a616f6b567389c5694c17 --- diff --git a/autoconf/tea/Makefile.in b/autoconf/tea/Makefile.in index 1eb22984ba..911717bc43 100644 --- a/autoconf/tea/Makefile.in +++ b/autoconf/tea/Makefile.in @@ -97,7 +97,7 @@ TCLLIBDIR = @TCLLIBDIR@ # 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) @@ -107,7 +107,7 @@ 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-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) @@ -120,7 +120,7 @@ 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@ @@ -139,8 +139,8 @@ tx.LDFLAGS = # # 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@ @@ -180,12 +180,6 @@ reconfigure: $(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@ @@ -201,7 +195,7 @@ $(tx.dll): $(tx.src) config.log all: $(tx.dll) tclsh: $(teaish.makefile) config.log - @{ echo "#!/bin/sh"; echo "exec $(TCLSH) \"\$$@\""; } > $@ + @{ echo "#!/bin/sh"; echo 'exec $(TCLSH) "$$@"'; } > $@ @chmod +x $@ @echo "Created $@" @@ -392,15 +386,15 @@ dist: # - 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. @@ -425,7 +419,7 @@ Makefile: @TEAISH_MAKEFILE@ # # 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 diff --git a/autoconf/tea/autosetup/core.tcl b/autoconf/tea/autosetup/core.tcl index 57d9246c7b..4c9aee4d66 100644 --- a/autoconf/tea/autosetup/core.tcl +++ b/autoconf/tea/autosetup/core.tcl @@ -23,14 +23,7 @@ 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. @@ -46,14 +39,51 @@ array set teaish__Config [proj-strip-hash-comments { # # 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]} { @@ -64,60 +94,51 @@ proc teaish__argv_has {args} { 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 @@ -151,10 +172,67 @@ proc teaish-configure-core {} { 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 ""] + if {$isDefOnly && "" 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. @@ -180,8 +258,10 @@ proc teaish-configure-core {} { 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]} { @@ -209,41 +289,15 @@ proc teaish-debug {msg} { # --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 {"" eq [get-define $key ""]} { - #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 {"" eq [get-define $key ""]} { - #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 @@ -260,48 +314,55 @@ proc teaish__configure-phase1 {} { 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 @@ -313,8 +374,8 @@ proc teaish__configure-phase1 {} { 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 @@ -326,7 +387,7 @@ proc teaish__configure-phase1 {} { # 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) @@ -338,14 +399,14 @@ proc teaish__configure-phase1 {} { # 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) @@ -354,12 +415,8 @@ proc teaish__configure-phase1 {} { 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 @@ -444,8 +501,8 @@ 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] - 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 @@ -468,7 +525,7 @@ proc teaish__check_tcl {} { # --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" @@ -477,8 +534,8 @@ proc teaish__check_tcl {} { [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 @@ -502,7 +559,7 @@ proc teaish__check_tcl {} { } } 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 @@ -524,7 +581,7 @@ proc teaish__check_tcl {} { break } } - msg-result "Using tclConfig.sh: $cfg" + teaish__verbose 1 msg-result "Using tclConfig.sh = $cfg" break } define TCL_CONFIG_SH $cfg @@ -561,20 +618,20 @@ proc teaish__check_tcl {} { 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 { @@ -587,15 +644,17 @@ proc teaish__check_tcl {} { # 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 @@ -611,18 +670,18 @@ proc teaish__check_tcl {} { # 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 "" }} @@ -634,7 +693,7 @@ proc teaish__find_extension {} { #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 { @@ -647,11 +706,12 @@ proc teaish__find_extension {} { # 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 @@ -691,7 +751,7 @@ If you are attempting an out-of-tree build, use } } 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 @@ -703,18 +763,17 @@ If you are attempting an out-of-tree build, use } 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, @@ -735,7 +794,7 @@ If you are attempting an out-of-tree build, use 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 "" @@ -754,7 +813,7 @@ If you are attempting an out-of-tree build, use 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 } @@ -838,14 +897,16 @@ If you are attempting an out-of-tree build, use 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 @@ -853,10 +914,11 @@ proc teaish-add-cflags {args} { # 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]. # @@ -865,26 +927,28 @@ proc teaish-define-to-cflag {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 @@ -892,14 +956,14 @@ proc teaish-prepend-ldflags {args} { # 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 {} @@ -914,7 +978,8 @@ proc teaish-add-src {args} { 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 ...]. # @@ -924,18 +989,19 @@ proc teaish-add-src {args} { # 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 @@ -950,7 +1016,7 @@ proc teaish-add-dist {args} { # 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 { @@ -965,6 +1031,7 @@ proc teaish-add-make {args} { define TEAISH_MAKEFILE_CODE $out } +# # @teaish-make-config-header filename # # Invokes autosetup's [make-config-header] and passes it $filename and @@ -985,6 +1052,7 @@ proc teaish-make-config-header {filename} { 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. @@ -994,6 +1062,7 @@ proc teaish-feature-cache-set {{key 0} val} { proj-cache-set $key 1 $val } +# # @teaish-feature-cache-check ?$key? tgtVarName # # Checks for a feature-check cache entry with the given key. @@ -1010,6 +1079,7 @@ proc teaish-feature-cache-check {{key 0} tgtVar} { proj-cache-check $key 1 tgt } +# # @teaish-check-cached@ ?-nostatus? msg script # # A proxy for feature-test impls which handles caching of a feature @@ -1157,7 +1227,7 @@ proc teaish__defs_format {type value} { set value $::teaish__Config(defs-skip) } default { - proj-fatal \ + proj-error \ "Unknown [project-current-scope] -type ($type) called from" \ [proj-current-scope 1] } @@ -1223,15 +1293,15 @@ proc teaish-pragma {args} { 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 } @@ -1250,6 +1320,119 @@ proc teaish-pragma {args} { } } +# +# @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 "" + 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? # @@ -1263,6 +1446,42 @@ proc teaish-enable-dist {{yes 1}} { 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 @@ -1270,7 +1489,7 @@ proc teaish-enable-dist {{yes 1}} { 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] @@ -1295,28 +1514,46 @@ proc teaish__create_extension {dir} { 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 static int diff --git a/autoconf/tea/autosetup/feature-tests.tcl b/autoconf/tea/autosetup/feature-tests.tcl index d6a54dd4d7..9d77092c82 100644 --- a/autoconf/tea/autosetup/feature-tests.tcl +++ b/autoconf/tea/autosetup/feature-tests.tcl @@ -27,7 +27,7 @@ proc teaish-check-libz {} { teaish-check-cached "Checking for libz" { set rc 0 if {[msg-quiet cc-check-includes zlib.h] && [msg-quiet proj-check-function-in-lib deflate z]} { - teaish-prepend-ldflags [define LDFLAGS_LIBZ [get-define lib_deflate]] + teaish-ldflags-prepend [define LDFLAGS_LIBZ [get-define lib_deflate]] undefine lib_deflate incr rc } @@ -38,7 +38,7 @@ proc teaish-check-libz {} { # @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. # @@ -52,7 +52,7 @@ proc teaish-check-librt {{funclist {fdatasync nanosleep}}} { 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 { @@ -95,7 +95,7 @@ proc teaish-is-mingw {} { # 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()" { @@ -117,7 +117,7 @@ proc teaish-check-dlopen {} { } else { msg-result "not found" } - teaish-prepend-ldflags [define LDFLAGS_DLOPEN $lfl] + teaish-ldflags-prepend [define LDFLAGS_DLOPEN $lfl] define HAVE_DLOPEN $rc } } @@ -135,7 +135,7 @@ proc teaish-check-libmath {} { 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 @@ -143,7 +143,7 @@ proc teaish-check-libmath {} { } } -# @teaish-import-features ?-no-options? feature-names... +# @teaish-import-features ?-flags? feature-names... # # For each $name in feature-names... it invokes: # @@ -155,32 +155,60 @@ proc teaish-check-libmath {} { # 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 + } + } } } diff --git a/autoconf/tea/autosetup/tester.tcl b/autoconf/tea/autosetup/tester.tcl index d48d7af44a..199f64dafb 100644 --- a/autoconf/tea/autosetup/tester.tcl +++ b/autoconf/tea/autosetup/tester.tcl @@ -21,7 +21,7 @@ # 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 @@ -52,23 +52,27 @@ proc test-msg {args} { # @test-warn # # Emits all arugments to stderr. +# proc test-warn {args} { puts stderr "WARNING: $args" } -######################################################################## +# # @test-error msg # # Triggers a test-failed error with a string describing the calling # scope and the provided message. +# proc test-fail {args} { #puts stderr "ERROR: \[[test-current-scope 1]]: $msg" #exit 1 error "FAIL: \[[test-current-scope 1]]: $args" } +# # Internal impl for assert-likes. Should not be called directly by # client code. +# proc test__assert {lvl script {msg ""}} { set src "expr \{ $script \}" # puts "XXXX evalling $src"; @@ -83,42 +87,46 @@ proc test__assert {lvl script {msg ""}} { } } -######################################################################## +# # @assert script ?message? # # Kind of like a C assert: if uplevel (eval) of [expr {$script}] is # false, a fatal error is triggered. The error message, by default, # includes the body of the failed assertion, but if $msg is set then # that is used instead. +# proc assert {script {msg ""}} { test__assert 1 $script $msg } -######################################################################## +# # @test-assert testId script ?msg? # # Works like [assert] but emits $testId to stdout first. +# proc test-assert {testId script {msg ""}} { puts "test $testId" test__assert 2 $script $msg } -######################################################################## +# # @test-expect testId script result # # Runs $script in the calling scope and compares its result to # $result. 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 @@ -133,6 +141,7 @@ if {![array exists ::teaish__BuildFlags]} { array set ::teaish__BuildFlags {} } +# # @teaish-build-flag2 flag tgtVar ?dflt? # # Caveat #1: only valid when called in the context of teaish's default @@ -165,11 +174,13 @@ proc teaish-build-flag2 {flag tgtVar {dflt ""}} { 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 diff --git a/autoconf/tea/pkgIndex.tcl.in b/autoconf/tea/pkgIndex.tcl.in index 93fbe0ead1..6ed6bb68db 100644 --- a/autoconf/tea/pkgIndex.tcl.in +++ b/autoconf/tea/pkgIndex.tcl.in @@ -12,24 +12,24 @@ if {![package vsatisfies [package provide Tcl] @TEAISH_VSATISFIES_TCL@]} { } @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 } diff --git a/autoconf/tea/teaish.tcl b/autoconf/tea/teaish.tcl index 7d8490edf8..eedd9bdaf4 100644 --- a/autoconf/tea/teaish.tcl +++ b/autoconf/tea/teaish.tcl @@ -1,13 +1,16 @@ # 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 @@ -70,14 +73,14 @@ proc teaish-configure {} { 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." } @@ -98,8 +101,8 @@ proc teaish-configure {} { 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 @@ -141,7 +144,7 @@ proc sqlite-affirm-have-math {featureName} { user-notice "Forcing requirement of $lfl for $featureName" } define LDFLAGS_MATH $lfl - teaish-prepend-ldflags $lfl + teaish-ldflags-prepend $lfl } } @@ -230,7 +233,7 @@ proc sqlite-handle-common-feature-flags {} { 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 ######################################################################## @@ -252,7 +255,7 @@ proc sqlite-handle-threadsafe {} { 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]} { @@ -314,7 +317,7 @@ proc sqlite-handle-load-extension {} { 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]} { @@ -433,8 +436,8 @@ proc sqlite-handle-icu {} { 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 { @@ -478,7 +481,7 @@ proc sqlite-handle-math {} { 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" } { diff --git a/autosetup/proj.tcl b/autosetup/proj.tcl index d4fcdc590f..2e272a3b52 100644 --- a/autosetup/proj.tcl +++ b/autosetup/proj.tcl @@ -54,9 +54,10 @@ # ----- @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 } @@ -74,18 +75,19 @@ array set proj__Config { 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. @@ -93,6 +95,7 @@ proc proj-warn {args} { # 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 @@ -100,17 +103,33 @@ proc proj-fatal {args} { 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"] @@ -124,12 +143,13 @@ proc proj-assert {script {msg ""}} { } } -######################################################################## +# # @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] @@ -137,7 +157,7 @@ proc proj-bold {args} { return "\033\[1m${args}\033\[0m" } -######################################################################## +# # @proj-indented-notice ?-error? ?-notice? msg # # Takes a multi-line message and emits it with consistent indentation. @@ -152,6 +172,7 @@ proc proj-bold {args} { # # 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" @@ -185,15 +206,16 @@ proc proj-indented-notice {args} { } } -######################################################################## +# # @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 @@ -201,6 +223,7 @@ proc proj-is-cross-compiling {} { # 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] { @@ -211,12 +234,13 @@ proc proj-strip-hash-comments {val} { 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 ""] { @@ -228,7 +252,7 @@ proc proj-cflags-without-werror {{var CFLAGS}} { return [join $rv " "] } -######################################################################## +# # @proj-check-function-in-lib # # A proxy for cc-check-function-in-lib with the following differences: @@ -241,6 +265,7 @@ proc proj-cflags-without-werror {{var CFLAGS}} { # 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} { @@ -252,13 +277,14 @@ proc proj-check-function-in-lib {function libs {otherlibs {}}} { 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} @@ -285,7 +311,7 @@ proc proj-search-for-header-dir {header args} { return "" } -######################################################################## +# # @proj-find-executable-path ?-v? binaryName # # Works similarly to autosetup's [find-executable-path $binName] but: @@ -293,6 +319,7 @@ proc proj-search-for-header-dir {header args} { # - 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 @@ -312,7 +339,7 @@ proc proj-find-executable-path {args} { return $check } -######################################################################## +# # @proj-bin-define binName ?defName? # # Uses [proj-find-executable-path $binName] to (verbosely) search for @@ -322,6 +349,7 @@ proc proj-find-executable-path {args} { # 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} { @@ -331,7 +359,7 @@ proc proj-bin-define {binName {defName {}}} { return $check } -######################################################################## +# # @proj-first-bin-of bin... # # Looks for the first binary found of the names passed to this @@ -342,6 +370,7 @@ proc proj-bin-define {binName {defName {}}} { # 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 { @@ -356,7 +385,7 @@ proc proj-first-bin-of {args} { return $rc } -######################################################################## +# # @proj-opt-was-provided key # # Returns 1 if the user specifically provided the given configure flag @@ -384,17 +413,19 @@ proc proj-first-bin-of {args} { # 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 @@ -405,29 +436,32 @@ proc proj-opt-set {flag {val 1}} { 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 @@ -438,10 +472,11 @@ proc proj-opt-truthy {flag} { 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 @@ -450,13 +485,14 @@ proc proj-if-opt-truthy {boolFlag thenScript {elseScript {}}} { } } -######################################################################## +# # @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 " @@ -479,7 +515,7 @@ proc proj-define-for-opt {flag def {msg ""} {iftrue 1} {iffalse 0}} { return $rc } -######################################################################## +# # @proj-opt-define-bool ?-v? optName defName ?descr? # # Checks [proj-opt-truthy $optName] and calls [define $defName X] @@ -489,6 +525,7 @@ proc proj-define-for-opt {flag def {msg ""} {iftrue 1} {iffalse 0}} { # 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"} { @@ -517,7 +554,7 @@ proc proj-opt-define-bool {args} { return $rc } -######################################################################## +# # @proj-check-module-loader # # Check for module-loading APIs (libdl/libltdl)... @@ -537,6 +574,7 @@ proc proj-opt-define-bool {args} { # # 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]} { @@ -582,25 +620,27 @@ proc proj-check-module-loader {} { 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 @@ -615,11 +655,12 @@ proc proj-file-content {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 {} @@ -630,12 +671,13 @@ proc proj-file-content-list {fname} { 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 @@ -655,7 +697,7 @@ proc proj-file-write {args} { } } -######################################################################## +# # @proj-check-compile-commands ?configFlag? # # Checks the compiler for compile_commands.json support. If passed an @@ -669,6 +711,7 @@ proc proj-file-write {args} { # # 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]} { @@ -693,16 +736,17 @@ proc proj-check-compile-commands {{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 @@ -723,6 +767,7 @@ proc proj-touch {filename} { # please the build process. # # Failures when running chmod or touch are silently ignored. +# proc proj-make-from-dot-in {args} { set fIn "" set fOut "" @@ -755,7 +800,7 @@ proc proj-make-from-dot-in {args} { } } -######################################################################## +# # @proj-check-profile-flag ?flagname? # # Checks for the boolean configure option named by $flagname. If set, @@ -768,6 +813,7 @@ proc proj-make-from-dot-in {args} { # 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]} { @@ -787,7 +833,7 @@ proc proj-check-profile-flag {{flagname profile}} { return 0 } -######################################################################## +# # @proj-looks-like-windows ?key? # # Returns 1 if this appears to be a Windows environment (MinGw, @@ -798,6 +844,7 @@ proc proj-check-profile-flag {{flagname profile}} { # 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] { @@ -816,13 +863,14 @@ proc proj-looks-like-windows {{key host}} { 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* { @@ -834,7 +882,7 @@ proc proj-looks-like-mac {{key host}} { } } -######################################################################## +# # @proj-exe-extension # # Checks autosetup's "host" and "build" defines to see if the build @@ -842,6 +890,7 @@ proc proj-looks-like-mac {{key host}} { # 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 "" @@ -855,7 +904,7 @@ proc proj-exe-extension {} { define TARGET_EXEEXT $rH } -######################################################################## +# # @proj-dll-extension # # Works like proj-exe-extension except that it defines BUILD_DLLEXT @@ -863,6 +912,7 @@ proc proj-exe-extension {} { # # 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] { @@ -881,12 +931,13 @@ proc proj-dll-extension {} { 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] { @@ -904,23 +955,25 @@ proc proj-lib-extension {} { 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 @@ -939,7 +992,7 @@ proc proj-affirm-files-exist {args} { return rc } -######################################################################## +# # @proj-check-emsdk # # Emscripten is used for doing in-tree builds of web-based WASM stuff, @@ -971,6 +1024,7 @@ proc proj-affirm-files-exist {args} { # 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 "" @@ -1008,7 +1062,7 @@ proc proj-check-emsdk {} { return $rc } -######################################################################## +# # @proj-cc-check-Wl-flag ?flag ?args?? # # Checks whether the given linker flag (and optional arguments) can be @@ -1019,6 +1073,7 @@ proc proj-check-emsdk {} { # # 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 @@ -1037,7 +1092,7 @@ proc proj-cc-check-Wl-flag {args} { } } -######################################################################## +# # @proj-check-rpath # # Tries various approaches to handling the -rpath link-time @@ -1048,6 +1103,7 @@ proc proj-cc-check-Wl-flag {args} { # --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]} { @@ -1073,7 +1129,7 @@ proc proj-check-rpath {} { expr {"" ne [get-define LDFLAGS_RPATH]} } -######################################################################## +# # @proj-check-soname ?libname? # # Checks whether CC supports the -Wl,soname,lib... flag. If so, it @@ -1086,6 +1142,7 @@ proc proj-check-rpath {} { # 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}"]} { @@ -1098,7 +1155,7 @@ proc proj-check-soname {{libname "libfoo.so.0"}} { } } -######################################################################## +# # @proj-check-fsanitize ?list-of-opts? # # Checks whether CC supports -fsanitize=X, where X is each entry of @@ -1113,6 +1170,7 @@ proc proj-check-soname {{libname "libfoo.so.0"}} { # # 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 { @@ -1131,12 +1189,13 @@ proc proj-check-fsanitize {{opts {address bounds-strict}}} { 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 { @@ -1148,20 +1207,22 @@ proc proj-defs-type_ {name spec} { 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 { @@ -1200,7 +1261,7 @@ proc proj-defs-format_ {type value} { 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 @@ -1230,6 +1291,7 @@ proc proj-defs-format_ {type value} { # 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 {} @@ -1248,7 +1310,7 @@ proc proj-dump-defs-json {file args} { } } -######################################################################## +# # @proj-xfer-option-aliases map # # Expects a list of pairs of configure flags which have been @@ -1283,6 +1345,7 @@ proc proj-dump-defs-json {file args} { # 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]} { @@ -1295,7 +1358,7 @@ proc proj-xfer-options-aliases {mapping} { } } -######################################################################## +# # Arguable/debatable... # # When _not_ cross-compiling and CC_FOR_BUILD is _not_ explicitly @@ -1311,6 +1374,7 @@ proc proj-xfer-options-aliases {mapping} { # 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] @@ -1320,13 +1384,14 @@ proc proj-redefine-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]} { @@ -1336,7 +1401,7 @@ proc proj-which-linenoise {dotH} { } } -######################################################################## +# # @proj-remap-autoconf-dir-vars # # "Re-map" the autoconf-conventional --XYZdir flags into something @@ -1373,6 +1438,7 @@ proc proj-which-linenoise {dotH} { # 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] @@ -1406,13 +1472,14 @@ proc proj-remap-autoconf-dir-vars {} { } } -######################################################################## +# # @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]} { @@ -1421,7 +1488,7 @@ proc proj-env-file {flag {dflt ""}} { return $dflt } -######################################################################## +# # @proj-get-env var ?default? # # Extracts the value of "environment" variable $var from the first of @@ -1432,11 +1499,12 @@ proc proj-env-file {flag {dflt ""}} { # - 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 @@ -1444,6 +1512,7 @@ proc proj-get-env {var {dflt ""}} { # 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] @@ -1458,13 +1527,14 @@ proc proj-current-scope {{lvl 0}} { } -######################################################################## +# # 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 { @@ -1511,7 +1581,7 @@ proc proj-tclConfig-sh-to-autosetup {tclConfigSh} { } } -######################################################################## +# # @proj-tweak-default-env-dirs # # This function is not useful before [use system] is called to set up @@ -1529,6 +1599,7 @@ proc proj-tclConfig-sh-to-autosetup {tclConfigSh} { # 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] { @@ -1550,7 +1621,7 @@ proc proj-tweak-default-env-dirs {} { return $rc } -######################################################################## +# # @proj-dot-ins-append file ?fileOut ?postProcessScript?? # # Queues up an autosetup [make-template]-style file to be processed @@ -1569,6 +1640,7 @@ proc proj-tweak-default-env-dirs {} { # 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] { @@ -1589,17 +1661,18 @@ proc proj-dot-ins-append {fileIn 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] @@ -1620,6 +1693,7 @@ proc proj-dot-ins-list {} { # # -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"} @@ -1647,7 +1721,7 @@ proc proj-dot-ins-process {args} { } } -######################################################################## +# # @proj-validate-no-unresolved-ats filenames... # # For each filename given to it, it validates that the file has no @@ -1661,6 +1735,7 @@ proc proj-dot-ins-process {args} { # 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 @@ -1676,12 +1751,13 @@ proc proj-validate-no-unresolved-ats {args} { } } -######################################################################## +# # @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 { @@ -1693,10 +1769,11 @@ proc proj-first-file-found {fileList tgtVar} { 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 @@ -1713,11 +1790,12 @@ proc proj-setup-autoreconfig {defName} { } } -######################################################################## +# # @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} { @@ -1726,7 +1804,7 @@ proc proj-define-append {defineName args} { } } -######################################################################## +# # @prod-define-amend ?-p|-prepend? ?-define? FLAG args... # # A proxy for Autosetup's [define-append]. @@ -1744,6 +1822,7 @@ proc proj-define-append {defineName args} { # technically correct and still relevant on some environments. # # See: proj-append-to +# proc proj-define-amend {args} { set defName "" set prepend 0 @@ -1783,6 +1862,7 @@ proc proj-define-amend {args} { } } +# # @proj-define-to-cflag ?-list? defineName... # # Treat each argument as the name of a [define] @@ -1798,6 +1878,7 @@ proc proj-define-amend {args} { # 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 {} @@ -1878,6 +1959,7 @@ if {0} { # Internal cache for use via proj-cache-*. array set proj__Cache {} +# # @proj-cache-key ?addLevel? arg # # Helper to generate cache keys for [proj-cache-*]. @@ -1901,6 +1983,7 @@ proc proj-cache-key {{addLevel 0} arg} { return $arg } +# # @proj-cache-set ?key? ?addLevel? value # # Sets a feature-check cache entry with the given key. @@ -1913,6 +1996,7 @@ proc proj-cache-set {{key 0} {addLevel 0} val} { set ::proj__Cache($key) $val } +# # @proj-cache-remove ?key? ?addLevel? # # Removes an entry from the proj-cache. @@ -1926,6 +2010,7 @@ proc proj-cache-remove {{key 0} {addLevel 0}} { return $rv; } +# # @proj-cache-check ?$key? ?addLevel? tgtVarName # # Checks for a feature-check cache entry with the given key. @@ -1950,6 +2035,7 @@ proc proj-cache-check {{key 0} {addLevel 0} tgtVar} { return $rc } +# # @proj-coalesce ...args # # Returns the first argument which is not empty (eq ""), or an empty @@ -1963,6 +2049,7 @@ proc proj-coalesce {args} { return "" } +# # @proj-parse-simple-flags ... # # An experiment. Do not use. @@ -2064,7 +2151,7 @@ proc proj-parse-simple-flags {argvName tgtArrayName prototype} { 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 @@ -2080,12 +2167,12 @@ proc proj-parse-simple-flags {argvName tgtArrayName prototype} { 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 @@ -2093,7 +2180,6 @@ proc proj-parse-simple-flags {argvName tgtArrayName prototype} { incr skipMode lappend rv $arg } - incr i } set argv $rv return $rc diff --git a/manifest b/manifest index a2ce1a6072..2a8589e62e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -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 @@ -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 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 @@ -51,7 +51,7 @@ F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e 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 @@ -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 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. diff --git a/manifest.uuid b/manifest.uuid index 2da6206783..0400ecc4de 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -de0968226effb79f9d25539da7882fa5475e4ff2410870b45a63a6545deb5979 +c72c00d34d70b36f847af19a2382299746448b5dd94a616f6b567389c5694c17