Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Latest upstream teaish. Most notably it adds the ability for the extension to specify a minimum Tcl version, and this build now enforces a minimum Tcl of 8.6. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
c86315e538f4d75161faa72673927cde |
User & Date: | stephan 2025-04-16 21:53:01.406 |
Context
2025-04-16
| ||
22:25 | Add docs explaining how to test the teaish build. (check-in: b53619ddb7 user: stephan tags: trunk) | |
21:53 | Latest upstream teaish. Most notably it adds the ability for the extension to specify a minimum Tcl version, and this build now enforces a minimum Tcl of 8.6. (check-in: c86315e538 user: stephan tags: trunk) | |
17:47 | Update doc/tcl-extension-testing.md for Unix systems, consolidating the Tcl 8.x and 9.x sections. (check-in: c4c5dcb79c user: stephan tags: trunk) | |
Changes
Changes to autoconf/tea/Makefile.in.
︙ | ︙ | |||
34 35 36 37 38 39 40 | # any given teaish build. # tx.name = @TEAISH_NAME@ tx.pkgName = @TEAISH_PKGNAME@ tx.version = @TEAISH_VERSION@ tx.libdir = @TEAISH_LIBDIR_NAME@ tx.loadPrefix = @TEAISH_LOAD_PREFIX@ | < | | | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | # any given teaish build. # tx.name = @TEAISH_NAME@ tx.pkgName = @TEAISH_PKGNAME@ tx.version = @TEAISH_VERSION@ tx.libdir = @TEAISH_LIBDIR_NAME@ tx.loadPrefix = @TEAISH_LOAD_PREFIX@ tx.tcl = @TEAISH_TCL@ tx.makefile = @TEAISH_MAKEFILE@ tx.makefile.in = @TEAISH_MAKEFILE_IN@ tx.dll8.basename = @TEAISH_DLL8_BASENAME@ tx.dll9.basename = @TEAISH_DLL9_BASENAME@ tx.dll8 = @TEAISH_DLL8@ tx.dll9 = @TEAISH_DLL9@ tx.dll = $(tx.dll$(TCL_MAJOR_VERSION)) tx.dir = @TEAISH_DIR@ teaish.dir = @abs_top_srcdir@ #teaish.dir.autosetup = @TEAISH_AUTOSETUP_DIR@ teaish.makefile = Makefile teaish.makefile.in = $(teaish.dir)/Makefile.in teaish__auto.def = $(teaish.dir)/auto.def # # Autotools-conventional vars. We don't actually use these in this # makefile but some may be referenced by vars imported via # tclConfig.sh. They are part of the public API and may be reliably # depended on from teaish.make.in. |
︙ | ︙ | |||
152 153 154 155 156 157 158 | # as a dependency to the 'clean' target, like so: # # clean: distclean-extension # distclean: distclean-extension # teaish__cleanExtra = | < | > > > > > > > > > > > > > | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | # as a dependency to the 'clean' target, like so: # # clean: distclean-extension # distclean: distclean-extension # teaish__cleanExtra = # List of deps which may trigger an auto-reconfigure. # teaish__autogen.deps = \ $(tx.makefile.in) $(teaish.makefile.in) \ $(tx.tcl) \ @TEAISH_PKGINDEX_TCL_IN@ \ @TEAISH_MODULE_TEST_TCL@ \ @AUTODEPS@ # # 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@ # ^^^ 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.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@ # # The rest of this makefile exists solely to support this brief # 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) |
︙ | ︙ | |||
204 205 206 207 208 209 210 | # If the extension has no test script, add a small one which # simply loads the DLL and success if it can. # # tx.tester.args = $(tx.dll) $(tx.loadPrefix) @TEAISH_MODULE_TEST_TCL@ .PHONY: test-pre test-core test test-post test-extension test-extension: # this name is reserved for use by teaish.make | | | | > > > > > > > > > > > > > > > > > | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | # If the extension has no test script, add a small one which # simply loads the DLL and success if it can. # # tx.tester.args = $(tx.dll) $(tx.loadPrefix) @TEAISH_MODULE_TEST_TCL@ .PHONY: test-pre test-core test test-post test-extension test-extension: # this name is reserved for use by teaish.make test-prepre: $(tx.dll) @TEAISH_TESTER_TCL@ test-pre: test-prepre test-core: test-pre $(TCLSH) @TEAISH_TESTER_TCL@ $(tx.tester.args) test-post: test-core test: test-post # # Cleanup rules... # #.PHONY: clean-pre clean-core clean-post clean-extension clean-extension: # this name is reserved for use by teaish.make clean-pre: clean-core: clean-pre rm -f $(tx.dll8) $(tx.dll9) tclsh $(teaish__cleanExtra) 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 rm -f config.log config.defines.txt @if TEAISH_MAKEFILE_IN @if TEAISH_MAKEFILE rm -f @TEAISH_MAKEFILE@ @endif @endif @if TEAISH_TESTER_TCL_IN rm -f @TEAISH_TESTER_TCL@ @endif @if TEAISH_PKGINDEX_TCL_IN rm -f @TEAISH_PKGINDEX_TCL@ @endif @if TEAISH_PKGINIT_TCL_IN rm -f @TEAISH_PKGINIT_TCL@ @endif @if TEAISH_TEST_TCL_IN rm -f @TEAISH_TEST_TCL@ @endif distclean-post: distclean-core distclean: distclean-post # # Installation rules... # .PHONY: install-pre install-core install-post install-test install-prepre install-extension |
︙ | ︙ | |||
275 276 277 278 279 280 281 | uninstall-core: uninstall-pre rm -fr "$(DESTDIR)$(TCLLIBDIR)" uninstall-post: uninstall-core @echo "Uninstalled Tcl extension $(tx.name) $(tx.version)" uninstall: uninstall-post Makefile: config.log $(teaish.makefile.in) | | | | 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | uninstall-core: uninstall-pre rm -fr "$(DESTDIR)$(TCLLIBDIR)" 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@ @endif # # Package archive generation ("dist") rules... # @if TEAISH_ENABLE_DIST @if BIN_ZIP |
︙ | ︙ | |||
350 351 352 353 354 355 356 | dist: @if TEAISH_OUT_OF_EXT_TREE @echo "'dist' can only be used from an extension's home dir" 1>&2; \ echo "In this case: @TEAISH_DIR@" 1>&2; exit 1 @endif @endif #TEAISH_ENABLE_DIST | < | > > > > > > > > > > > > > > > < > > > | 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 | dist: @if TEAISH_OUT_OF_EXT_TREE @echo "'dist' can only be used from an extension's home dir" 1>&2; \ echo "In this case: @TEAISH_DIR@" 1>&2; exit 1 @endif @endif #TEAISH_ENABLE_DIST # # TEAISH_MAKEFILE[_IN] defines any extension-specific state this file # needs. # # It must set the following vars if they're not already accounted for # via teaish.tcl. # # - 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]. # # It may optionally set the following vars: # # - tx.CFLAGS = CFLAGS/CPPFLAGS. Optionally, [define] TEAISH_CFLAGS # or pass them to [teaish-add-cflags]. # # - tx.LDFLAGS = LDFLAGS. Optionally, [define] TEAISH_LDFLAGS or # pass them to [teaish-add-ldflags]. # # 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. # #@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-add-make] to incrementally build up this # content. # @if TEAISH_MAKEFILE_CODE # TEAISH_MAKEFILE_CODE ==> Makefile: @TEAISH_TCL@ @TEAISH_MAKEFILE_CODE@ @endif #TEAISH_MAKEFILE_CODE |
Changes to autoconf/tea/autosetup/core.tcl.
︙ | ︙ | |||
44 45 46 47 48 49 50 51 52 53 54 55 56 57 | # 0x04 = teaish__find_extension found TEAISH_DIR/pkgIndex.tcl (static file) # 0x10 = teaish-pragma was called: behave as if 0x04 # # This might no longer be needed. pkgindex-policy 0 }] set teaish__Config(core-dir) $::autosetup(libdir)/teaish # # Returns true if any arg in $::argv matches any of the given globs, # else returns false. # proc teaish__argv_has {args} { foreach glob $args { foreach arg $::argv { | > | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # 0x04 = teaish__find_extension found TEAISH_DIR/pkgIndex.tcl (static file) # 0x10 = teaish-pragma was called: behave as if 0x04 # # This might no longer be needed. pkgindex-policy 0 }] set teaish__Config(core-dir) $::autosetup(libdir)/teaish # # Returns true if any arg in $::argv matches any of the given globs, # else returns false. # proc teaish__argv_has {args} { foreach glob $args { foreach arg $::argv { |
︙ | ︙ | |||
78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 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 "" } { define $f $v } 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 | > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 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 } 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 |
︙ | ︙ | |||
188 189 190 191 192 193 194 | } proj-assert {1==$gotExt} "Else we cannot have gotten this far" teaish__configure-phase1 } | < > > > > > > | > > > > | > | | | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | } proj-assert {1==$gotExt} "Else we cannot have gotten this far" teaish__configure-phase1 } # # Internal config-time debugging output routine. It is not legal to # call this from the global scope. # proc teaish-debug {msg} { if {$::teaish__Config(debug-enabled)} { puts stderr [proj-bold "** DEBUG: \[[proj-current-scope 1]\]: $msg"] } } # # Runs "phase 1" of the configuration, immediately after processing # --flags. This is what will import the client-defined teaish.tcl. # proc teaish__configure-phase1 {} { # Set up some default values if the user did not set them. foreach {key val} [list \ TEAISH_PKGNAME [get-define TEAISH_NAME] \ TEAISH_VERSION 0.0.0 \ TEAISH_MAKEFILE_CODE ""] { if {"<nope>" eq [get-define $key "<nope>"]} { #puts "***** defining default $key $val" define $key $val } } # Do it again for vars which rely on defaults derived from other # vars. foreach {key val} [list \ TEAISH_LIBDIR_NAME \ [join [list \ [get-define TEAISH_PKGNAME ""] \ [get-define TEAISH_VERSION ""]] \ "" ] \ TEAISH_LOAD_PREFIX [string totitle \ [get-define TEAISH_PKGNAME ""]] \ TEAISH_PKGNAME [get-define TEAISH_NAME]] { if {"<nope>" eq [get-define $key "<nope>"]} { #puts "***** defining default $key $val" define $key $val } } msg-result \ "Configuring extension [proj-bold [get-define TEAISH_NAME] [get-define TEAISH_VERSION]]..." 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 # TCL_... counterpart from tclConfig.sh. Caveat: by the time we can # reach this point, autosetup's system.tcl will have already done # some non-trivial amount of work with these to create various # derived values from them, so we temporarily end up with a mishmash |
︙ | ︙ | |||
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | # } if {[llength [info proc teaish-configure]] > 0} { # teaish-configure is assumed to be imported via # TEAISH_TCL teaish-configure } if {[proj-looks-like-windows]} { # Without this, linking of an extension will not work on Cygwin or # Msys2. msg-result "Using USE_TCL_STUBS for Unix(ish)-on-Windows environment" teaish-add-cflags -DUSE_TCL_STUBS=1 } #define AS_LIBDIR $::autosetup(libdir) define TEAISH_MODULE_TEST_TCL $::teaish__Config(core-dir)/tester.tcl | > > > > > > > > > > > > > > > > > > > < < < < > < < | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | # } if {[llength [info proc teaish-configure]] > 0} { # teaish-configure is assumed to be imported via # TEAISH_TCL teaish-configure } 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. 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" \ [get-define TEAISH_NAME] \ [get-define TEAISH_VERSION] \ ": expecting vsatisfies to match ($vsat)"]] } unset vsat } } if {[proj-looks-like-windows]} { # Without this, linking of an extension will not work on Cygwin or # Msys2. msg-result "Using USE_TCL_STUBS for Unix(ish)-on-Windows environment" teaish-add-cflags -DUSE_TCL_STUBS=1 } #define AS_LIBDIR $::autosetup(libdir) define TEAISH_MODULE_TEST_TCL $::teaish__Config(core-dir)/tester.tcl apply {{} { # # Ensure we have a pkgIndex.tcl and don't have a stale generated one # when rebuilding for different --with-tcl=... values. # if {!$::teaish__Config(pkgindex-policy)} { proj-fatal "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__Config(pkgindex-policy) set dEx $::teaish__Config(teaish-dir) set dSrc $::autosetup(srcdir) 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 } |
︙ | ︙ | |||
345 346 347 348 349 350 351 | } proj-remap-autoconf-dir-vars define TEAISH__DEFINES_MAP \ [teaish__dump_defs_to_list]; # injected into teaish.tester.tcl proj-dot-ins-process -validate; # do not [define] after this point proj-if-opt-truthy teaish-dump-defines { make-config-header config.defines.txt \ | | > | > < | < > | < > | | | 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 | } proj-remap-autoconf-dir-vars define TEAISH__DEFINES_MAP \ [teaish__dump_defs_to_list]; # injected into teaish.tester.tcl proj-dot-ins-process -validate; # do not [define] after this point proj-if-opt-truthy teaish-dump-defines { make-config-header config.defines.txt \ -none {TEAISH__* TEAISH_MAKEFILE_CODE} \ -str { BIN_* CC LD AR INSTALL LDFLAG* CFLAGS* *_LDFLAGS *_CFLAGS } \ -bare {HAVE_*} \ -auto {*} } # # If these are set up before call [options], it triggers an # "option already defined" error. # #proj-opt-set teaish.tcl [get-define ] #proj-opt-set teaish.make.in [get-define ] # # $::autosetup(builddir)/.configured is a workaround to prevent # concurrent executions of TEAISH_AUTORECONFIG. MUST come last in # the configure process. # #proj-file-write $::autosetup(builddir)/.configured "" } # # Run checks for required binaries. # proc teaish__check_common_bins {} { if {"" eq [proj-bin-define install]} { proj-warn "Cannot find install binary, so 'make install' will not work." define BIN_INSTALL false } if {"" eq [proj-bin-define zip]} { proj-warn "Cannot find zip, so 'make dist.zip' will not work." } if {"" eq [proj-bin-define tar]} { proj-warn "Cannot find tar, so 'make dist.tgz' will not work." } } # # TCL... # # teaish__check_tcl performs most of the --with-tcl and --with-tclsh # handling. Some related bits and pieces are performed before and # after that function is called. # # Important [define]'d vars: # # - TCLSH_CMD is the path to the canonical tclsh or "". # # - TCL_CONFIG_SH is the path to tclConfig.sh or "". # # - TCLLIBDIR is the dir to which the extension library gets # - installed. # proc teaish__check_tcl {} { define TCLSH_CMD false ; # Significant is that it exits with non-0 define TCLLIBDIR "" ; # Installation dir for TCL extension lib define TCL_CONFIG_SH ""; # full path to tclConfig.sh # Clear out all vars which would harvest from tclConfig.sh so that # the late-config validation of @VARS@ works even if --disable-tcl # is used. |
︙ | ︙ | |||
724 725 726 727 728 729 730 | define TEAISH_PKGINIT_TCL [file tail [file rootname $extI]] } else { define TEAISH_PKGINIT_TCL_IN "" define TEAISH_PKGINIT_TCL $extI } apply $addDist $extI msg-result "Extension post-load init = $extI" | > | | < | | < | < < < < | | | < < | | > | | | | > > > > | | | | > > > > > > > > > > > > | | | > > > | | | | > | 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 | define TEAISH_PKGINIT_TCL [file tail [file rootname $extI]] } else { define TEAISH_PKGINIT_TCL_IN "" define TEAISH_PKGINIT_TCL $extI } apply $addDist $extI 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 } # Look for pkgIndex.tcl[.in]... set piPolicy 0 if {[proj-first-file-found $dirExt/pkgIndex.tcl.in extPI]} { # Generate ./pkgIndex.tcl from it. define TEAISH_PKGINDEX_TCL_IN $extPI define TEAISH_PKGINDEX_TCL [file rootname [file tail $extPI]] proj-dot-ins-append $extPI file delete -force -- [get-define TEAISH_PKGINDEX_TCL] apply $addDist $extPI set piPolicy 0x01 } elseif {$dirExt ne $dirSrc && [proj-first-file-found $dirSrc/pkgIndex.tcl.in extPI]} { # Generate ./pkgIndex.tcl from it. define TEAISH_PKGINDEX_TCL_IN $extPI define TEAISH_PKGINDEX_TCL [file rootname [file tail $extPI]] proj-dot-ins-append $extPI file delete -force -- [get-define TEAISH_PKGINDEX_TCL] set piPolicy 0x02 } elseif {[proj-first-file-found $dirExt/pkgIndex.tcl extPI]} { # Assume it's a static file and use it. define TEAISH_PKGINDEX_TCL_IN "" define TEAISH_PKGINDEX_TCL $extPI apply $addDist $extPI set piPolicy 0x04 } set ::teaish__Config(pkgindex-policy) $piPolicy # Look for teaish.test.tcl[.in] proj-assert {"" ne $dirExt} set flist [list $dirExt/teaish.test.tcl.in $dirExt/teaish.test.tcl] if {[proj-first-file-found $flist ttt]} { if {[string match *.in $ttt]} { # Generate teaish.test.tcl from $ttt set xt [file rootname [file tail $ttt]] file delete -force -- $xt; # ensure no stale copy is used define TEAISH_TEST_TCL $xt define TEAISH_TEST_TCL_IN $ttt proj-dot-ins-append $ttt $xt } else { define TEAISH_TEST_TCL $ttt define TEAISH_TEST_TCL_IN "" } apply $addDist $ttt } else { define TEAISH_TEST_TCL "" define TEAISH_TEST_TCL_IN "" } # Look for teaish.tester.tcl[.in] set flist [list $dirExt/teaish.tester.tcl.in $dirSrc/teaish.tester.tcl.in] if {[proj-first-file-found $flist ttt]} { # Generate teaish.test.tcl from $ttt set xt [file rootname [file tail $ttt]] file delete -force -- $xt; # ensure no stale copy is used define TEAISH_TESTER_TCL $xt define TEAISH_TESTER_TCL_IN $ttt proj-dot-ins-append $ttt $xt if {[lindex $flist 0] eq $ttt} { apply $addDist $ttt } } 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 } unset flist xt ttt # TEAISH_OUT_OF_EXT_TREE = 1 if we're building from a dir other # than the extension's home dir. set dteaish [file-normalize [get-define TEAISH_DIR]] define TEAISH_OUT_OF_EXT_TREE \ [expr {[file-normalize $::autosetup(builddir)] ne $dteaish}] return 1 }; # teaish__find_extension # @teaish-add-cflags ?-p|prepend? ?-define? cflags... # # Equivalent to [proj-define-amend TEAISH_CFLAGS {*}$args]. # proc teaish-add-cflags {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 |
︙ | ︙ | |||
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 | # # Typically, -lXYZ flags need to be in "reverse" order, with each -lY # resolving symbols for -lX's to its left. This order is largely # historical, and not relevant on all environments, but it is # technically correct and still relevant on some environments. # # See: teaish-prepend-ldflags proc teaish-add-ldflags {args} { proj-define-amend TEAISH_LDFLAGS {*}$args } # @teaish-prepend-ldflags args... # # Functionally equivalent to [teaish-add-ldflags -p {*}$args] proc teaish-prepend-ldflags {args} { teaish-add-ldflags -p {*}$args } # @teaish-add-src ?-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]. # # 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 # 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). proc teaish-add-src {args} { set i 0 proj-parse-simple-flags args flags { -dist 0 {return 1} -dir 0 {return 1} } if {$flags(-dist)} { | > > > | 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 | # # Typically, -lXYZ flags need to be in "reverse" order, with each -lY # resolving symbols for -lX's to its left. This order is largely # historical, and not relevant on all environments, but it is # technically correct and still relevant on some environments. # # See: teaish-prepend-ldflags # proc teaish-add-ldflags {args} { proj-define-amend TEAISH_LDFLAGS {*}$args } # @teaish-prepend-ldflags args... # # Functionally equivalent to [teaish-add-ldflags -p {*}$args] # proc teaish-prepend-ldflags {args} { teaish-add-ldflags -p {*}$args } # @teaish-add-src ?-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]. # # 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 # 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). # proc teaish-add-src {args} { set i 0 proj-parse-simple-flags args flags { -dist 0 {return 1} -dir 0 {return 1} } if {$flags(-dist)} { |
︙ | ︙ | |||
875 876 877 878 879 880 881 882 883 884 885 886 887 888 | # Equivalent to [proj-define-apend TEAISH_DIST_FILES ...]. # # This is a no-op when the current build is not in the extension's # directory, as dist support is disabled in out-of-tree builds. # # It is not legal to call this until TEAISH_DIR has been reliably set # (via teaish__find_extension). proc teaish-add-dist {args} { if {$::teaish__Config(blddir-is-extdir)} { proj-define-amend TEAISH_DIST_FILES {*}$args } } # teaish-add-install files... | > | 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 | # Equivalent to [proj-define-apend TEAISH_DIST_FILES ...]. # # This is a no-op when the current build is not in the extension's # directory, as dist support is disabled in out-of-tree builds. # # It is not legal to call this until TEAISH_DIR has been reliably set # (via teaish__find_extension). # proc teaish-add-dist {args} { if {$::teaish__Config(blddir-is-extdir)} { proj-define-amend TEAISH_DIST_FILES {*}$args } } # teaish-add-install files... |
︙ | ︙ | |||
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 | # a relatively generic list of options for controlling which defined # symbols get exported. Clients which need more control over the # exports can copy/paste/customize this. # # The exported file is then passed to [proj-touch] because, in # practice, that's sometimes necessary to avoid build dependency # issues. proc teaish-make-config-header {filename} { make-config-header $filename \ -bare {} \ -none {HAVE_CFLAG_* LDFLAGS_* SH_*} \ -auto {SIZEOF_* HAVE_* TEAISH_* TCL_*} \ -none * proj-touch $filename; # help avoid frequent unnecessary auto-reconfig } # @teaish-feature-cache-set ?$key? value # # Sets a feature-check cache entry with the given key. # See proj-cache-set for the key's semantics. proc teaish-feature-cache-set {{key 0} val} { proj-cache-set $key 1 $val } # @teaish-feature-cache-check ?$key? tgtVarName # # Checks for a feature-check cache entry with the given key. # See proj-cache-set for the key's semantics. # # If the feature-check cache has a matching entry then this function # assigns its value to tgtVar and returns 1, else it assigns tgtVar to # "" and returns 0. # # See proj-cache-check for $key's semantics. proc teaish-feature-cache-check {{key 0} tgtVar} { upvar $tgtVar tgt proj-cache-check $key 1 tgt } # @teaish-check-cached@ ?-nostatus? msg script # | > > > | 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 | # a relatively generic list of options for controlling which defined # symbols get exported. Clients which need more control over the # exports can copy/paste/customize this. # # The exported file is then passed to [proj-touch] because, in # practice, that's sometimes necessary to avoid build dependency # issues. # proc teaish-make-config-header {filename} { make-config-header $filename \ -bare {} \ -none {HAVE_CFLAG_* LDFLAGS_* SH_*} \ -auto {SIZEOF_* HAVE_* TEAISH_* TCL_*} \ -none * proj-touch $filename; # help avoid frequent unnecessary auto-reconfig } # @teaish-feature-cache-set ?$key? value # # Sets a feature-check cache entry with the given key. # See proj-cache-set for the key's semantics. # proc teaish-feature-cache-set {{key 0} val} { proj-cache-set $key 1 $val } # @teaish-feature-cache-check ?$key? tgtVarName # # Checks for a feature-check cache entry with the given key. # See proj-cache-set for the key's semantics. # # If the feature-check cache has a matching entry then this function # assigns its value to tgtVar and returns 1, else it assigns tgtVar to # "" and returns 0. # # See proj-cache-check for $key's semantics. # proc teaish-feature-cache-check {{key 0} tgtVar} { upvar $tgtVar tgt proj-cache-check $key 1 tgt } # @teaish-check-cached@ ?-nostatus? msg script # |
︙ | ︙ | |||
978 979 980 981 982 983 984 985 986 987 988 989 990 991 | # calling scope and its result value is stored in the cache. This # routine will intercept a 'return' from $script. # # Flags: # # -nostatus = do not emit "ok" or "no" at the end. This presumes # that the caller will emit at least one newline before turning. proc teaish-check-cached {args} { proj-parse-simple-flags args flags { -nostatus 0 {expr 1} } lassign $args msg script if {"" eq $msg} { set msg [proj-current-scope 1] | > | 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 | # calling scope and its result value is stored in the cache. This # routine will intercept a 'return' from $script. # # Flags: # # -nostatus = do not emit "ok" or "no" at the end. This presumes # that the caller will emit at least one newline before turning. # proc teaish-check-cached {args} { proj-parse-simple-flags args flags { -nostatus 0 {expr 1} } lassign $args msg script if {"" eq $msg} { set msg [proj-current-scope 1] |
︙ | ︙ | |||
1012 1013 1014 1015 1016 1017 1018 | teaish-feature-cache-set 1 0 } #puts "**** code=$code rc=$rc" return {*}$xopt $rc } } | < > | > > > | < > | > > > < > | | | | | > < > > > > > > > > > > > > > > > | | > > > > > > > > > > | | < > | > | > > | 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 | teaish-feature-cache-set 1 0 } #puts "**** code=$code rc=$rc" return {*}$xopt $rc } } # # Internal helper for teaish__defs_format_: returns a JSON-ish quoted # form of the given string-type values. # # If $asList is true then the return value is in {$value} form. If # $asList is false it only performs the most basic of escaping and # the input must not contain any control characters. # proc teaish__quote_str {asList value} { if {$asList} { return [join [list "\{" $value "\}"] ""] } return \"[string map [list \\ \\\\ \" \\\"] $value]\" } # # Internal helper for teaish__dump_defs_to_list. Expects to be passed # a name and the variadic $args which are passed to # teaish__dump_defs_to_list.. If it finds a pattern match for the # given $name in the various $args, it returns the type flag for that # $name, e.g. "-str" or "-bare", else returns an empty string. # proc teaish__defs_type {name spec} { foreach {type patterns} $spec { foreach pattern $patterns { if {[string match $pattern $name]} { return $type } } } return "" } # # An internal impl detail. Requires a data type specifier, as used by # make-config-header, and a value. Returns the formatted value or the # value $::teaish__Config(defs-skip) if the caller should skip # emitting that value. # # In addition to -str, -auto, etc., as defined by make-config-header, # it supports: # # -list {...} will cause non-integer values to be quoted in {...} # instead of quotes. # # -autolist {...} works like -auto {...} except that it falls back to # -list {...} type instead of -str {...} style for non-integers. # # -array {...} emits the output in something which, for conservative # inputs, will be a valid JSON array. It can only handle relatively # simple values with no control characters in them. # set teaish__Config(defs-skip) "-teaish__defs_format sentinel" proc teaish__defs_format {type value} { switch -exact -- $type { -bare { # Just output the value unchanged } -none { set value $::teaish__Config(defs-skip) } -str { set value [teaish__quote_str 0 $value] } -auto { # Automatically determine the type if {![string is integer -strict $value]} { set value [teaish__quote_str 0 $value] } } -autolist { if {![string is integer -strict $value]} { set value [teaish__quote_str 1 $value] } } -list { set value [teaish__quote_str 1 $value] } -array { set ar {} foreach v $value { set v [teaish__defs_format -auto $v] if {$::teaish__Config(defs-skip) ne $v} { lappend ar $v } } set value "\[ [join $ar {, }] \]" } "" { set value $::teaish__Config(defs-skip) } default { proj-fatal \ "Unknown [project-current-scope] -type ($type) called from" \ [proj-current-scope 1] } } return $value } # # Returns Tcl code in the form of code which evaluates to a list of # configure-time DEFINEs in the form {key val key2 val...}. It may # misbehave for values which are not numeric or simple strings. # proc teaish__dump_defs_to_list {args} { set lines {} lappend lines "\{" set skipper $::teaish__Config(defs-skip) lappend args \ -none { TEAISH__* TEAISH_MAKEFILE_CODE AM_* AS_* } \ -auto { SIZEOF_* HAVE_* } \ -autolist * foreach n [lsort [dict keys [all-defines]]] { set type [teaish__defs_type $n $args] set value [teaish__defs_format $type [get-define $n]] if {$skipper ne $value} { lappend lines "$n $value" } } lappend lines "\}" return [join $lines "\n"] } # # @teaish-pragma ...flags # # Offers a way to tweak how teaish's core behaves in some cases, in # particular those which require changing how the core looks for an # extension and its files. # # Accepts the following flags. Those marked with [L] are safe to use # during initial loading of tclish.tcl (recall that most teaish APIs # cannot be used until [teaish-configure] is called). # # --have-own-pkgIndex.tcl [L]: Tells teaish that ./pkgIndex.tcl is # not a generated file, so it will not try to overwrite or delete # it. # # Emits a warning message for unknown arguments. # proc teaish-pragma {args} { foreach arg $args { switch -exact -- $arg { --have-own-pkgIndex.tcl { set flist [list \ [file join $::teaish__Config(teaish-dir) pkgIndex.tcl.in] \ |
︙ | ︙ | |||
1163 1164 1165 1166 1167 1168 1169 | # # --disable-dist { # define TEAISH_ENABLE_DIST 0 # } } } | | | 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 | # # --disable-dist { # define TEAISH_ENABLE_DIST 0 # } } } # # @teaish-enable-dist ?yes? # # Explicitly enables or disables the "dist" rules in the default # Makefile.in. This is equivalent to defining TEAISH_ENABLE_DIST # to $yes (which must be 0 or 1). # # By default, dist creation is enabled. |
︙ | ︙ | |||
1211 1212 1213 1214 1215 1216 1217 | set name [file tail $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} | | | | > > > > > > > | 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 | set name [file tail $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 # 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. } proc teaish-configure {} { set d \[get-define TEAISH_DIR] teaish-add-src \$d/teaish.c teaish-add-dist teaish.c } " proj-file-write teaish.tcl $content |
︙ | ︙ |
Changes to autoconf/tea/autosetup/tester.tcl.
︙ | ︙ | |||
57 58 59 60 61 62 63 | } ######################################################################## # @test-error msg # # Triggers a test-failed error with a string describing the calling # scope and the provided message. | | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | } ######################################################################## # @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"; |
︙ | ︙ | |||
125 126 127 128 129 130 131 | } rc xopts]} { puts "[test-current-scope] ignoring failure of: $cmd [lindex $args 0]: $rc" return 1 } return 0 } | > | > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | } rc xopts]} { puts "[test-current-scope] ignoring failure of: $cmd [lindex $args 0]: $rc" return 1 } return 0 } if {![array exists ::teaish__BuildFlags]} { array set ::teaish__BuildFlags {} } # @teaish-build-flag2 flag tgtVar ?dflt? # # Caveat #1: only valid when called in the context of teaish's default # "make test" recipe, e.g. from teaish.test.tcl. It is not valid from # a teaish.tcl configure script because (A) the state it relies on # doesn't fully exist at that point and (B) that level of the API has |
︙ | ︙ |
Changes to autoconf/tea/pkgIndex.tcl.in.
1 | # -*- tcl -*- | < > > > > > > > > > > | < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # -*- tcl -*- # Tcl package index file # # Unless this file is named pkgIndex.tcl.in, you are probably looking # at an automatically generated/filtered copy and should probably not # edit it. # # Adapted from https://core.tcl-lang.org/tcltls @if TEAISH_VSATISFIES_TCL if {![package vsatisfies [package provide Tcl] @TEAISH_VSATISFIES_TCL@]} { error "Package @TEAISH_PKGNAME@ @TEAISH_VERSION@ requires 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@ @if 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@ } else { load {} @TEAISH_LOAD_PREFIX@ } @if TEAISH_PKGINIT_TCL_TAIL set initScript [file join $dir @TEAISH_PKGINIT_TCL_TAIL@] if {[file exists $initScript]} { source -encoding utf-8 $initScript } @endif }} $dir] } |
Changes to autoconf/tea/teaish.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 | # 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_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]] ""] # # Object for communicating certain config-time state across various | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 | # 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]] ""] # # Object for communicating certain config-time state across various |
︙ | ︙ |
Changes to autoconf/tea/teaish.tester.tcl.in.
1 | # -*- tcl -*- | > > | > > > > > > | > > | > > > > > > > > | | > | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # -*- tcl -*- # # Unless this file is named teaish.tester.tcl.in, you are probably # looking at an automatically generated/filtered copy and should # probably not edit it. # # This is the wrapper script invoked by teaish's "make test" recipe. @if TEAISH_VSATISFIES_TCL if {![package vsatisfies [package provide Tcl] @TEAISH_VSATISFIES_TCL@]} { error "Package @TEAISH_PKGNAME@ @TEAISH_VERSION@ requires Tcl @TEAISH_VSATISFIES_TCL@" } @endif load [lindex $::argv 0] [lindex $::argv 1]; source [lindex $::argv 2]; # teaish/tester.tcl @if TEAISH_PKGINIT_TCL apply {{file} { set dir [file dirname $::argv0] source $file }} [join {@TEAISH_PKGINIT_TCL@}] @endif @if TEAISH_TEST_TCL apply {{file} { # Populate state for [tester.tcl::teaish-build-flag*] array set ::teaish__BuildFlags @TEAISH__DEFINES_MAP@ set dir [file normalize [file dirname $file]] #test-fail "Just testing" source $file }} [join {@TEAISH_TEST_TCL@}] @else # TEAISH_TEST_TCL # No $TEAISH_TEST_TCL provided, so here's a default test which simply # loads the extension. puts {Extension @TEAISH_NAME@ @TEAISH_VERSION@ successfully loaded from @TEAISH_TESTER_TCL@} @endif |