Mercurial
comparison third_party/sqlite3/autosetup/teaish/core.tcl @ 167:589bab390fb4
[ThirdParty] Added sqlite3 to the third_party.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 19 Jan 2026 16:28:45 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 166:78ea8d5ccc87 | 167:589bab390fb4 |
|---|---|
| 1 ######################################################################## | |
| 2 # 2025 April 5 | |
| 3 # | |
| 4 # The author disclaims copyright to this source code. In place of | |
| 5 # a legal notice, here is a blessing: | |
| 6 # | |
| 7 # * May you do good and not evil. | |
| 8 # * May you find forgiveness for yourself and forgive others. | |
| 9 # * May you share freely, never taking more than you give. | |
| 10 # | |
| 11 ######################################################################## | |
| 12 # ----- @module teaish.tcl ----- | |
| 13 # @section TEA-ish ((TCL Extension Architecture)-ish) | |
| 14 # | |
| 15 # Functions in this file with a prefix of teaish__ are | |
| 16 # private/internal APIs. Those with a prefix of teaish- are | |
| 17 # public APIs. | |
| 18 # | |
| 19 # Teaish has a hard dependency on proj.tcl, and any public API members | |
| 20 # of that module are considered legal for use by teaish extensions. | |
| 21 # | |
| 22 # Project home page: https://fossil.wanderinghorse.net/r/teaish | |
| 23 | |
| 24 use proj | |
| 25 | |
| 26 # | |
| 27 # API-internal settings and shared state. | |
| 28 array set teaish__Config [proj-strip-hash-comments { | |
| 29 # | |
| 30 # Teaish's version number, not to be confused with | |
| 31 # teaish__PkgInfo(-version). | |
| 32 # | |
| 33 version 0.1-beta | |
| 34 | |
| 35 # set to 1 to enable some internal debugging output | |
| 36 debug-enabled 0 | |
| 37 | |
| 38 # | |
| 39 # 0 = don't yet have extension's pkgindex | |
| 40 # 0x01 = found TEAISH_EXT_DIR/pkgIndex.tcl.in | |
| 41 # 0x02 = found srcdir/pkgIndex.tcl.in | |
| 42 # 0x10 = found TEAISH_EXT_DIR/pkgIndex.tcl (static file) | |
| 43 # 0x20 = static-pkgIndex.tcl pragma: behave as if 0x10 | |
| 44 # 0x100 = disabled by -tm.tcl.in | |
| 45 # 0x200 = disabled by -tm.tcl | |
| 46 # | |
| 47 # Reminder: it's significant that the bottom 4 bits be | |
| 48 # cases where teaish manages ./pkgIndex.tcl. | |
| 49 # | |
| 50 pkgindex-policy 0 | |
| 51 | |
| 52 # | |
| 53 # The pkginit counterpart of pkgindex-policy: | |
| 54 # | |
| 55 # 0 = no pkginit | |
| 56 # 0x01 = found default X.in: generate X from X.in | |
| 57 # 0x10 = found static pkginit file X | |
| 58 # 0x02 = user-provided X.in generates ./X. | |
| 59 # 0x20 = user-provided static pkginit file X | |
| 60 # | |
| 61 # The 0x0f bits indicate that teaish is responsible for cleaning up | |
| 62 # the (generated) pkginit file. | |
| 63 # | |
| 64 pkginit-policy 0 | |
| 65 # | |
| 66 # 0 = no tm.tcl | |
| 67 # 0x01 = tm.tcl.in | |
| 68 # 0x10 = static tm.tcl | |
| 69 tm-policy 0 | |
| 70 | |
| 71 # | |
| 72 # If 1+ then teaish__verbose will emit messages. | |
| 73 # | |
| 74 verbose 0 | |
| 75 | |
| 76 # | |
| 77 # Mapping of pkginfo -flags to their TEAISH_xxx define (if any). | |
| 78 # This must not be modified after initialization. | |
| 79 # | |
| 80 pkginfo-f2d { | |
| 81 -name TEAISH_NAME | |
| 82 -name.dist TEAISH_DIST_NAME | |
| 83 -name.pkg TEAISH_PKGNAME | |
| 84 -version TEAISH_VERSION | |
| 85 -libDir TEAISH_LIBDIR_NAME | |
| 86 -loadPrefix TEAISH_LOAD_PREFIX | |
| 87 -vsatisfies TEAISH_VSATISFIES | |
| 88 -pkgInit.tcl TEAISH_PKGINIT_TCL | |
| 89 -pkgInit.tcl.in TEAISH_PKGINIT_TCL_IN | |
| 90 -url TEAISH_URL | |
| 91 -tm.tcl TEAISH_TM_TCL | |
| 92 -tm.tcl.in TEAISH_TM_TCL_IN | |
| 93 -options {} | |
| 94 -pragmas {} | |
| 95 -src {} | |
| 96 } | |
| 97 | |
| 98 # | |
| 99 # Queues for use with teaish-checks-queue and teaish-checks-run. | |
| 100 # | |
| 101 queued-checks-pre {} | |
| 102 queued-checks-post {} | |
| 103 | |
| 104 # Whether or not "make dist" parts are enabled. They get enabled | |
| 105 # when building from an extension's dir, disabled when building | |
| 106 # elsewhere. | |
| 107 dist-enabled 1 | |
| 108 # Whether or not "make install" parts are enabled. By default | |
| 109 # they are, but we have a single use case where they're | |
| 110 # both unnecessary and unhelpful, so... | |
| 111 install-enabled 1 | |
| 112 | |
| 113 # By default we enable compilation of a native extension but if the | |
| 114 # extension has no native code or the user wants to take that over | |
| 115 # via teaish.make.in or provide a script-only extension, we will | |
| 116 # elide the default compilation rules if this is 0. | |
| 117 dll-enabled 1 | |
| 118 | |
| 119 # Files to include in the "make dist" bundle. | |
| 120 dist-files {} | |
| 121 | |
| 122 # List of source files for the extension. | |
| 123 extension-src {} | |
| 124 | |
| 125 # Path to the teaish.tcl file. | |
| 126 teaish.tcl {} | |
| 127 | |
| 128 # Dir where teaish.tcl is found. | |
| 129 extension-dir {} | |
| 130 | |
| 131 # Whether the generates TEASH_VSATISFIES_CODE should error out on a | |
| 132 # satisfies error. If 0, it uses return instead of error. | |
| 133 vsatisfies-error 1 | |
| 134 | |
| 135 # Whether or not to allow a "full dist" - a "make dist" build which | |
| 136 # includes both the extension and teaish. By default this is only on | |
| 137 # if the extension dir is teaish's dir. | |
| 138 dist-full-enabled 0 | |
| 139 }] | |
| 140 set teaish__Config(core-dir) $::autosetup(libdir)/teaish | |
| 141 | |
| 142 # | |
| 143 # Array of info managed by teaish-pkginfo-get and friends. Has the | |
| 144 # same set of keys as $teaish__Config(pkginfo-f2d). | |
| 145 # | |
| 146 array set teaish__PkgInfo {} | |
| 147 | |
| 148 # | |
| 149 # Runs {*}$args if $lvl is <= the current verbosity level, else it has | |
| 150 # no side effects. | |
| 151 # | |
| 152 proc teaish__verbose {lvl args} { | |
| 153 if {$lvl <= $::teaish__Config(verbose)} { | |
| 154 {*}$args | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 # | |
| 159 # @teaish-argv-has flags... | |
| 160 # | |
| 161 # Returns true if any arg in $::argv matches any of the given globs, | |
| 162 # else returns false. | |
| 163 # | |
| 164 proc teaish-argv-has {args} { | |
| 165 foreach glob $args { | |
| 166 foreach arg $::argv { | |
| 167 if {[string match $glob $arg]} { | |
| 168 return 1 | |
| 169 } | |
| 170 } | |
| 171 } | |
| 172 return 0 | |
| 173 } | |
| 174 | |
| 175 if {[teaish-argv-has --teaish-verbose --t-v]} { | |
| 176 # Check this early so that we can use verbose-only messages in the | |
| 177 # pre-options-parsing steps. | |
| 178 set ::teaish__Config(verbose) 1 | |
| 179 #teaish__verbose 1 msg-result "--teaish-verbose activated" | |
| 180 } | |
| 181 | |
| 182 msg-quiet use system ; # Outputs "Host System" and "Build System" lines | |
| 183 if {"--help" ni $::argv} { | |
| 184 teaish__verbose 1 msg-result "TEA(ish) Version = $::teaish__Config(version)" | |
| 185 teaish__verbose 1 msg-result "Source dir = $::autosetup(srcdir)" | |
| 186 teaish__verbose 1 msg-result "Build dir = $::autosetup(builddir)" | |
| 187 } | |
| 188 | |
| 189 # | |
| 190 # @teaish-configure-core | |
| 191 # | |
| 192 # Main entry point for the TEA-ish configure process. auto.def's primary | |
| 193 # (ideally only) job should be to call this. | |
| 194 # | |
| 195 proc teaish-configure-core {} { | |
| 196 proj-tweak-default-env-dirs | |
| 197 | |
| 198 set ::teaish__Config(install-mode) [teaish-argv-has --teaish-install*] | |
| 199 set ::teaish__Config(create-ext-mode) \ | |
| 200 [teaish-argv-has --teaish-create-extension=* --t-c-e=*] | |
| 201 set gotExt 0; # True if an extension config is found | |
| 202 if {!$::teaish__Config(create-ext-mode) | |
| 203 && !$::teaish__Config(install-mode)} { | |
| 204 # Don't look for an extension if we're in --t-c-e or --t-i mode | |
| 205 set gotExt [teaish__find_extension] | |
| 206 } | |
| 207 | |
| 208 # | |
| 209 # Set up the core --flags. This needs to come before teaish.tcl is | |
| 210 # sourced so that that file can use teaish-pkginfo-set to append | |
| 211 # options. | |
| 212 # | |
| 213 options-add [proj-strip-hash-comments { | |
| 214 with-tcl:DIR | |
| 215 => {Directory containing tclConfig.sh or a directory one level up from | |
| 216 that, from which we can derive a directory containing tclConfig.sh. | |
| 217 Defaults to the $TCL_HOME environment variable.} | |
| 218 | |
| 219 with-tclsh:PATH | |
| 220 => {Full pathname of tclsh to use. It is used for trying to find | |
| 221 tclConfig.sh. Warning: if its containing dir has multiple tclsh | |
| 222 versions, it may select the wrong tclConfig.sh! | |
| 223 Defaults to the $TCLSH environment variable.} | |
| 224 | |
| 225 tcl-stubs=0 => {Enable use of Tcl stubs library.} | |
| 226 | |
| 227 # TEA has --with-tclinclude but it appears to only be useful for | |
| 228 # building an extension against an uninstalled copy of TCL's own | |
| 229 # source tree. The policy here is that either we get that info | |
| 230 # from tclConfig.sh or we give up. | |
| 231 # | |
| 232 # with-tclinclude:DIR | |
| 233 # => {Specify the directory which contains the tcl.h. This should not | |
| 234 # normally be required, as that information comes from tclConfig.sh.} | |
| 235 | |
| 236 # We _generally_ want to reduce the possibility of flag collisions with | |
| 237 # extensions, and thus use a teaish-... prefix on most flags. However, | |
| 238 # --teaish-extension-dir is frequently needed, so... | |
| 239 # | |
| 240 # As of this spontaneous moment, we'll settle on using --t-A-X to | |
| 241 # abbreviate --teaish-A...-X... flags when doing so is | |
| 242 # unambiguous... | |
| 243 ted: t-e-d: | |
| 244 teaish-extension-dir:DIR | |
| 245 => {Looks for an extension in the given directory instead of the current | |
| 246 dir.} | |
| 247 | |
| 248 t-c-e: | |
| 249 teaish-create-extension:TARGET_DIRECTORY | |
| 250 => {Writes stub files for creating an extension. Will refuse to overwrite | |
| 251 existing files without --teaish-force.} | |
| 252 | |
| 253 t-f | |
| 254 teaish-force | |
| 255 => {Has a context-dependent meaning (autosetup defines --force for its | |
| 256 own use).} | |
| 257 | |
| 258 t-d-d | |
| 259 teaish-dump-defines | |
| 260 => {Dump all configure-defined vars to config.defines.txt} | |
| 261 | |
| 262 t-v:=0 | |
| 263 teaish-verbose:=0 | |
| 264 => {Enable more (often extraneous) messages from the teaish core.} | |
| 265 | |
| 266 t-d | |
| 267 teaish-debug=0 => {Enable teaish-specific debug output} | |
| 268 | |
| 269 t-i | |
| 270 teaish-install:=auto | |
| 271 => {Installs a copy of teaish, including autosetup, to the target dir. | |
| 272 When used with --teaish-create-extension=DIR, a value of "auto" | |
| 273 (no no value) will inherit that directory.} | |
| 274 | |
| 275 #TODO: --teaish-install-extension:=dir as short for | |
| 276 # --t-c-e=dir --t-i | |
| 277 | |
| 278 t-e-p: | |
| 279 teaish-extension-pkginfo:pkginfo | |
| 280 => {For use with --teaish-create-extension. If used, it must be a | |
| 281 list of arguments for use with teaish-pkginfo-set, e.g. | |
| 282 --teaish-extension-pkginfo="-name Foo -version 2.3"} | |
| 283 | |
| 284 t-v-c | |
| 285 teaish-vsatisfies-check=1 | |
| 286 => {Disable the configure-time "vsatisfies" check on the target tclsh.} | |
| 287 | |
| 288 }]; # main options. | |
| 289 | |
| 290 if {$gotExt} { | |
| 291 # We found an extension. Source it... | |
| 292 set ttcl $::teaish__Config(teaish.tcl) | |
| 293 proj-assert {"" ne [teaish-pkginfo-get -name]} | |
| 294 proj-assert {[file exists $ttcl]} \ | |
| 295 "Expecting to have found teaish.(tcl|config) by now" | |
| 296 if {[string match *.tcl $ttcl]} { | |
| 297 uplevel 1 {source $::teaish__Config(teaish.tcl)} | |
| 298 } else { | |
| 299 teaish-pkginfo-set {*}[proj-file-content -trim $ttcl] | |
| 300 } | |
| 301 unset ttcl | |
| 302 # Set up some default values if the extension did not set them. | |
| 303 # This must happen _after_ it's sourced but before | |
| 304 # teaish-configure is called. | |
| 305 array set f2d $::teaish__Config(pkginfo-f2d) | |
| 306 foreach {pflag key type val} { | |
| 307 - TEAISH_CFLAGS -v "" | |
| 308 - TEAISH_LDFLAGS -v "" | |
| 309 - TEAISH_MAKEFILE -v "" | |
| 310 - TEAISH_MAKEFILE_CODE -v "" | |
| 311 - TEAISH_MAKEFILE_IN -v "" | |
| 312 - TEAISH_PKGINDEX_TCL -v "" | |
| 313 - TEAISH_PKGINDEX_TCL_IN -v "" | |
| 314 - TEAISH_PKGINIT_TCL -v "" | |
| 315 - TEAISH_PKGINIT_TCL_IN -v "" | |
| 316 - TEAISH_PKGINIT_TCL_TAIL -v "" | |
| 317 - TEAISH_TEST_TCL -v "" | |
| 318 - TEAISH_TEST_TCL_IN -v "" | |
| 319 | |
| 320 -version - -v 0.0.0 | |
| 321 -name.pkg - -e {set ::teaish__PkgInfo(-name)} | |
| 322 -name.dist - -e {set ::teaish__PkgInfo(-name)} | |
| 323 -libDir - -e { | |
| 324 join [list \ | |
| 325 $::teaish__PkgInfo(-name.pkg) \ | |
| 326 $::teaish__PkgInfo(-version)] "" | |
| 327 } | |
| 328 -loadPrefix - -e { | |
| 329 string totitle $::teaish__PkgInfo(-name.pkg) | |
| 330 } | |
| 331 -vsatisfies - -v {{Tcl 8.5-}} | |
| 332 -pkgInit.tcl - -v "" | |
| 333 -pkgInit.tcl.in - -v "" | |
| 334 -url - -v "" | |
| 335 -tm.tcl - -v "" | |
| 336 -tm.tcl.in - -v "" | |
| 337 -src - -v "" | |
| 338 } { | |
| 339 #proj-assert 0 {Just testing} | |
| 340 set isPIFlag [expr {"-" ne $pflag}] | |
| 341 if {$isPIFlag} { | |
| 342 if {[info exists ::teaish__PkgInfo($pflag)]} { | |
| 343 # Was already set - skip it. | |
| 344 continue; | |
| 345 } | |
| 346 proj-assert {{-} eq $key};# "Unexpected pflag=$pflag key=$key type=$type val=$val" | |
| 347 set key $f2d($pflag) | |
| 348 } | |
| 349 if {"" ne $key} { | |
| 350 if {"<nope>" ne [get-define $key "<nope>"]} { | |
| 351 # Was already set - skip it. | |
| 352 continue | |
| 353 } | |
| 354 } | |
| 355 switch -exact -- $type { | |
| 356 -v {} | |
| 357 -e { set val [eval $val] } | |
| 358 default { proj-error "Invalid type flag: $type" } | |
| 359 } | |
| 360 #puts "***** defining default $pflag $key {$val} isPIFlag=$isPIFlag" | |
| 361 if {$key ne ""} { | |
| 362 define $key $val | |
| 363 } | |
| 364 if {$isPIFlag} { | |
| 365 set ::teaish__PkgInfo($pflag) $val | |
| 366 } | |
| 367 } | |
| 368 unset isPIFlag pflag key type val | |
| 369 array unset f2d | |
| 370 }; # sourcing extension's teaish.tcl | |
| 371 | |
| 372 if {[llength [info proc teaish-options]] > 0} { | |
| 373 # Add options defined by teaish-options, which is assumed to be | |
| 374 # imported via [teaish-get -teaish-tcl]. | |
| 375 set o [teaish-options] | |
| 376 if {"" ne $o} { | |
| 377 options-add $o | |
| 378 } | |
| 379 } | |
| 380 #set opts [proj-options-combine] | |
| 381 #lappend opts teaish-debug => {x}; #testing dupe entry handling | |
| 382 if {[catch {options {}} msg xopts]} { | |
| 383 # Workaround for <https://github.com/msteveb/autosetup/issues/73> | |
| 384 # where [options] behaves oddly on _some_ TCL builds when it's | |
| 385 # called from deeper than the global scope. | |
| 386 dict incr xopts -level | |
| 387 return {*}$xopts $msg | |
| 388 } | |
| 389 | |
| 390 proj-xfer-options-aliases { | |
| 391 t-c-e => teaish-create-extension | |
| 392 t-d => teaish-debug | |
| 393 t-d-d => teaish-dump-defines | |
| 394 ted => teaish-extension-dir | |
| 395 t-e-d => teaish-extension-dir | |
| 396 t-e-p => teaish-extension-pkginfo | |
| 397 t-f => teaish-force | |
| 398 t-i => teaish-install | |
| 399 t-v => teaish-verbose | |
| 400 t-v-c => teaish-vsatisfies-check | |
| 401 } | |
| 402 | |
| 403 scan [opt-val teaish-verbose 0] %d ::teaish__Config(verbose) | |
| 404 set ::teaish__Config(debug-enabled) [opt-bool teaish-debug] | |
| 405 | |
| 406 set exitEarly 0 | |
| 407 if {[proj-opt-was-provided teaish-create-extension]} { | |
| 408 teaish__create_extension [opt-val teaish-create-extension] | |
| 409 incr exitEarly | |
| 410 } | |
| 411 if {$::teaish__Config(install-mode)} { | |
| 412 teaish__install | |
| 413 incr exitEarly | |
| 414 } | |
| 415 | |
| 416 if {$exitEarly} { | |
| 417 file delete -force config.log | |
| 418 return | |
| 419 } | |
| 420 proj-assert {1==$gotExt} "Else we cannot have gotten this far" | |
| 421 | |
| 422 teaish__configure_phase1 | |
| 423 } | |
| 424 | |
| 425 | |
| 426 # | |
| 427 # Internal config-time debugging output routine. It is not legal to | |
| 428 # call this from the global scope. | |
| 429 # | |
| 430 proc teaish-debug {msg} { | |
| 431 if {$::teaish__Config(debug-enabled)} { | |
| 432 puts stderr [proj-bold "** DEBUG: \[[proj-scope 1]\]: $msg"] | |
| 433 } | |
| 434 } | |
| 435 | |
| 436 # | |
| 437 # Runs "phase 1" of the configuration, immediately after processing | |
| 438 # --flags. This is what will import the client-defined teaish.tcl. | |
| 439 # | |
| 440 proc teaish__configure_phase1 {} { | |
| 441 msg-result \ | |
| 442 [join [list "Configuring build of Tcl extension" \ | |
| 443 [proj-bold [teaish-pkginfo-get -name] \ | |
| 444 [teaish-pkginfo-get -version]] "..."]] | |
| 445 | |
| 446 uplevel 1 { | |
| 447 use cc cc-db cc-shared cc-lib; # pkg-config | |
| 448 } | |
| 449 teaish__check_tcl | |
| 450 apply {{} { | |
| 451 # | |
| 452 # If --prefix or --exec-prefix are _not_ provided, use their | |
| 453 # TCL_... counterpart from tclConfig.sh. Caveat: by the time we can | |
| 454 # reach this point, autosetup's system.tcl will have already done | |
| 455 # some non-trivial amount of work with these to create various | |
| 456 # derived values from them, so we temporarily end up with a mishmash | |
| 457 # of autotools-compatibility var values. That will be straightened | |
| 458 # out in the final stage of the configure script via | |
| 459 # [proj-remap-autoconf-dir-vars]. | |
| 460 # | |
| 461 foreach {flag uflag tclVar} { | |
| 462 prefix prefix TCL_PREFIX | |
| 463 exec-prefix exec_prefix TCL_EXEC_PREFIX | |
| 464 } { | |
| 465 if {![proj-opt-was-provided $flag]} { | |
| 466 if {"exec-prefix" eq $flag} { | |
| 467 # If --exec-prefix was not used, ensure that --exec-prefix | |
| 468 # derives from the --prefix we may have just redefined. | |
| 469 set v {${prefix}} | |
| 470 } else { | |
| 471 set v [get-define $tclVar "???"] | |
| 472 teaish__verbose 1 msg-result "Using \$$tclVar for --$flag=$v" | |
| 473 } | |
| 474 proj-assert {"???" ne $v} "Expecting teaish__check_tcl to have defined $tclVar" | |
| 475 #puts "*** $flag $uflag $tclVar = $v" | |
| 476 proj-opt-set $flag $v | |
| 477 define $uflag $v | |
| 478 | |
| 479 # ^^^ As of here, all autotools-compatibility vars which derive | |
| 480 # from --$flag, e.g. --libdir, still derive from the default | |
| 481 # --$flag value which was active when system.tcl was | |
| 482 # included. So long as those flags are not explicitly passed to | |
| 483 # the configure script, those will be straightened out via | |
| 484 # [proj-remap-autoconf-dir-vars]. | |
| 485 } | |
| 486 } | |
| 487 }}; # --[exec-]prefix defaults | |
| 488 teaish__check_common_bins | |
| 489 # | |
| 490 # Set up library file names | |
| 491 # | |
| 492 proj-file-extensions | |
| 493 teaish__define_pkginfo_derived * | |
| 494 | |
| 495 teaish-checks-run -pre | |
| 496 if {[llength [info proc teaish-configure]] > 0} { | |
| 497 # teaish-configure is assumed to be imported via | |
| 498 # teaish.tcl | |
| 499 teaish-configure | |
| 500 } | |
| 501 teaish-checks-run -post | |
| 502 | |
| 503 define TEAISH_USE_STUBS [opt-bool tcl-stubs] | |
| 504 | |
| 505 apply {{} { | |
| 506 # Set up "vsatisfies" code for pkgIndex.tcl.in, | |
| 507 # _teaish.tester.tcl.in, and for a configure-time check. We would | |
| 508 # like to put this before [teaish-checks-run -pre] but it's | |
| 509 # marginally conceivable that a client may need to dynamically | |
| 510 # calculate the vsatisfies and set it via [teaish-configure]. | |
| 511 set vs [get-define TEAISH_VSATISFIES ""] | |
| 512 if {"" eq $vs} return | |
| 513 set code {} | |
| 514 set n 0 | |
| 515 # Treat $vs as a list-of-lists {{Tcl 8.5-} {Foo 1.0- -3.0} ...} | |
| 516 # and generate Tcl which will run package vsatisfies tests with | |
| 517 # that info. | |
| 518 foreach pv $vs { | |
| 519 set n [llength $pv] | |
| 520 if {$n < 2} { | |
| 521 proj-error "-vsatisfies: {$pv} appears malformed. Whole list is: $vs" | |
| 522 } | |
| 523 set pkg [lindex $pv 0] | |
| 524 set vcheck {} | |
| 525 for {set i 1} {$i < $n} {incr i} { | |
| 526 lappend vcheck [lindex $pv $i] | |
| 527 } | |
| 528 if {[opt-bool teaish-vsatisfies-check]} { | |
| 529 set tclsh [get-define TCLSH_CMD] | |
| 530 set vsat "package vsatisfies \[ package provide $pkg \] $vcheck" | |
| 531 set vputs "puts \[ $vsat \]" | |
| 532 #puts "*** vputs = $vputs" | |
| 533 scan [exec echo $vputs | $tclsh] %d vvcheck | |
| 534 if {![info exists vvcheck] || 0 == $vvcheck} { | |
| 535 proj-fatal -up $tclsh "check failed:" $vsat | |
| 536 } | |
| 537 } | |
| 538 if {$::teaish__Config(vsatisfies-error)} { | |
| 539 set vunsat \ | |
| 540 [list error [list Package \ | |
| 541 $::teaish__PkgInfo(-name) $::teaish__PkgInfo(-version) \ | |
| 542 requires $pv]] | |
| 543 } else { | |
| 544 set vunsat return | |
| 545 } | |
| 546 lappend code \ | |
| 547 [string trim [subst -nocommands \ | |
| 548 {if { ![package vsatisfies [package provide $pkg] $vcheck] } {\n $vunsat\n}}]] | |
| 549 }; # foreach pv | |
| 550 define TEAISH_VSATISFIES_CODE [join $code "\n"] | |
| 551 }}; # vsatisfies | |
| 552 | |
| 553 if {[proj-looks-like-windows]} { | |
| 554 # Without this, linking of an extension will not work on Cygwin or | |
| 555 # Msys2. | |
| 556 msg-result "Using USE_TCL_STUBS for Unix(ish)-on-Windows environment" | |
| 557 teaish-cflags-add -DUSE_TCL_STUBS=1 | |
| 558 } | |
| 559 | |
| 560 #define AS_LIBDIR $::autosetup(libdir) | |
| 561 define TEAISH_TESTUTIL_TCL $::teaish__Config(core-dir)/tester.tcl | |
| 562 | |
| 563 apply {{} { | |
| 564 # | |
| 565 # Ensure we have a pkgIndex.tcl and don't have a stale generated one | |
| 566 # when rebuilding for different --with-tcl=... values. | |
| 567 # | |
| 568 if {!$::teaish__Config(pkgindex-policy)} { | |
| 569 proj-error "Cannot determine which pkgIndex.tcl to use" | |
| 570 } | |
| 571 if {0x300 & $::teaish__Config(pkgindex-policy)} { | |
| 572 teaish__verbose 1 msg-result "pkgIndex disabled by -tm.tcl(.in)" | |
| 573 } else { | |
| 574 set tpi [proj-coalesce \ | |
| 575 [get-define TEAISH_PKGINDEX_TCL_IN] \ | |
| 576 [get-define TEAISH_PKGINDEX_TCL]] | |
| 577 proj-assert {$tpi ne ""} \ | |
| 578 "TEAISH_PKGINDEX_TCL should have been set up by now" | |
| 579 teaish__verbose 1 msg-result "Using pkgIndex from $tpi" | |
| 580 if {0x0f & $::teaish__Config(pkgindex-policy)} { | |
| 581 # Don't leave stale pkgIndex.tcl laying around yet don't delete | |
| 582 # or overwrite a user-managed static pkgIndex.tcl. | |
| 583 file delete -force -- [get-define TEAISH_PKGINDEX_TCL] | |
| 584 proj-dot-ins-append [get-define TEAISH_PKGINDEX_TCL_IN] | |
| 585 } else { | |
| 586 teaish-dist-add [file tail $tpi] | |
| 587 } | |
| 588 } | |
| 589 }}; # $::teaish__Config(pkgindex-policy) | |
| 590 | |
| 591 # | |
| 592 # Ensure we clean up TEAISH_PKGINIT_TCL if needed and @-process | |
| 593 # TEAISH_PKGINIT_TCL_IN if needed. | |
| 594 # | |
| 595 if {0x0f & $::teaish__Config(pkginit-policy)} { | |
| 596 file delete -force -- [get-define TEAISH_PKGINIT_TCL] | |
| 597 proj-dot-ins-append [get-define TEAISH_PKGINIT_TCL_IN] \ | |
| 598 [get-define TEAISH_PKGINIT_TCL] | |
| 599 } | |
| 600 if {0x0f & $::teaish__Config(tm-policy)} { | |
| 601 file delete -force -- [get-define TEAISH_TM_TCL] | |
| 602 proj-dot-ins-append [get-define TEAISH_TM_TCL_IN] | |
| 603 } | |
| 604 | |
| 605 apply {{} { | |
| 606 # Queue up any remaining dot-in files | |
| 607 set dotIns [list] | |
| 608 foreach {dIn => dOut} { | |
| 609 TEAISH_TESTER_TCL_IN => TEAISH_TESTER_TCL | |
| 610 TEAISH_TEST_TCL_IN => TEAISH_TEST_TCL | |
| 611 TEAISH_MAKEFILE_IN => TEAISH_MAKEFILE | |
| 612 } { | |
| 613 lappend dotIns [get-define $dIn ""] [get-define $dOut ""] | |
| 614 } | |
| 615 lappend dotIns $::autosetup(srcdir)/Makefile.in Makefile; # must be after TEAISH_MAKEFILE_IN. | |
| 616 # Much later: probably because of timestamps for deps purposes :-? | |
| 617 #puts "dotIns=$dotIns" | |
| 618 foreach {i o} $dotIns { | |
| 619 if {"" ne $i && "" ne $o} { | |
| 620 #puts " pre-dot-ins-append: \[$i\] -> \[$o\]" | |
| 621 proj-dot-ins-append $i $o | |
| 622 } | |
| 623 } | |
| 624 }} | |
| 625 | |
| 626 define TEAISH_DIST_FULL \ | |
| 627 [expr { | |
| 628 $::teaish__Config(dist-enabled) | |
| 629 && $::teaish__Config(dist-full-enabled) | |
| 630 }] | |
| 631 | |
| 632 define TEAISH_AUTOSETUP_DIR $::teaish__Config(core-dir) | |
| 633 define TEAISH_ENABLE_DIST $::teaish__Config(dist-enabled) | |
| 634 define TEAISH_ENABLE_INSTALL $::teaish__Config(install-enabled) | |
| 635 define TEAISH_ENABLE_DLL $::teaish__Config(dll-enabled) | |
| 636 define TEAISH_TCL $::teaish__Config(teaish.tcl) | |
| 637 | |
| 638 define TEAISH_DIST_FILES [join $::teaish__Config(dist-files)] | |
| 639 define TEAISH_EXT_DIR [join $::teaish__Config(extension-dir)] | |
| 640 define TEAISH_EXT_SRC [join $::teaish__Config(extension-src)] | |
| 641 proj-setup-autoreconfig TEAISH_AUTORECONFIG | |
| 642 foreach f { | |
| 643 TEAISH_CFLAGS | |
| 644 TEAISH_LDFLAGS | |
| 645 } { | |
| 646 # Ensure that any of these lists are flattened | |
| 647 define $f [join [get-define $f]] | |
| 648 } | |
| 649 proj-remap-autoconf-dir-vars | |
| 650 set tdefs [teaish__defines_to_list] | |
| 651 define TEAISH__DEFINES_MAP $tdefs; # injected into _teaish.tester.tcl | |
| 652 | |
| 653 # | |
| 654 # NO [define]s after this point! | |
| 655 # | |
| 656 proj-if-opt-truthy teaish-dump-defines { | |
| 657 proj-file-write config.defines.txt $tdefs | |
| 658 } | |
| 659 proj-dot-ins-process -validate | |
| 660 | |
| 661 }; # teaish__configure_phase1 | |
| 662 | |
| 663 # | |
| 664 # Run checks for required binaries. | |
| 665 # | |
| 666 proc teaish__check_common_bins {} { | |
| 667 if {"" eq [proj-bin-define install]} { | |
| 668 proj-warn "Cannot find install binary, so 'make install' will not work." | |
| 669 define BIN_INSTALL false | |
| 670 } | |
| 671 if {"" eq [proj-bin-define zip]} { | |
| 672 proj-warn "Cannot find zip, so 'make dist.zip' will not work." | |
| 673 } | |
| 674 if {"" eq [proj-bin-define tar]} { | |
| 675 proj-warn "Cannot find tar, so 'make dist.tgz' will not work." | |
| 676 } | |
| 677 } | |
| 678 | |
| 679 # | |
| 680 # TCL... | |
| 681 # | |
| 682 # teaish__check_tcl performs most of the --with-tcl and --with-tclsh | |
| 683 # handling. Some related bits and pieces are performed before and | |
| 684 # after that function is called. | |
| 685 # | |
| 686 # Important [define]'d vars: | |
| 687 # | |
| 688 # - TCLSH_CMD is the path to the canonical tclsh or "". | |
| 689 # | |
| 690 # - TCL_CONFIG_SH is the path to tclConfig.sh or "". | |
| 691 # | |
| 692 # - TCLLIBDIR is the dir to which the extension library gets | |
| 693 # - installed. | |
| 694 # | |
| 695 proc teaish__check_tcl {} { | |
| 696 define TCLSH_CMD false ; # Significant is that it exits with non-0 | |
| 697 define TCLLIBDIR "" ; # Installation dir for TCL extension lib | |
| 698 define TCL_CONFIG_SH ""; # full path to tclConfig.sh | |
| 699 | |
| 700 # Clear out all vars which would harvest from tclConfig.sh so that | |
| 701 # the late-config validation of @VARS@ works even if --disable-tcl | |
| 702 # is used. | |
| 703 proj-tclConfig-sh-to-autosetup "" | |
| 704 | |
| 705 # TODO: better document the steps this is taking. | |
| 706 set srcdir $::autosetup(srcdir) | |
| 707 msg-result "Checking for a suitable tcl... " | |
| 708 set use_tcl 1 | |
| 709 set withSh [opt-val with-tclsh [proj-get-env TCLSH]] | |
| 710 set tclHome [opt-val with-tcl [proj-get-env TCL_HOME]] | |
| 711 if {[string match */lib $tclHome]} { | |
| 712 # TEA compatibility kludge: its --with-tcl wants the lib | |
| 713 # dir containing tclConfig.sh. | |
| 714 #proj-warn "Replacing --with-tcl=$tclHome for TEA compatibility" | |
| 715 regsub {/lib^} $tclHome "" tclHome | |
| 716 msg-result "NOTE: stripped /lib suffix from --with-tcl=$tclHome (a TEA-ism)" | |
| 717 } | |
| 718 if {0} { | |
| 719 # This misinteracts with the $TCL_PREFIX default: it will use the | |
| 720 # autosetup-defined --prefix default | |
| 721 if {"prefix" eq $tclHome} { | |
| 722 set tclHome [get-define prefix] | |
| 723 } | |
| 724 } | |
| 725 teaish-debug "use_tcl ${use_tcl}" | |
| 726 teaish-debug "withSh=${withSh}" | |
| 727 teaish-debug "tclHome=$tclHome" | |
| 728 if {"" eq $withSh && "" eq $tclHome} { | |
| 729 # If neither --with-tclsh nor --with-tcl are provided, try to find | |
| 730 # a workable tclsh. | |
| 731 set withSh [proj-first-bin-of tclsh9.1 tclsh9.0 tclsh8.6 tclsh] | |
| 732 teaish-debug "withSh=${withSh}" | |
| 733 } | |
| 734 | |
| 735 set doConfigLookup 1 ; # set to 0 to test the tclConfig.sh-not-found cases | |
| 736 if {"" ne $withSh} { | |
| 737 # --with-tclsh was provided or found above. Validate it and use it | |
| 738 # to trump any value passed via --with-tcl=DIR. | |
| 739 if {![file-isexec $withSh]} { | |
| 740 proj-error "TCL shell $withSh is not executable" | |
| 741 } else { | |
| 742 define TCLSH_CMD $withSh | |
| 743 #msg-result "Using tclsh: $withSh" | |
| 744 } | |
| 745 if {$doConfigLookup && | |
| 746 [catch {exec $withSh $::autosetup(libdir)/find_tclconfig.tcl} result] == 0} { | |
| 747 set tclHome $result | |
| 748 } | |
| 749 if {"" ne $tclHome && [file isdirectory $tclHome]} { | |
| 750 teaish__verbose 1 msg-result "$withSh recommends the tclConfig.sh from $tclHome" | |
| 751 } else { | |
| 752 proj-warn "$withSh is unable to recommend a tclConfig.sh" | |
| 753 set use_tcl 0 | |
| 754 } | |
| 755 } | |
| 756 set cfg "" | |
| 757 set tclSubdirs {tcl9.1 tcl9.0 tcl8.6 tcl8.5 lib} | |
| 758 while {$use_tcl} { | |
| 759 if {"" ne $tclHome} { | |
| 760 # Ensure that we can find tclConfig.sh under ${tclHome}/... | |
| 761 if {$doConfigLookup} { | |
| 762 if {[file readable "${tclHome}/tclConfig.sh"]} { | |
| 763 set cfg "${tclHome}/tclConfig.sh" | |
| 764 } else { | |
| 765 foreach i $tclSubdirs { | |
| 766 if {[file readable "${tclHome}/$i/tclConfig.sh"]} { | |
| 767 set cfg "${tclHome}/$i/tclConfig.sh" | |
| 768 break | |
| 769 } | |
| 770 } | |
| 771 } | |
| 772 } | |
| 773 if {"" eq $cfg} { | |
| 774 proj-error "No tclConfig.sh found under ${tclHome}" | |
| 775 } | |
| 776 } else { | |
| 777 # If we have not yet found a tclConfig.sh file, look in $libdir | |
| 778 # which is set automatically by autosetup or via the --prefix | |
| 779 # command-line option. See | |
| 780 # https://sqlite.org/forum/forumpost/e04e693439a22457 | |
| 781 set libdir [get-define libdir] | |
| 782 if {[file readable "${libdir}/tclConfig.sh"]} { | |
| 783 set cfg "${libdir}/tclConfig.sh" | |
| 784 } else { | |
| 785 foreach i $tclSubdirs { | |
| 786 if {[file readable "${libdir}/$i/tclConfig.sh"]} { | |
| 787 set cfg "${libdir}/$i/tclConfig.sh" | |
| 788 break | |
| 789 } | |
| 790 } | |
| 791 } | |
| 792 if {![file readable $cfg]} { | |
| 793 break | |
| 794 } | |
| 795 } | |
| 796 teaish__verbose 1 msg-result "Using tclConfig.sh = $cfg" | |
| 797 break | |
| 798 }; # while {$use_tcl} | |
| 799 define TCL_CONFIG_SH $cfg | |
| 800 # Export a subset of tclConfig.sh to the current TCL-space. If $cfg | |
| 801 # is an empty string, this emits empty-string entries for the | |
| 802 # various options we're interested in. | |
| 803 proj-tclConfig-sh-to-autosetup $cfg | |
| 804 | |
| 805 if {"" eq $withSh && $cfg ne ""} { | |
| 806 # We have tclConfig.sh but no tclsh. Attempt to locate a tclsh | |
| 807 # based on info from tclConfig.sh. | |
| 808 set tclExecPrefix [get-define TCL_EXEC_PREFIX] | |
| 809 proj-assert {"" ne $tclExecPrefix} | |
| 810 set tryThese [list \ | |
| 811 $tclExecPrefix/bin/tclsh[get-define TCL_VERSION] \ | |
| 812 $tclExecPrefix/bin/tclsh ] | |
| 813 foreach trySh $tryThese { | |
| 814 if {[file-isexec $trySh]} { | |
| 815 set withSh $trySh | |
| 816 break | |
| 817 } | |
| 818 } | |
| 819 if {![file-isexec $withSh]} { | |
| 820 proj-warn "Cannot find a usable tclsh (tried: $tryThese)" | |
| 821 } | |
| 822 } | |
| 823 define TCLSH_CMD $withSh | |
| 824 if {$use_tcl} { | |
| 825 # Set up the TCLLIBDIR | |
| 826 set tcllibdir [get-env TCLLIBDIR ""] | |
| 827 set extDirName [teaish-pkginfo-get -libDir] | |
| 828 if {"" eq $tcllibdir} { | |
| 829 # Attempt to extract TCLLIBDIR from TCL's $auto_path | |
| 830 if {"" ne $withSh && | |
| 831 [catch {exec echo "puts stdout \$auto_path" | "$withSh"} result] == 0} { | |
| 832 foreach i $result { | |
| 833 if {![string match //zip* $i] && [file isdirectory $i]} { | |
| 834 # isdirectory actually passes on //zipfs:/..., but those are | |
| 835 # useless for our purposes | |
| 836 set tcllibdir $i/$extDirName | |
| 837 break | |
| 838 } | |
| 839 } | |
| 840 } else { | |
| 841 proj-error "Cannot determine TCLLIBDIR." | |
| 842 } | |
| 843 } | |
| 844 define TCLLIBDIR $tcllibdir | |
| 845 }; # find TCLLIBDIR | |
| 846 | |
| 847 set gotSh [file-isexec $withSh] | |
| 848 set tmdir ""; # first tcl::tm::list entry | |
| 849 if {$gotSh} { | |
| 850 catch { | |
| 851 set tmli [exec echo {puts [tcl::tm::list]} | $withSh] | |
| 852 # Reminder: this list contains many names of dirs which do not | |
| 853 # exist but are legitimate. If we rely only on an is-dir check, | |
| 854 # we can end up not finding any of the many candidates. | |
| 855 set firstDir "" | |
| 856 foreach d $tmli { | |
| 857 if {"" eq $firstDir && ![string match //*:* $d]} { | |
| 858 # First non-VFS entry, e.g. not //zipfs: | |
| 859 set firstDir $d | |
| 860 } | |
| 861 if {[file isdirectory $d]} { | |
| 862 set tmdir $d | |
| 863 break | |
| 864 } | |
| 865 } | |
| 866 if {"" eq $tmdir} { | |
| 867 set tmdir $firstDir | |
| 868 } | |
| 869 }; # find tcl::tm path | |
| 870 } | |
| 871 define TEAISH_TCL_TM_DIR $tmdir | |
| 872 | |
| 873 # Finally, let's wrap up... | |
| 874 if {$gotSh} { | |
| 875 teaish__verbose 1 msg-result "Using tclsh = $withSh" | |
| 876 if {$cfg ne ""} { | |
| 877 define HAVE_TCL 1 | |
| 878 } else { | |
| 879 proj-warn "Found tclsh but no tclConfig.sh." | |
| 880 } | |
| 881 if {"" eq $tmdir} { | |
| 882 proj-warn "Did not find tcl::tm directory." | |
| 883 } | |
| 884 } | |
| 885 show-notices | |
| 886 # If TCL is not found: if it was explicitly requested then fail | |
| 887 # fatally, else just emit a warning. If we can find the APIs needed | |
| 888 # to generate a working JimTCL then that will suffice for build-time | |
| 889 # TCL purposes (see: proc sqlite-determine-codegen-tcl). | |
| 890 if {!$gotSh} { | |
| 891 proj-error "Did not find tclsh" | |
| 892 } elseif {"" eq $cfg} { | |
| 893 proj-indented-notice -error { | |
| 894 Cannot find a usable tclConfig.sh file. Use --with-tcl=DIR to | |
| 895 specify a directory near which tclConfig.sh can be found, or | |
| 896 --with-tclsh=/path/to/tclsh to allow the tclsh binary to locate | |
| 897 its tclConfig.sh, with the caveat that a symlink to tclsh, or | |
| 898 wrapper script around it, e.g. ~/bin/tclsh -> | |
| 899 $HOME/tcl/9.0/bin/tclsh9.1, may not work because tclsh emits | |
| 900 different library paths for the former than the latter. | |
| 901 } | |
| 902 } | |
| 903 msg-result "Using Tcl [get-define TCL_VERSION] from [get-define TCL_PREFIX]." | |
| 904 teaish__tcl_platform_quirks | |
| 905 }; # teaish__check_tcl | |
| 906 | |
| 907 # | |
| 908 # Perform last-minute platform-specific tweaks to account for quirks. | |
| 909 # | |
| 910 proc teaish__tcl_platform_quirks {} { | |
| 911 define TEAISH_POSTINST_PREREQUIRE "" | |
| 912 switch -glob -- [get-define host] { | |
| 913 *-haiku { | |
| 914 # Haiku's default TCLLIBDIR is "all wrong": it points to a | |
| 915 # read-only virtual filesystem mount-point. We bend it back to | |
| 916 # fit under $TCL_PACKAGE_PATH here. | |
| 917 foreach {k d} { | |
| 918 vj TCL_MAJOR_VERSION | |
| 919 vn TCL_MINOR_VERSION | |
| 920 pp TCL_PACKAGE_PATH | |
| 921 ld TCLLIBDIR | |
| 922 } { | |
| 923 set $k [get-define $d] | |
| 924 } | |
| 925 if {[string match /packages/* $ld]} { | |
| 926 set old $ld | |
| 927 set tail [file tail $ld] | |
| 928 if {8 == $vj} { | |
| 929 set ld "${pp}/tcl${vj}.${vn}/${tail}" | |
| 930 } else { | |
| 931 proj-assert {9 == $vj} | |
| 932 set ld "${pp}/${tail}" | |
| 933 } | |
| 934 define TCLLIBDIR $ld | |
| 935 # [load foo.so], without a directory part, does not work via | |
| 936 # automated tests on Haiku (but works when run | |
| 937 # manually). Similarly, the post-install [package require ...] | |
| 938 # test fails, presumably for a similar reason. We work around | |
| 939 # the former in _teaish.tester.tcl.in. We work around the | |
| 940 # latter by amending the post-install check's ::auto_path (in | |
| 941 # Makefile.in). This code MUST NOT contain any single-quotes. | |
| 942 define TEAISH_POSTINST_PREREQUIRE \ | |
| 943 [join [list set ::auto_path \ | |
| 944 \[ linsert \$::auto_path 0 $ld \] \; \ | |
| 945 ]] | |
| 946 proj-indented-notice [subst -nocommands -nobackslashes { | |
| 947 Haiku users take note: patching target installation dir to match | |
| 948 Tcl's home because Haiku's is not writable. | |
| 949 | |
| 950 Original : $old | |
| 951 Substitute: $ld | |
| 952 }] | |
| 953 } | |
| 954 } | |
| 955 } | |
| 956 }; # teaish__tcl_platform_quirks | |
| 957 | |
| 958 # | |
| 959 # Searches $::argv and/or the build dir and/or the source dir for | |
| 960 # teaish.tcl and friends. Fails if it cannot find teaish.tcl or if | |
| 961 # there are other irreconcilable problems. If it returns 0 then it did | |
| 962 # not find an extension but the --help flag was seen, in which case | |
| 963 # that's not an error. | |
| 964 # | |
| 965 # This does not _load_ the extension, it primarily locates the files | |
| 966 # which make up an extension and fills out no small amount of teaish | |
| 967 # state related to that. | |
| 968 # | |
| 969 proc teaish__find_extension {} { | |
| 970 proj-assert {!$::teaish__Config(install-mode)} | |
| 971 teaish__verbose 1 msg-result "Looking for teaish extension..." | |
| 972 | |
| 973 # Helper for the foreach loop below. | |
| 974 set checkTeaishTcl {{mustHave fid dir} { | |
| 975 set f [file join $dir $fid] | |
| 976 if {[file readable $f]} { | |
| 977 file-normalize $f | |
| 978 } elseif {$mustHave} { | |
| 979 proj-error "Missing required $dir/$fid" | |
| 980 } | |
| 981 }} | |
| 982 | |
| 983 # | |
| 984 # We have to handle some flags manually because the extension must | |
| 985 # be loaded before [options] is run (so that the extension can | |
| 986 # inject its own options). | |
| 987 # | |
| 988 set dirBld $::autosetup(builddir); # dir we're configuring under | |
| 989 set dirSrc $::autosetup(srcdir); # where teaish's configure script lives | |
| 990 set extT ""; # teaish.tcl | |
| 991 set largv {}; # rewritten $::argv | |
| 992 set gotHelpArg 0; # got the --help | |
| 993 foreach arg $::argv { | |
| 994 #puts "*** arg=$arg" | |
| 995 switch -glob -- $arg { | |
| 996 --ted=* - | |
| 997 --t-e-d=* - | |
| 998 --teaish-extension-dir=* { | |
| 999 # Ensure that $extD refers to a directory and contains a | |
| 1000 # teaish.tcl. | |
| 1001 regexp -- {--[^=]+=(.+)} $arg - extD | |
| 1002 set extD [file-normalize $extD] | |
| 1003 if {![file isdirectory $extD]} { | |
| 1004 proj-error "--teaish-extension-dir value is not a directory: $extD" | |
| 1005 } | |
| 1006 set extT [apply $checkTeaishTcl 0 teaish.config $extD] | |
| 1007 if {"" eq $extT} { | |
| 1008 set extT [apply $checkTeaishTcl 1 teaish.tcl $extD] | |
| 1009 } | |
| 1010 set ::teaish__Config(extension-dir) $extD | |
| 1011 } | |
| 1012 --help { | |
| 1013 incr gotHelpArg | |
| 1014 lappend largv $arg | |
| 1015 } | |
| 1016 default { | |
| 1017 lappend largv $arg | |
| 1018 } | |
| 1019 } | |
| 1020 } | |
| 1021 set ::argv $largv | |
| 1022 | |
| 1023 set dirExt $::teaish__Config(extension-dir); # dir with the extension | |
| 1024 # | |
| 1025 # teaish.tcl is a TCL script which implements various | |
| 1026 # interfaces described by this framework. | |
| 1027 # | |
| 1028 # We use the first one we find in the builddir or srcdir. | |
| 1029 # | |
| 1030 if {"" eq $extT} { | |
| 1031 set flist [list] | |
| 1032 proj-assert {$dirExt eq ""} | |
| 1033 lappend flist $dirBld/teaish.tcl $dirBld/teaish.config $dirSrc/teaish.tcl | |
| 1034 if {![proj-first-file-found extT $flist]} { | |
| 1035 if {$gotHelpArg} { | |
| 1036 # Tell teaish-configure-core that the lack of extension is not | |
| 1037 # an error when --help or --teaish-install is used. | |
| 1038 return 0; | |
| 1039 } | |
| 1040 proj-indented-notice -error " | |
| 1041 Did not find any of: $flist | |
| 1042 | |
| 1043 If you are attempting an out-of-tree build, use | |
| 1044 --teaish-extension-dir=/path/to/extension" | |
| 1045 } | |
| 1046 } | |
| 1047 if {![file readable $extT]} { | |
| 1048 proj-error "extension tcl file is not readable: $extT" | |
| 1049 } | |
| 1050 set ::teaish__Config(teaish.tcl) $extT | |
| 1051 set dirExt [file dirname $extT] | |
| 1052 | |
| 1053 set ::teaish__Config(extension-dir) $dirExt | |
| 1054 set ::teaish__Config(blddir-is-extdir) [expr {$dirBld eq $dirExt}] | |
| 1055 set ::teaish__Config(dist-enabled) $::teaish__Config(blddir-is-extdir); # may change later | |
| 1056 set ::teaish__Config(dist-full-enabled) \ | |
| 1057 [expr {[file-normalize $::autosetup(srcdir)] | |
| 1058 eq [file-normalize $::teaish__Config(extension-dir)]}] | |
| 1059 | |
| 1060 set addDist {{file} { | |
| 1061 teaish-dist-add [file tail $file] | |
| 1062 }} | |
| 1063 apply $addDist $extT | |
| 1064 | |
| 1065 teaish__verbose 1 msg-result "Extension dir = [teaish-get -dir]" | |
| 1066 teaish__verbose 1 msg-result "Extension config = $extT" | |
| 1067 | |
| 1068 teaish-pkginfo-set -name [file tail [file dirname $extT]] | |
| 1069 | |
| 1070 # | |
| 1071 # teaish.make[.in] provides some of the info for the main makefile, | |
| 1072 # like which source(s) to build and their build flags. | |
| 1073 # | |
| 1074 # We use the first one of teaish.make.in or teaish.make we find in | |
| 1075 # $dirExt. | |
| 1076 # | |
| 1077 if {[proj-first-file-found extM \ | |
| 1078 [list \ | |
| 1079 $dirExt/teaish.make.in \ | |
| 1080 $dirExt/teaish.make \ | |
| 1081 ]]} { | |
| 1082 if {[string match *.in $extM]} { | |
| 1083 define TEAISH_MAKEFILE_IN $extM | |
| 1084 define TEAISH_MAKEFILE _[file rootname [file tail $extM]] | |
| 1085 } else { | |
| 1086 define TEAISH_MAKEFILE_IN "" | |
| 1087 define TEAISH_MAKEFILE $extM | |
| 1088 } | |
| 1089 apply $addDist $extM | |
| 1090 teaish__verbose 1 msg-result "Extension makefile = $extM" | |
| 1091 } else { | |
| 1092 define TEAISH_MAKEFILE_IN "" | |
| 1093 define TEAISH_MAKEFILE "" | |
| 1094 } | |
| 1095 | |
| 1096 # Look for teaish.pkginit.tcl[.in] | |
| 1097 set piPolicy 0 | |
| 1098 if {[proj-first-file-found extI \ | |
| 1099 [list \ | |
| 1100 $dirExt/teaish.pkginit.tcl.in \ | |
| 1101 $dirExt/teaish.pkginit.tcl \ | |
| 1102 ]]} { | |
| 1103 if {[string match *.in $extI]} { | |
| 1104 # Generate teaish.pkginit.tcl from $extI. | |
| 1105 define TEAISH_PKGINIT_TCL_IN $extI | |
| 1106 define TEAISH_PKGINIT_TCL [file rootname [file tail $extI]] | |
| 1107 set piPolicy 0x01 | |
| 1108 } else { | |
| 1109 # Assume static $extI. | |
| 1110 define TEAISH_PKGINIT_TCL_IN "" | |
| 1111 define TEAISH_PKGINIT_TCL $extI | |
| 1112 set piPolicy 0x10 | |
| 1113 } | |
| 1114 apply $addDist $extI | |
| 1115 teaish__verbose 1 msg-result "Extension post-load init = $extI" | |
| 1116 define TEAISH_PKGINIT_TCL_TAIL \ | |
| 1117 [file tail [get-define TEAISH_PKGINIT_TCL]]; # for use in pkgIndex.tcl.in | |
| 1118 } | |
| 1119 set ::teaish__Config(pkginit-policy) $piPolicy | |
| 1120 | |
| 1121 # Look for pkgIndex.tcl[.in]... | |
| 1122 set piPolicy 0 | |
| 1123 if {[proj-first-file-found extPI $dirExt/pkgIndex.tcl.in]} { | |
| 1124 # Generate ./pkgIndex.tcl from $extPI. | |
| 1125 define TEAISH_PKGINDEX_TCL_IN $extPI | |
| 1126 define TEAISH_PKGINDEX_TCL [file rootname [file tail $extPI]] | |
| 1127 apply $addDist $extPI | |
| 1128 set piPolicy 0x01 | |
| 1129 } elseif {$dirExt ne $dirSrc | |
| 1130 && [proj-first-file-found extPI $dirSrc/pkgIndex.tcl.in]} { | |
| 1131 # Generate ./pkgIndex.tcl from $extPI. | |
| 1132 define TEAISH_PKGINDEX_TCL_IN $extPI | |
| 1133 define TEAISH_PKGINDEX_TCL [file rootname [file tail $extPI]] | |
| 1134 set piPolicy 0x02 | |
| 1135 } elseif {[proj-first-file-found extPI $dirExt/pkgIndex.tcl]} { | |
| 1136 # Assume $extPI's a static file and use it. | |
| 1137 define TEAISH_PKGINDEX_TCL_IN "" | |
| 1138 define TEAISH_PKGINDEX_TCL $extPI | |
| 1139 apply $addDist $extPI | |
| 1140 set piPolicy 0x10 | |
| 1141 } | |
| 1142 # Reminder: we have to delay removal of stale TEAISH_PKGINDEX_TCL | |
| 1143 # and the proj-dot-ins-append of TEAISH_PKGINDEX_TCL_IN until much | |
| 1144 # later in the process. | |
| 1145 set ::teaish__Config(pkgindex-policy) $piPolicy | |
| 1146 | |
| 1147 # Look for teaish.test.tcl[.in] | |
| 1148 proj-assert {"" ne $dirExt} | |
| 1149 set flist [list $dirExt/teaish.test.tcl.in $dirExt/teaish.test.tcl] | |
| 1150 if {[proj-first-file-found ttt $flist]} { | |
| 1151 if {[string match *.in $ttt]} { | |
| 1152 # Generate _teaish.test.tcl from $ttt | |
| 1153 set xt _[file rootname [file tail $ttt]] | |
| 1154 file delete -force -- $xt; # ensure no stale copy is used | |
| 1155 define TEAISH_TEST_TCL $xt | |
| 1156 define TEAISH_TEST_TCL_IN $ttt | |
| 1157 } else { | |
| 1158 define TEAISH_TEST_TCL $ttt | |
| 1159 define TEAISH_TEST_TCL_IN "" | |
| 1160 } | |
| 1161 apply $addDist $ttt | |
| 1162 } else { | |
| 1163 define TEAISH_TEST_TCL "" | |
| 1164 define TEAISH_TEST_TCL_IN "" | |
| 1165 } | |
| 1166 | |
| 1167 # Look for _teaish.tester.tcl[.in] | |
| 1168 set flist [list $dirExt/_teaish.tester.tcl.in $dirSrc/_teaish.tester.tcl.in] | |
| 1169 if {[proj-first-file-found ttt $flist]} { | |
| 1170 # Generate teaish.test.tcl from $ttt | |
| 1171 set xt [file rootname [file tail $ttt]] | |
| 1172 file delete -force -- $xt; # ensure no stale copy is used | |
| 1173 define TEAISH_TESTER_TCL $xt | |
| 1174 define TEAISH_TESTER_TCL_IN $ttt | |
| 1175 if {[lindex $flist 0] eq $ttt} { | |
| 1176 apply $addDist $ttt | |
| 1177 } | |
| 1178 unset ttt xt | |
| 1179 } else { | |
| 1180 if {[file exists [set ttt [file join $dirSrc _teaish.tester.tcl.in]]]} { | |
| 1181 set xt [file rootname [file tail $ttt]] | |
| 1182 define TEAISH_TESTER_TCL $xt | |
| 1183 define TEAISH_TESTER_TCL_IN $ttt | |
| 1184 } else { | |
| 1185 define TEAISH_TESTER_TCL "" | |
| 1186 define TEAISH_TESTER_TCL_IN "" | |
| 1187 } | |
| 1188 } | |
| 1189 unset flist | |
| 1190 | |
| 1191 # TEAISH_OUT_OF_EXT_TREE = 1 if we're building from a dir other | |
| 1192 # than the extension's home dir. | |
| 1193 define TEAISH_OUT_OF_EXT_TREE \ | |
| 1194 [expr {[file-normalize $::autosetup(builddir)] ne \ | |
| 1195 [file-normalize $::teaish__Config(extension-dir)]}] | |
| 1196 return 1 | |
| 1197 }; # teaish__find_extension | |
| 1198 | |
| 1199 # | |
| 1200 # @teaish-cflags-add ?-p|prepend? ?-define? cflags... | |
| 1201 # | |
| 1202 # Equivalent to [proj-define-amend TEAISH_CFLAGS {*}$args]. | |
| 1203 # | |
| 1204 proc teaish-cflags-add {args} { | |
| 1205 proj-define-amend TEAISH_CFLAGS {*}$args | |
| 1206 } | |
| 1207 | |
| 1208 # | |
| 1209 # @teaish-define-to-cflag ?flags? defineName...|{defineName...} | |
| 1210 # | |
| 1211 # Uses [proj-define-to-cflag] to expand a list of [define] keys, each | |
| 1212 # one a separate argument, to CFLAGS-style -D... form then appends | |
| 1213 # that to the current TEAISH_CFLAGS. | |
| 1214 # | |
| 1215 # It accepts these flags from proj-define-to-cflag: -quote, | |
| 1216 # -zero-undef. It does _not_ support its -list flag. | |
| 1217 # | |
| 1218 # It accepts its non-flag argument(s) in 2 forms: (1) each arg is a | |
| 1219 # single [define] key or (2) its one arg is a list of such keys. | |
| 1220 # | |
| 1221 # TODO: document teaish's well-defined (as it were) defines for this | |
| 1222 # purpose. At a bare minimum: | |
| 1223 # | |
| 1224 # - TEAISH_NAME | |
| 1225 # - TEAISH_PKGNAME | |
| 1226 # - TEAISH_VERSION | |
| 1227 # - TEAISH_LIBDIR_NAME | |
| 1228 # - TEAISH_LOAD_PREFIX | |
| 1229 # - TEAISH_URL | |
| 1230 # | |
| 1231 proc teaish-define-to-cflag {args} { | |
| 1232 set flags {} | |
| 1233 while {[string match -* [lindex $args 0]]} { | |
| 1234 set arg [lindex $args 0] | |
| 1235 switch -exact -- $arg { | |
| 1236 -quote - | |
| 1237 -zero-undef { | |
| 1238 lappend flags $arg | |
| 1239 set args [lassign $args -] | |
| 1240 } | |
| 1241 default break | |
| 1242 } | |
| 1243 } | |
| 1244 if {1 == [llength $args]} { | |
| 1245 set args [list {*}[lindex $args 0]] | |
| 1246 } | |
| 1247 #puts "***** flags=$flags args=$args" | |
| 1248 teaish-cflags-add [proj-define-to-cflag {*}$flags {*}$args] | |
| 1249 } | |
| 1250 | |
| 1251 # | |
| 1252 # @teaish-cflags-for-tea ?...CFLAGS? | |
| 1253 # | |
| 1254 # Adds several -DPACKAGE_... CFLAGS using the extension's metadata, | |
| 1255 # all as quoted strings. Those symbolic names are commonly used in | |
| 1256 # TEA-based builds, and this function is intended to simplify porting | |
| 1257 # of such builds. The -D... flags added are: | |
| 1258 # | |
| 1259 # -DPACKAGE_VERSION=... | |
| 1260 # -DPACKAGE_NAME=... | |
| 1261 # -DPACKAGE_URL=... | |
| 1262 # -DPACKAGE_STRING=... | |
| 1263 # | |
| 1264 # Any arguments are passed-on as-is to teaish-cflags-add. | |
| 1265 # | |
| 1266 proc teaish-cflags-for-tea {args} { | |
| 1267 set name $::teaish__PkgInfo(-name) | |
| 1268 set version $::teaish__PkgInfo(-version) | |
| 1269 set pstr [join [list $name $version]] | |
| 1270 teaish-cflags-add \ | |
| 1271 {*}$args \ | |
| 1272 '-DPACKAGE_VERSION="$version"' \ | |
| 1273 '-DPACKAGE_NAME="$name"' \ | |
| 1274 '-DPACKAGE_STRING="$pstr"' \ | |
| 1275 '-DPACKAGE_URL="[teaish-get -url]"' | |
| 1276 } | |
| 1277 | |
| 1278 # | |
| 1279 # @teaish-ldflags-add ?-p|-prepend? ?-define? ldflags... | |
| 1280 # | |
| 1281 # Equivalent to [proj-define-amend TEAISH_LDFLAGS {*}$args]. | |
| 1282 # | |
| 1283 # Typically, -lXYZ flags need to be in "reverse" order, with each -lY | |
| 1284 # resolving symbols for -lX's to its left. This order is largely | |
| 1285 # historical, and not relevant on all environments, but it is | |
| 1286 # technically correct and still relevant on some environments. | |
| 1287 # | |
| 1288 # See: teaish-ldflags-prepend | |
| 1289 # | |
| 1290 proc teaish-ldflags-add {args} { | |
| 1291 proj-define-amend TEAISH_LDFLAGS {*}$args | |
| 1292 } | |
| 1293 | |
| 1294 # | |
| 1295 # @teaish-ldflags-prepend args... | |
| 1296 # | |
| 1297 # Functionally equivalent to [teaish-ldflags-add -p {*}$args] | |
| 1298 # | |
| 1299 proc teaish-ldflags-prepend {args} { | |
| 1300 teaish-ldflags-add -p {*}$args | |
| 1301 } | |
| 1302 | |
| 1303 # | |
| 1304 # @teaish-src-add ?-dist? ?-dir? src-files... | |
| 1305 # | |
| 1306 # Appends all non-empty $args to the project's list of C/C++ source or | |
| 1307 # (in some cases) object files. | |
| 1308 # | |
| 1309 # If passed -dist then it also passes each filename, as-is, to | |
| 1310 # [teaish-dist-add]. | |
| 1311 # | |
| 1312 # If passed -dir then each src-file has [teaish-get -dir] prepended to | |
| 1313 # it before they're added to the list. As often as not, that will be | |
| 1314 # the desired behavior so that out-of-tree builds can find the | |
| 1315 # sources, but there are cases where it's not desired (e.g. when using | |
| 1316 # a source file from outside of the extension's dir, or when adding | |
| 1317 # object files (which are typically in the build tree)). | |
| 1318 # | |
| 1319 proc teaish-src-add {args} { | |
| 1320 proj-parse-simple-flags args flags { | |
| 1321 -dist 0 {expr 1} | |
| 1322 -dir 0 {expr 1} | |
| 1323 } | |
| 1324 if {$flags(-dist)} { | |
| 1325 teaish-dist-add {*}$args | |
| 1326 } | |
| 1327 if {$flags(-dir)} { | |
| 1328 set xargs {} | |
| 1329 foreach arg $args { | |
| 1330 if {"" ne $arg} { | |
| 1331 lappend xargs [file join $::teaish__Config(extension-dir) $arg] | |
| 1332 } | |
| 1333 } | |
| 1334 set args $xargs | |
| 1335 } | |
| 1336 lappend ::teaish__Config(extension-src) {*}$args | |
| 1337 } | |
| 1338 | |
| 1339 # | |
| 1340 # @teaish-dist-add files-or-dirs... | |
| 1341 # | |
| 1342 # Adds the given files to the list of files to include with the "make | |
| 1343 # dist" rules. | |
| 1344 # | |
| 1345 # This is a no-op when the current build is not in the extension's | |
| 1346 # directory, as dist support is disabled in out-of-tree builds. | |
| 1347 # | |
| 1348 # It is not legal to call this until [teaish-get -dir] has been | |
| 1349 # reliably set (via teaish__find_extension). | |
| 1350 # | |
| 1351 proc teaish-dist-add {args} { | |
| 1352 if {$::teaish__Config(blddir-is-extdir)} { | |
| 1353 # ^^^ reminder: we ignore $::teaish__Config(dist-enabled) here | |
| 1354 # because the client might want to implement their own dist | |
| 1355 # rules. | |
| 1356 #proj-warn "**** args=$args" | |
| 1357 lappend ::teaish__Config(dist-files) {*}$args | |
| 1358 } | |
| 1359 } | |
| 1360 | |
| 1361 # teaish-install-add files... | |
| 1362 # Equivalent to [proj-define-apend TEAISH_INSTALL_FILES ...]. | |
| 1363 #proc teaish-install-add {args} { | |
| 1364 # proj-define-amend TEAISH_INSTALL_FILES {*}$args | |
| 1365 #} | |
| 1366 | |
| 1367 # | |
| 1368 # @teash-make-add args... | |
| 1369 # | |
| 1370 # Appends makefile code to the TEAISH_MAKEFILE_CODE define. Each | |
| 1371 # arg may be any of: | |
| 1372 # | |
| 1373 # -tab: emit a literal tab | |
| 1374 # -nl: emit a literal newline | |
| 1375 # -nltab: short for -nl -tab | |
| 1376 # -bnl: emit a backslash-escaped end-of-line | |
| 1377 # -bnltab: short for -eol -tab | |
| 1378 # | |
| 1379 # Anything else is appended verbatim. This function adds no additional | |
| 1380 # spacing between each argument nor between subsequent invocations. | |
| 1381 # Generally speaking, a series of calls to this function need to | |
| 1382 # be sure to end the series with a newline. | |
| 1383 proc teaish-make-add {args} { | |
| 1384 set out [get-define TEAISH_MAKEFILE_CODE ""] | |
| 1385 foreach a $args { | |
| 1386 switch -exact -- $a { | |
| 1387 -bnl { set a " \\\n" } | |
| 1388 -bnltab { set a " \\\n\t" } | |
| 1389 -tab { set a "\t" } | |
| 1390 -nl { set a "\n" } | |
| 1391 -nltab { set a "\n\t" } | |
| 1392 } | |
| 1393 append out $a | |
| 1394 } | |
| 1395 define TEAISH_MAKEFILE_CODE $out | |
| 1396 } | |
| 1397 | |
| 1398 # Internal helper to generate a clean/distclean rule name | |
| 1399 proc teaish__cleanup_rule {{tgt clean}} { | |
| 1400 set x [incr ::teaish__Config(teaish__cleanup_rule-counter-${tgt})] | |
| 1401 return ${tgt}-_${x}_ | |
| 1402 } | |
| 1403 | |
| 1404 # @teaish-make-obj ?flags? ?...args? | |
| 1405 # | |
| 1406 # Uses teaish-make-add to inject makefile rules for $objfile from | |
| 1407 # $srcfile, which is assumed to be C code which uses libtcl. Unless | |
| 1408 # -recipe is used (see below) it invokes the compiler using the | |
| 1409 # makefile-defined $(CC.tcl) which, in the default Makefile.in | |
| 1410 # template, includes any flags needed for building against the | |
| 1411 # configured Tcl. | |
| 1412 # | |
| 1413 # This always terminates the resulting code with a newline. | |
| 1414 # | |
| 1415 # Any arguments after the 2nd may be flags described below or, if no | |
| 1416 # -recipe is provided, flags for the compiler call. | |
| 1417 # | |
| 1418 # -obj obj-filename.o | |
| 1419 # | |
| 1420 # -src src-filename.c | |
| 1421 # | |
| 1422 # -recipe {...} | |
| 1423 # Uses the trimmed value of {...} as the recipe, prefixing it with | |
| 1424 # a single hard-tab character. | |
| 1425 # | |
| 1426 # -deps {...} | |
| 1427 # List of extra files to list as dependencies of $o. | |
| 1428 # | |
| 1429 # -clean | |
| 1430 # Generate cleanup rules as well. | |
| 1431 proc teaish-make-obj {args} { | |
| 1432 proj-parse-simple-flags args flags { | |
| 1433 -clean 0 {expr 1} | |
| 1434 -recipe => {} | |
| 1435 -deps => {} | |
| 1436 -obj => {} | |
| 1437 -src => {} | |
| 1438 } | |
| 1439 #parray flags | |
| 1440 if {"" eq $flags(-obj)} { | |
| 1441 set args [lassign $args flags(-obj)] | |
| 1442 if {"" eq $flags(-obj)} { | |
| 1443 proj-error "Missing -obj flag." | |
| 1444 } | |
| 1445 } | |
| 1446 foreach f {-deps -src} { | |
| 1447 set flags($f) [string trim [string map {\n " "} $flags($f)]] | |
| 1448 } | |
| 1449 foreach f {-deps -src} { | |
| 1450 set flags($f) [string trim $flags($f)] | |
| 1451 } | |
| 1452 #parray flags | |
| 1453 #puts "-- args=$args" | |
| 1454 teaish-make-add \ | |
| 1455 "# [proj-scope 1] -> [proj-scope] $flags(-obj) $flags(-src)" -nl \ | |
| 1456 "$flags(-obj): $flags(-src) $::teaish__Config(teaish.tcl)" | |
| 1457 if {[info exists flags(-deps)]} { | |
| 1458 teaish-make-add " " [join $flags(-deps)] | |
| 1459 } | |
| 1460 teaish-make-add -nltab | |
| 1461 if {[info exists flags(-recipe)]} { | |
| 1462 teaish-make-add [string trim $flags(-recipe)] -nl | |
| 1463 } else { | |
| 1464 teaish-make-add [join [list \$(CC.tcl) -c $flags(-src) {*}$args]] -nl | |
| 1465 } | |
| 1466 if {$flags(-clean)} { | |
| 1467 set rule [teaish__cleanup_rule] | |
| 1468 teaish-make-add \ | |
| 1469 "clean: $rule\n$rule:\n\trm -f \"$flags(-obj)\"\n" | |
| 1470 } | |
| 1471 } | |
| 1472 | |
| 1473 # | |
| 1474 # @teaish-make-clean ?-r? ?-dist? ...files|{...files} | |
| 1475 # | |
| 1476 # Adds makefile rules for cleaning up the given files via the "make | |
| 1477 # clean" or (if -dist is used) "make distclean" makefile rules. The -r | |
| 1478 # flag uses "rm -fr" instead of "rm -f", so be careful with that. | |
| 1479 # | |
| 1480 # The file names are taken literally as arguments to "rm", so they may | |
| 1481 # be shell wildcards to be resolved at cleanup-time. To clean up whole | |
| 1482 # directories, pass the -r flag. Each name gets quoted in | |
| 1483 # double-quotes, so spaces in names should not be a problem (but | |
| 1484 # double-quotes in names will be). | |
| 1485 # | |
| 1486 proc teaish-make-clean {args} { | |
| 1487 if {1 == [llength $args]} { | |
| 1488 set args [list {*}[lindex $args 0]] | |
| 1489 } | |
| 1490 | |
| 1491 set tgt clean | |
| 1492 set rmflags "-f" | |
| 1493 proj-parse-simple-flags args flags { | |
| 1494 -dist 0 { | |
| 1495 set tgt distclean | |
| 1496 } | |
| 1497 -r 0 { | |
| 1498 set rmflags "-fr" | |
| 1499 } | |
| 1500 } | |
| 1501 set rule [teaish__cleanup_rule $tgt] | |
| 1502 teaish-make-add "# [proj-scope 1] -> [proj-scope]: [join $args]\n" | |
| 1503 teaish-make-add "${rule}:\n\trm ${rmflags}" | |
| 1504 foreach a $args { | |
| 1505 teaish-make-add " \"$a\"" | |
| 1506 } | |
| 1507 teaish-make-add "\n${tgt}: ${rule}\n" | |
| 1508 } | |
| 1509 | |
| 1510 # | |
| 1511 # @teaish-make-config-header filename | |
| 1512 # | |
| 1513 # Invokes autosetup's [make-config-header] and passes it $filename and | |
| 1514 # a relatively generic list of options for controlling which defined | |
| 1515 # symbols get exported. Clients which need more control over the | |
| 1516 # exports can copy/paste/customize this. | |
| 1517 # | |
| 1518 # The exported file is then passed to [proj-touch] because, in | |
| 1519 # practice, that's sometimes necessary to avoid build dependency | |
| 1520 # issues. | |
| 1521 # | |
| 1522 proc teaish-make-config-header {filename} { | |
| 1523 make-config-header $filename \ | |
| 1524 -none {HAVE_CFLAG_* LDFLAGS_* SH_* TEAISH__* TEAISH_*_CODE} \ | |
| 1525 -auto {SIZEOF_* HAVE_* TEAISH_* TCL_*} \ | |
| 1526 -none * | |
| 1527 proj-touch $filename; # help avoid frequent unnecessary auto-reconfig | |
| 1528 } | |
| 1529 | |
| 1530 # | |
| 1531 # @teaish-feature-cache-set $key value | |
| 1532 # | |
| 1533 # Sets a feature-check cache entry with the given key. | |
| 1534 # See proj-cache-set for the key's semantics. $key should | |
| 1535 # normally be 0. | |
| 1536 # | |
| 1537 proc teaish-feature-cache-set {key val} { | |
| 1538 proj-cache-set -key $key -level 1 $val | |
| 1539 } | |
| 1540 | |
| 1541 # | |
| 1542 # @teaish-feature-cache-check key tgtVarName | |
| 1543 # | |
| 1544 # Checks for a feature-check cache entry with the given key. | |
| 1545 # See proj-cache-set for the key's semantics. | |
| 1546 # | |
| 1547 # $key should also almost always be 0 but, due to a tclsh | |
| 1548 # incompatibility in 1 OS, it cannot have a default value unless it's | |
| 1549 # the second argument (but it should be the first one). | |
| 1550 # | |
| 1551 # If the feature-check cache has a matching entry then this function | |
| 1552 # assigns its value to tgtVar and returns 1, else it assigns tgtVar to | |
| 1553 # "" and returns 0. | |
| 1554 # | |
| 1555 # See proj-cache-check for $key's semantics. | |
| 1556 # | |
| 1557 proc teaish-feature-cache-check {key tgtVar} { | |
| 1558 upvar $tgtVar tgt | |
| 1559 proj-cache-check -key $key -level 1 tgt | |
| 1560 } | |
| 1561 | |
| 1562 # | |
| 1563 # @teaish-check-cached@ ?flags? msg script... | |
| 1564 # | |
| 1565 # A proxy for feature-test impls which handles caching of a feature | |
| 1566 # flag check on per-function basis, using the calling scope's name as | |
| 1567 # the cache key. | |
| 1568 # | |
| 1569 # It emits [msg-checking $msg]. If $msg is empty then it defaults to | |
| 1570 # the name of the caller's scope. The -nomsg flag suppresses the | |
| 1571 # message for non-cache-hit checks. At the end, it will [msg-result | |
| 1572 # "ok"] [msg-result "no"] unless -nostatus is used, in which case the | |
| 1573 # caller is responsible for emitting at least a newline when it's | |
| 1574 # done. The -msg-0 and -msg-1 flags can be used to change the ok/no | |
| 1575 # text. | |
| 1576 # | |
| 1577 # This function checks for a cache hit before running $script and | |
| 1578 # caching the result. If no hit is found then $script is run in the | |
| 1579 # calling scope and its result value is stored in the cache. This | |
| 1580 # routine will intercept a 'return' from $script. | |
| 1581 # | |
| 1582 # $script may be a command and its arguments, as opposed to a single | |
| 1583 # script block. | |
| 1584 # | |
| 1585 # Flags: | |
| 1586 # | |
| 1587 # -nostatus = do not emit "ok" or "no" at the end. This presumes | |
| 1588 # that either $script will emit at least one newline before | |
| 1589 # returning or the caller will account for it. Because of how this | |
| 1590 # function is typically used, -nostatus is not honored when the | |
| 1591 # response includes a cached result. | |
| 1592 # | |
| 1593 # -quiet = disable output from Autosetup's msg-checking and | |
| 1594 # msg-result for the duration of the $script check. Note that when | |
| 1595 # -quiet is in effect, Autosetup's user-notice can be used to queue | |
| 1596 # up output to appear after the check is done. Also note that | |
| 1597 # -quiet has no effect on _this_ function, only the $script part. | |
| 1598 # | |
| 1599 # -nomsg = do not emit $msg for initial check. Like -nostatus, this | |
| 1600 # flag is not honored when the response includes a cached result | |
| 1601 # because it would otherwise produce no output (which is confusing | |
| 1602 # in this context). This is useful when a check runs several other | |
| 1603 # verbose checks and they emit all the necessary info. | |
| 1604 # | |
| 1605 # -msg-0 and -msg-1 MSG = strings to show when the check has failed | |
| 1606 # resp. passed. Defaults are "no" and "ok". The 0 and 1 refer to the | |
| 1607 # result value from teaish-feature-cache-check. | |
| 1608 # | |
| 1609 # -key cachekey = set the cache context key. Only needs to be | |
| 1610 # explicit when using this function multiple times from a single | |
| 1611 # scope. See proj-cache-check and friends for details on the key | |
| 1612 # name. Its default is the name of the scope which calls this | |
| 1613 # function. | |
| 1614 # | |
| 1615 proc teaish-check-cached {args} { | |
| 1616 proj-parse-simple-flags args flags { | |
| 1617 -nostatus 0 {expr 1} | |
| 1618 -quiet 0 {expr 1} | |
| 1619 -key => 1 | |
| 1620 -nomsg 0 {expr 1} | |
| 1621 -msg-0 => no | |
| 1622 -msg-1 => ok | |
| 1623 } | |
| 1624 set args [lassign $args msg] | |
| 1625 set script [join $args] | |
| 1626 if {"" eq $msg} { | |
| 1627 set msg [proj-scope 1] | |
| 1628 } | |
| 1629 if {[teaish-feature-cache-check $flags(-key) check]} { | |
| 1630 #if {0 == $flags(-nomsg)} { | |
| 1631 msg-checking "${msg} ... (cached) " | |
| 1632 #} | |
| 1633 #if {!$flags(-nostatus)} { | |
| 1634 msg-result $flags(-msg-[expr {0 != ${check}}]) | |
| 1635 #} | |
| 1636 return $check | |
| 1637 } else { | |
| 1638 if {0 == $flags(-nomsg)} { | |
| 1639 msg-checking "${msg} ... " | |
| 1640 } | |
| 1641 if {$flags(-quiet)} { | |
| 1642 incr ::autosetup(msg-quiet) | |
| 1643 } | |
| 1644 set code [catch {uplevel 1 $script} rc xopt] | |
| 1645 if {$flags(-quiet)} { | |
| 1646 incr ::autosetup(msg-quiet) -1 | |
| 1647 } | |
| 1648 #puts "***** cached-check got code=$code rc=$rc" | |
| 1649 if {$code in {0 2}} { | |
| 1650 teaish-feature-cache-set 1 $rc | |
| 1651 if {!$flags(-nostatus)} { | |
| 1652 msg-result $flags(-msg-[expr {0 != ${rc}}]) | |
| 1653 } else { | |
| 1654 #show-notices; # causes a phantom newline because we're in a | |
| 1655 #msg-checking scope, so... | |
| 1656 if {[info exists ::autosetup(notices)]} { | |
| 1657 show-notices | |
| 1658 } | |
| 1659 } | |
| 1660 } else { | |
| 1661 #puts "**** code=$code rc=$rc xopt=$xopt" | |
| 1662 teaish-feature-cache-set 1 0 | |
| 1663 } | |
| 1664 #puts "**** code=$code rc=$rc" | |
| 1665 return {*}$xopt $rc | |
| 1666 } | |
| 1667 } | |
| 1668 | |
| 1669 # | |
| 1670 # Internal helper for teaish__defs_format_: returns a JSON-ish quoted | |
| 1671 # form of the given string-type values. | |
| 1672 # | |
| 1673 # If $asList is true then the return value is in {$value} form. If | |
| 1674 # $asList is false it only performs the most basic of escaping and | |
| 1675 # the input must not contain any control characters. | |
| 1676 # | |
| 1677 proc teaish__quote_str {asList value} { | |
| 1678 if {$asList} { | |
| 1679 return "{${value}}" | |
| 1680 } | |
| 1681 return \"[string map [list \\ \\\\ \" \\\"] $value]\" | |
| 1682 } | |
| 1683 | |
| 1684 # | |
| 1685 # Internal helper for teaish__defines_to_list. Expects to be passed | |
| 1686 # a name and the variadic $args which are passed to | |
| 1687 # teaish__defines_to_list.. If it finds a pattern match for the | |
| 1688 # given $name in the various $args, it returns the type flag for that | |
| 1689 # $name, e.g. "-str" or "-bare", else returns an empty string. | |
| 1690 # | |
| 1691 proc teaish__defs_type {name spec} { | |
| 1692 foreach {type patterns} $spec { | |
| 1693 foreach pattern $patterns { | |
| 1694 if {[string match $pattern $name]} { | |
| 1695 return $type | |
| 1696 } | |
| 1697 } | |
| 1698 } | |
| 1699 return "" | |
| 1700 } | |
| 1701 | |
| 1702 # | |
| 1703 # An internal impl detail. Requires a data type specifier, as used by | |
| 1704 # Autosetup's [make-config-header], and a value. Returns the formatted | |
| 1705 # value or the value $::teaish__Config(defs-skip) if the caller should | |
| 1706 # skip emitting that value. | |
| 1707 # | |
| 1708 # In addition to -str, -auto, etc., as defined by make-config-header, | |
| 1709 # it supports: | |
| 1710 # | |
| 1711 # -list {...} will cause non-integer values to be quoted in {...} | |
| 1712 # instead of quotes. | |
| 1713 # | |
| 1714 # -autolist {...} works like -auto {...} except that it falls back to | |
| 1715 # -list {...} type instead of -str {...} style for non-integers. | |
| 1716 # | |
| 1717 # -jsarray {...} emits the output in something which, for | |
| 1718 # conservative inputs, will be a valid JSON array. It can only | |
| 1719 # handle relatively simple values with no control characters in | |
| 1720 # them. | |
| 1721 # | |
| 1722 set teaish__Config(defs-skip) "-teaish__defs_format sentinel" | |
| 1723 proc teaish__defs_format {type value} { | |
| 1724 switch -exact -- $type { | |
| 1725 -bare { | |
| 1726 # Just output the value unchanged | |
| 1727 } | |
| 1728 -none { | |
| 1729 set value $::teaish__Config(defs-skip) | |
| 1730 } | |
| 1731 -str { | |
| 1732 set value [teaish__quote_str 0 $value] | |
| 1733 } | |
| 1734 -auto { | |
| 1735 # Automatically determine the type | |
| 1736 if {![string is integer -strict $value]} { | |
| 1737 set value [teaish__quote_str 0 $value] | |
| 1738 } | |
| 1739 } | |
| 1740 -autolist { | |
| 1741 if {![string is integer -strict $value]} { | |
| 1742 set value [teaish__quote_str 1 $value] | |
| 1743 } | |
| 1744 } | |
| 1745 -list { | |
| 1746 set value [teaish__quote_str 1 $value] | |
| 1747 } | |
| 1748 -jsarray { | |
| 1749 set ar {} | |
| 1750 foreach v $value { | |
| 1751 if {![string is integer -strict $v]} { | |
| 1752 set v [teaish__quote_str 0 $v] | |
| 1753 } | |
| 1754 if {$::teaish__Config(defs-skip) ne $v} { | |
| 1755 lappend ar $v | |
| 1756 } | |
| 1757 } | |
| 1758 set value [concat \[ [join $ar {, }] \]] | |
| 1759 } | |
| 1760 "" { | |
| 1761 # (Much later:) Why do we do this? | |
| 1762 set value $::teaish__Config(defs-skip) | |
| 1763 } | |
| 1764 default { | |
| 1765 proj-error \ | |
| 1766 "Unknown [proj-scope] -type ($type) called from" \ | |
| 1767 [proj-scope 1] | |
| 1768 } | |
| 1769 } | |
| 1770 return $value | |
| 1771 } | |
| 1772 | |
| 1773 # | |
| 1774 # Returns Tcl code in the form of code which evaluates to a list of | |
| 1775 # configure-time DEFINEs in the form {key val key2 val...}. It may | |
| 1776 # misbehave for values which are not numeric or simple strings. Some | |
| 1777 # defines are specifically filtered out of the result, either because | |
| 1778 # their irrelevant to teaish or because they may be arbitrarily large | |
| 1779 # (e.g. makefile content). | |
| 1780 # | |
| 1781 # The $args are explained in the docs for internal-use-only | |
| 1782 # [teaish__defs_format]. The default mode is -autolist. | |
| 1783 # | |
| 1784 proc teaish__defines_to_list {args} { | |
| 1785 set lines {} | |
| 1786 lappend lines "\{" | |
| 1787 set skipper $::teaish__Config(defs-skip) | |
| 1788 set args [list \ | |
| 1789 -none { | |
| 1790 TEAISH__* | |
| 1791 TEAISH_*_CODE | |
| 1792 AM_* AS_* | |
| 1793 } \ | |
| 1794 {*}$args \ | |
| 1795 -autolist *] | |
| 1796 foreach d [lsort [dict keys [all-defines]]] { | |
| 1797 set type [teaish__defs_type $d $args] | |
| 1798 set value [teaish__defs_format $type [get-define $d]] | |
| 1799 if {$skipper ne $value} { | |
| 1800 lappend lines "$d $value" | |
| 1801 } | |
| 1802 } | |
| 1803 lappend lines "\}" | |
| 1804 tailcall join $lines "\n" | |
| 1805 } | |
| 1806 | |
| 1807 # | |
| 1808 # teaish__pragma ...flags | |
| 1809 # | |
| 1810 # Offers a way to tweak how teaish's core behaves in some cases, in | |
| 1811 # particular those which require changing how the core looks for an | |
| 1812 # extension and its files. | |
| 1813 # | |
| 1814 # Accepts the following flags. Those marked with [L] are safe to use | |
| 1815 # during initial loading of tclish.tcl (recall that most teaish APIs | |
| 1816 # cannot be used until [teaish-configure] is called). | |
| 1817 # | |
| 1818 # static-pkgIndex.tcl [L]: Tells teaish that ./pkgIndex.tcl is not | |
| 1819 # a generated file, so it will not try to overwrite or delete | |
| 1820 # it. Errors out if it does not find pkgIndex.tcl in the | |
| 1821 # extension's dir. | |
| 1822 # | |
| 1823 # no-dist [L]: tells teaish to elide the 'make dist' recipe | |
| 1824 # from the generated Makefile. | |
| 1825 # | |
| 1826 # no-dll [L]: tells teaish to elide the DLL-building recipe | |
| 1827 # from the generated Makefile. | |
| 1828 # | |
| 1829 # no-vsatisfies-error [L]: tells teaish that failure to match the | |
| 1830 # -vsatisfies value should simply "return" instead of "error". | |
| 1831 # | |
| 1832 # no-tester [L]: disables automatic generation of teaish.test.tcl | |
| 1833 # even if a copy of _teaish.tester.tcl.in is found. | |
| 1834 # | |
| 1835 # no-full-dist [L]: changes the "make dist" rules to never include | |
| 1836 # a copy of teaish itself. By default it will include itself only | |
| 1837 # if the extension lives in the same directory as teaish. | |
| 1838 # | |
| 1839 # full-dist [L]: changes the "make dist" rules to always include | |
| 1840 # a copy of teaish itself. | |
| 1841 # | |
| 1842 # Emits a warning message for unknown arguments. | |
| 1843 # | |
| 1844 proc teaish__pragma {args} { | |
| 1845 foreach arg $args { | |
| 1846 switch -exact -- $arg { | |
| 1847 | |
| 1848 static-pkgIndex.tcl { | |
| 1849 if {$::teaish__Config(tm-policy)} { | |
| 1850 proj-fatal -up "Cannot use pragma $arg together with -tm.tcl or -tm.tcl.in." | |
| 1851 } | |
| 1852 set tpi [file join $::teaish__Config(extension-dir) pkgIndex.tcl] | |
| 1853 if {[file exists $tpi]} { | |
| 1854 define TEAISH_PKGINDEX_TCL_IN "" | |
| 1855 define TEAISH_PKGINDEX_TCL $tpi | |
| 1856 set ::teaish__Config(pkgindex-policy) 0x20 | |
| 1857 } else { | |
| 1858 proj-error "pragma $arg: found no package-local pkgIndex.tcl\[.in]" | |
| 1859 } | |
| 1860 } | |
| 1861 | |
| 1862 no-dist { | |
| 1863 set ::teaish__Config(dist-enabled) 0 | |
| 1864 } | |
| 1865 | |
| 1866 no-install { | |
| 1867 set ::teaish__Config(install-enabled) 0 | |
| 1868 } | |
| 1869 | |
| 1870 full-dist { | |
| 1871 set ::teaish__Config(dist-full-enabled) 1 | |
| 1872 } | |
| 1873 | |
| 1874 no-full-dist { | |
| 1875 set ::teaish__Config(dist-full-enabled) 0 | |
| 1876 } | |
| 1877 | |
| 1878 no-dll { | |
| 1879 set ::teaish__Config(dll-enabled) 0 | |
| 1880 } | |
| 1881 | |
| 1882 no-vsatisfies-error { | |
| 1883 set ::teaish__Config(vsatisfies-error) 0 | |
| 1884 } | |
| 1885 | |
| 1886 no-tester { | |
| 1887 define TEAISH_TESTER_TCL_IN "" | |
| 1888 define TEAISH_TESTER_TCL "" | |
| 1889 } | |
| 1890 | |
| 1891 default { | |
| 1892 proj-error "Unknown flag: $arg" | |
| 1893 } | |
| 1894 } | |
| 1895 } | |
| 1896 } | |
| 1897 | |
| 1898 # | |
| 1899 # @teaish-pkginfo-set ...flags | |
| 1900 # | |
| 1901 # The way to set up the initial package state. Used like: | |
| 1902 # | |
| 1903 # teaish-pkginfo-set -name foo -version 0.1.2 | |
| 1904 # | |
| 1905 # Or: | |
| 1906 # | |
| 1907 # teaish-pkginfo-set ?-vars|-subst? {-name foo -version 0.1.2} | |
| 1908 # | |
| 1909 # The latter may be easier to write for a multi-line invocation. | |
| 1910 # | |
| 1911 # For the second call form, passing the -vars flag tells it to perform | |
| 1912 # a [subst] of (only) variables in the {...} part from the calling | |
| 1913 # scope. The -subst flag will cause it to [subst] the {...} with | |
| 1914 # command substitution as well (but no backslash substitution). When | |
| 1915 # using -subst for string concatenation, e.g. with -libDir | |
| 1916 # foo[get-version-number], be sure to wrap the value in braces: | |
| 1917 # -libDir {foo[get-version-number]}. | |
| 1918 # | |
| 1919 # Each pkginfo flag corresponds to one piece of extension package | |
| 1920 # info. Teaish provides usable default values for all of these flags, | |
| 1921 # but at least the -name and -version should be set by clients. | |
| 1922 # e.g. the default -name is the directory name the extension lives in, | |
| 1923 # which may change (e.g. when building it from a "make dist" bundle). | |
| 1924 # | |
| 1925 # The flags: | |
| 1926 # | |
| 1927 # -name theName: The extension's name. It defaults to the name of the | |
| 1928 # directory containing the extension. (In TEA this would be the | |
| 1929 # PACKAGE_NAME, not to be confused with...) | |
| 1930 # | |
| 1931 # -name.pkg pkg-provide-name: The extension's name for purposes of | |
| 1932 # Tcl_PkgProvide(), [package require], and friends. It defaults to | |
| 1933 # the `-name`, and is normally the same, but some projects (like | |
| 1934 # SQLite) have a different name here than they do in their | |
| 1935 # historical TEA PACKAGE_NAME. | |
| 1936 # | |
| 1937 # -version version: The extension's package version. Defaults to | |
| 1938 # 0.0.0. | |
| 1939 # | |
| 1940 # -libDir dirName: The base name of the directory into which this | |
| 1941 # extension should be installed. It defaults to a concatenation of | |
| 1942 # `-name.pkg` and `-version`. | |
| 1943 # | |
| 1944 # -loadPrefix prefix: For use as the second argument passed to | |
| 1945 # Tcl's `load` command in the package-loading process. It defaults | |
| 1946 # to title-cased `-name.pkg` because Tcl's `load` plugin system | |
| 1947 # expects it in that form. | |
| 1948 # | |
| 1949 # -options {...}: If provided, it must be a list compatible with | |
| 1950 # Autosetup's `options-add` function. These can also be set up via | |
| 1951 # `teaish-options`. | |
| 1952 # | |
| 1953 # -vsatisfies {{...} ...}: Expects a list-of-lists of conditions | |
| 1954 # for Tcl's `package vsatisfies` command: each list entry is a | |
| 1955 # sub-list of `{PkgName Condition...}`. Teaish inserts those | |
| 1956 # checks via its default pkgIndex.tcl.in and _teaish.tester.tcl.in | |
| 1957 # templates to verify that the system's package dependencies meet | |
| 1958 # these requirements. The default value is `{{Tcl 8.5-}}` (recall | |
| 1959 # that it's a list-of-lists), as 8.5 is the minimum Tcl version | |
| 1960 # teaish will run on, but some extensions may require newer | |
| 1961 # versions or dependencies on other packages. As a special case, | |
| 1962 # if `-vsatisfies` is given a single token, e.g. `8.6-`, then it | |
| 1963 # is transformed into `{Tcl $thatToken}`, i.e. it checks the Tcl | |
| 1964 # version which the package is being run with. If given multiple | |
| 1965 # lists, each `package provides` check is run in the given | |
| 1966 # order. Failure to meet a `vsatisfies` condition triggers an | |
| 1967 # error. | |
| 1968 # | |
| 1969 # -url {...}: an optional URL for the extension. | |
| 1970 # | |
| 1971 # -pragmas {...} A list of infrequently-needed lower-level | |
| 1972 # directives which can influence teaish, including: | |
| 1973 # | |
| 1974 # static-pkgIndex.tcl: tells teaish that the client manages their | |
| 1975 # own pkgIndex.tcl, so that teaish won't try to overwrite it | |
| 1976 # using a template. | |
| 1977 # | |
| 1978 # no-dist: tells teaish to elide the "make dist" recipe from the | |
| 1979 # makefile so that the client can implement it. | |
| 1980 # | |
| 1981 # no-dll: tells teaish to elide the makefile rules which build | |
| 1982 # the DLL, as well as any templated test script and pkgIndex.tcl | |
| 1983 # references to them. The intent here is to (A) support | |
| 1984 # client-defined build rules for the DLL and (B) eventually | |
| 1985 # support script-only extensions. | |
| 1986 # | |
| 1987 # Unsupported flags or pragmas will trigger an error. | |
| 1988 # | |
| 1989 # Potential pothole: setting certain state, e.g. -version, after the | |
| 1990 # initial call requires recalculating of some [define]s. Any such | |
| 1991 # changes should be made as early as possible in teaish-configure so | |
| 1992 # that any later use of those [define]s gets recorded properly (not | |
| 1993 # with the old value). This is particularly relevant when it is not | |
| 1994 # possible to determine the -version or -name until teaish-configure | |
| 1995 # has been called, and it's updated dynamically from | |
| 1996 # teaish-configure. Notably: | |
| 1997 # | |
| 1998 # - If -version or -name are updated, -libDir will almost certainly | |
| 1999 # need to be explicitly set along with them. | |
| 2000 # | |
| 2001 # - If -name is updated, -loadPrefix probably needs to be as well. | |
| 2002 # | |
| 2003 proc teaish-pkginfo-set {args} { | |
| 2004 set doVars 0 | |
| 2005 set doCommands 0 | |
| 2006 set xargs $args | |
| 2007 set recalc {} | |
| 2008 foreach arg $args { | |
| 2009 switch -exact -- $arg { | |
| 2010 -vars { | |
| 2011 incr doVars | |
| 2012 set xargs [lassign $xargs -] | |
| 2013 } | |
| 2014 -subst { | |
| 2015 incr doVars | |
| 2016 incr doCommands | |
| 2017 set xargs [lassign $xargs -] | |
| 2018 } | |
| 2019 default { | |
| 2020 break | |
| 2021 } | |
| 2022 } | |
| 2023 } | |
| 2024 set args $xargs | |
| 2025 unset xargs | |
| 2026 if {1 == [llength $args] && [llength [lindex $args 0]] > 1} { | |
| 2027 # Transform a single {...} arg into the canonical call form | |
| 2028 set a [list {*}[lindex $args 0]] | |
| 2029 if {$doVars || $doCommands} { | |
| 2030 set sflags -nobackslashes | |
| 2031 if {!$doCommands} { | |
| 2032 lappend sflags -nocommands | |
| 2033 } | |
| 2034 set a [uplevel 1 [list subst {*}$sflags $a]] | |
| 2035 } | |
| 2036 set args $a | |
| 2037 } | |
| 2038 set sentinel "<nope>" | |
| 2039 set flagDefs [list] | |
| 2040 foreach {f d} $::teaish__Config(pkginfo-f2d) { | |
| 2041 lappend flagDefs $f => $sentinel | |
| 2042 } | |
| 2043 proj-parse-simple-flags args flags $flagDefs | |
| 2044 if {[llength $args]} { | |
| 2045 proj-error -up "Too many (or unknown) arguments to [proj-scope]: $args" | |
| 2046 } | |
| 2047 foreach {f d} $::teaish__Config(pkginfo-f2d) { | |
| 2048 if {$sentinel eq [set v $flags($f)]} continue | |
| 2049 switch -exact -- $f { | |
| 2050 | |
| 2051 -options { | |
| 2052 proj-assert {"" eq $d} | |
| 2053 options-add $v | |
| 2054 } | |
| 2055 | |
| 2056 -pragmas { | |
| 2057 teaish__pragma {*}$v | |
| 2058 } | |
| 2059 | |
| 2060 -vsatisfies { | |
| 2061 if {1 == [llength $v] && 1 == [llength [lindex $v 0]]} { | |
| 2062 # Transform X to {Tcl $X} | |
| 2063 set v [list [join [list Tcl $v]]] | |
| 2064 } | |
| 2065 define $d $v | |
| 2066 } | |
| 2067 | |
| 2068 -pkgInit.tcl - | |
| 2069 -pkgInit.tcl.in { | |
| 2070 if {0x22 & $::teaish__Config(pkginit-policy)} { | |
| 2071 proj-fatal "Cannot use -pkgInit.tcl(.in) more than once." | |
| 2072 } | |
| 2073 set x [file join $::teaish__Config(extension-dir) $v] | |
| 2074 set tTail [file tail $v] | |
| 2075 if {"-pkgInit.tcl.in" eq $f} { | |
| 2076 # Generate pkginit file X from X.in | |
| 2077 set pI 0x02 | |
| 2078 set tIn $x | |
| 2079 set tOut [file rootname $tTail] | |
| 2080 set other -pkgInit.tcl | |
| 2081 } else { | |
| 2082 # Static pkginit file X | |
| 2083 set pI 0x20 | |
| 2084 set tIn "" | |
| 2085 set tOut $x | |
| 2086 set other -pkgInit.tcl.in | |
| 2087 } | |
| 2088 set ::teaish__Config(pkginit-policy) $pI | |
| 2089 set ::teaish__PkgInfo($other) {} | |
| 2090 define TEAISH_PKGINIT_TCL_IN $tIn | |
| 2091 define TEAISH_PKGINIT_TCL $tOut | |
| 2092 define TEAISH_PKGINIT_TCL_TAIL $tTail | |
| 2093 teaish-dist-add $v | |
| 2094 set v $x | |
| 2095 } | |
| 2096 | |
| 2097 -src { | |
| 2098 set d $::teaish__Config(extension-dir) | |
| 2099 foreach f $v { | |
| 2100 lappend ::teaish__Config(dist-files) $f | |
| 2101 lappend ::teaish__Config(extension-src) $d/$f | |
| 2102 lappend ::teaish__PkgInfo(-src) $f | |
| 2103 # ^^^ so that default-value initialization in | |
| 2104 # teaish-configure-core recognizes that it's been set. | |
| 2105 } | |
| 2106 } | |
| 2107 | |
| 2108 -tm.tcl - | |
| 2109 -tm.tcl.in { | |
| 2110 if {0x30 & $::teaish__Config(pkgindex-policy)} { | |
| 2111 proj-fatal "Cannot use $f together with a pkgIndex.tcl." | |
| 2112 } elseif {$::teaish__Config(tm-policy)} { | |
| 2113 proj-fatal "Cannot use -tm.tcl(.in) more than once." | |
| 2114 } | |
| 2115 set x [file join $::teaish__Config(extension-dir) $v] | |
| 2116 if {"-tm.tcl.in" eq $f} { | |
| 2117 # Generate tm file X from X.in | |
| 2118 set pT 0x02 | |
| 2119 set pI 0x100 | |
| 2120 set tIn $x | |
| 2121 set tOut [file rootname [file tail $v]] | |
| 2122 set other -tm.tcl | |
| 2123 } else { | |
| 2124 # Static tm file X | |
| 2125 set pT 0x20 | |
| 2126 set pI 0x200 | |
| 2127 set tIn "" | |
| 2128 set tOut $x | |
| 2129 set other -tm.tcl.in | |
| 2130 } | |
| 2131 set ::teaish__Config(pkgindex-policy) $pI | |
| 2132 set ::teaish__Config(tm-policy) $pT | |
| 2133 set ::teaish__PkgInfo($other) {} | |
| 2134 define TEAISH_TM_TCL_IN $tIn | |
| 2135 define TEAISH_TM_TCL $tOut | |
| 2136 define TEAISH_PKGINDEX_TCL "" | |
| 2137 define TEAISH_PKGINDEX_TCL_IN "" | |
| 2138 define TEAISH_PKGINDEX_TCL_TAIL "" | |
| 2139 teaish-dist-add $v | |
| 2140 teaish__pragma no-dll | |
| 2141 set v $x | |
| 2142 } | |
| 2143 | |
| 2144 default { | |
| 2145 proj-assert {"" ne $d} | |
| 2146 define $d $v | |
| 2147 } | |
| 2148 } | |
| 2149 set ::teaish__PkgInfo($f) $v | |
| 2150 if {$f in {-name -version -libDir -loadPrefix}} { | |
| 2151 lappend recalc $f | |
| 2152 } | |
| 2153 } | |
| 2154 if {"" ne $recalc} { | |
| 2155 teaish__define_pkginfo_derived $recalc | |
| 2156 } | |
| 2157 } | |
| 2158 | |
| 2159 # | |
| 2160 # @teaish-pkginfo-get ?arg? | |
| 2161 # | |
| 2162 # If passed no arguments, it returns the extension config info in the | |
| 2163 # same form accepted by teaish-pkginfo-set. | |
| 2164 # | |
| 2165 # If passed one -flagname arg then it returns the value of that config | |
| 2166 # option. | |
| 2167 # | |
| 2168 # Else it treats arg as the name of caller-scoped variable to | |
| 2169 # which this function assigns an array containing the configuration | |
| 2170 # state of this extension, in the same structure accepted by | |
| 2171 # teaish-pkginfo-set. In this case it returns an empty string. | |
| 2172 # | |
| 2173 proc teaish-pkginfo-get {args} { | |
| 2174 set cases {} | |
| 2175 set argc [llength $args] | |
| 2176 set rv {} | |
| 2177 switch -exact $argc { | |
| 2178 0 { | |
| 2179 # Return a list of (-flag value) pairs | |
| 2180 lappend cases default {{ | |
| 2181 if {[info exists ::teaish__PkgInfo($flag)]} { | |
| 2182 lappend rv $flag $::teaish__PkgInfo($flag) | |
| 2183 } else { | |
| 2184 lappend rv $flag [get-define $defName] | |
| 2185 } | |
| 2186 }} | |
| 2187 } | |
| 2188 | |
| 2189 1 { | |
| 2190 set arg $args | |
| 2191 if {[string match -* $arg]} { | |
| 2192 # Return the corresponding -flag's value | |
| 2193 lappend cases $arg {{ | |
| 2194 if {[info exists ::teaish__PkgInfo($flag)]} { | |
| 2195 return $::teaish__PkgInfo($flag) | |
| 2196 } else { | |
| 2197 return [get-define $defName] | |
| 2198 } | |
| 2199 }} | |
| 2200 } else { | |
| 2201 # Populate target with an array of (-flag value). | |
| 2202 upvar $arg tgt | |
| 2203 array set tgt {} | |
| 2204 lappend cases default {{ | |
| 2205 if {[info exists ::teaish__PkgInfo($flag)]} { | |
| 2206 set tgt($flag) $::teaish__PkgInfo($flag) | |
| 2207 } else { | |
| 2208 set tgt($flag) [get-define $defName] | |
| 2209 } | |
| 2210 }} | |
| 2211 } | |
| 2212 } | |
| 2213 | |
| 2214 default { | |
| 2215 proj-error "invalid arg count from [proj-scope 1]" | |
| 2216 } | |
| 2217 } | |
| 2218 | |
| 2219 foreach {flag defName} $::teaish__Config(pkginfo-f2d) { | |
| 2220 switch -exact -- $flag [join $cases] | |
| 2221 } | |
| 2222 if {0 == $argc} { return $rv } | |
| 2223 } | |
| 2224 | |
| 2225 # (Re)set some defines based on pkginfo state. $flags is the list of | |
| 2226 # pkginfo -flags which triggered this, or "*" for the initial call. | |
| 2227 proc teaish__define_pkginfo_derived {flags} { | |
| 2228 set all [expr {{*} in $flags}] | |
| 2229 if {$all || "-version" in $flags || "-name" in $flags} { | |
| 2230 set name $::teaish__PkgInfo(-name) ; # _not_ -name.pkg | |
| 2231 if {[info exists ::teaish__PkgInfo(-version)]} { | |
| 2232 set pkgver $::teaish__PkgInfo(-version) | |
| 2233 set libname "lib" | |
| 2234 if {[string match *-cygwin [get-define host]]} { | |
| 2235 set libname cyg | |
| 2236 } | |
| 2237 define TEAISH_DLL8_BASENAME $libname$name$pkgver | |
| 2238 define TEAISH_DLL9_BASENAME ${libname}tcl9$name$pkgver | |
| 2239 set ext [get-define TARGET_DLLEXT] | |
| 2240 define TEAISH_DLL8 [get-define TEAISH_DLL8_BASENAME]$ext | |
| 2241 define TEAISH_DLL9 [get-define TEAISH_DLL9_BASENAME]$ext | |
| 2242 } | |
| 2243 } | |
| 2244 if {$all || "-libDir" in $flags} { | |
| 2245 if {[info exists ::teaish__PkgInfo(-libDir)]} { | |
| 2246 define TCLLIBDIR \ | |
| 2247 [file dirname [get-define TCLLIBDIR]]/$::teaish__PkgInfo(-libDir) | |
| 2248 } | |
| 2249 } | |
| 2250 } | |
| 2251 | |
| 2252 # | |
| 2253 # @teaish-checks-queue -pre|-post args... | |
| 2254 # | |
| 2255 # Queues one or more arbitrary "feature test" functions to be run when | |
| 2256 # teaish-checks-run is called. $flag must be one of -pre or -post to | |
| 2257 # specify whether the tests should be run before or after | |
| 2258 # teaish-configure is run. Each additional arg is the name of a | |
| 2259 # feature-test proc. | |
| 2260 # | |
| 2261 proc teaish-checks-queue {flag args} { | |
| 2262 if {$flag ni {-pre -post}} { | |
| 2263 proj-error "illegal flag: $flag" | |
| 2264 } | |
| 2265 lappend ::teaish__Config(queued-checks${flag}) {*}$args | |
| 2266 } | |
| 2267 | |
| 2268 # | |
| 2269 # @teaish-checks-run -pre|-post | |
| 2270 # | |
| 2271 # Runs all feature checks queued using teaish-checks-queue | |
| 2272 # then cleares the queue. | |
| 2273 # | |
| 2274 proc teaish-checks-run {flag} { | |
| 2275 if {$flag ni {-pre -post}} { | |
| 2276 proj-error "illegal flag: $flag" | |
| 2277 } | |
| 2278 #puts "*** running $flag: $::teaish__Config(queued-checks${flag})" | |
| 2279 set foo 0 | |
| 2280 foreach f $::teaish__Config(queued-checks${flag}) { | |
| 2281 if {![teaish-feature-cache-check $f foo]} { | |
| 2282 set v [$f] | |
| 2283 teaish-feature-cache-set $f $v | |
| 2284 } | |
| 2285 } | |
| 2286 set ::teaish__Config(queued-checks${flag}) {} | |
| 2287 } | |
| 2288 | |
| 2289 # | |
| 2290 # A general-purpose getter for various teaish state. Requires one | |
| 2291 # flag, which determines its result value. Flags marked with [L] below | |
| 2292 # are safe for using at load-time, before teaish-pkginfo-set is called | |
| 2293 # | |
| 2294 # -dir [L]: returns the extension's directory, which may differ from | |
| 2295 # the teaish core dir or the build dir. | |
| 2296 # | |
| 2297 # -teaish-home [L]: the "home" dir of teaish itself, which may | |
| 2298 # differ from the extension dir or build dir. | |
| 2299 # | |
| 2300 # -build-dir [L]: the build directory (typically the current working | |
| 2301 # -dir). | |
| 2302 # | |
| 2303 # Any of the teaish-pkginfo-get/get flags: returns the same as | |
| 2304 # teaish-pkginfo-get. Not safe for use until teaish-pkginfo-set has | |
| 2305 # been called. | |
| 2306 # | |
| 2307 # Triggers an error if passed an unknown flag. | |
| 2308 # | |
| 2309 proc teaish-get {flag} { | |
| 2310 #-teaish.tcl {return $::teaish__Config(teaish.tcl)} | |
| 2311 switch -exact -- $flag { | |
| 2312 -dir { | |
| 2313 return $::teaish__Config(extension-dir) | |
| 2314 } | |
| 2315 -teaish-home { | |
| 2316 return $::autosetup(srcdir) | |
| 2317 } | |
| 2318 -build-dir { | |
| 2319 return $::autosetup(builddir) | |
| 2320 } | |
| 2321 default { | |
| 2322 if {[info exists ::teaish__PkgInfo($flag)]} { | |
| 2323 return $::teaish__PkgInfo($flag) | |
| 2324 } | |
| 2325 } | |
| 2326 } | |
| 2327 proj-error "Unhandled flag: $flag" | |
| 2328 } | |
| 2329 | |
| 2330 # | |
| 2331 # Handles --teaish-create-extension=TARGET-DIR | |
| 2332 # | |
| 2333 proc teaish__create_extension {dir} { | |
| 2334 set force [opt-bool teaish-force] | |
| 2335 if {"" eq $dir} { | |
| 2336 proj-error "--teaish-create-extension=X requires a directory name." | |
| 2337 } | |
| 2338 file mkdir $dir/generic | |
| 2339 set cwd [pwd] | |
| 2340 #set dir [file-normalize [file join $cwd $dir]] | |
| 2341 teaish__verbose 1 msg-result "Created dir $dir" | |
| 2342 cd $dir | |
| 2343 if {!$force} { | |
| 2344 # Ensure that we don't blindly overwrite anything | |
| 2345 foreach f { | |
| 2346 generic/teaish.c | |
| 2347 teaish.tcl | |
| 2348 teaish.make.in | |
| 2349 teaish.test.tcl | |
| 2350 } { | |
| 2351 if {[file exists $f]} { | |
| 2352 error "Cowardly refusing to overwrite $dir/$f. Use --teaish-force to overwrite." | |
| 2353 } | |
| 2354 } | |
| 2355 } | |
| 2356 | |
| 2357 set name [file tail $dir] | |
| 2358 set pkgName $name | |
| 2359 set version 0.0.1 | |
| 2360 set loadPrefix [string totitle $pkgName] | |
| 2361 set content {teaish-pkginfo-set } | |
| 2362 #puts "0 content=$content" | |
| 2363 if {[opt-str teaish-extension-pkginfo epi]} { | |
| 2364 set epi [string trim $epi] | |
| 2365 if {[string match "*\n*" $epi]} { | |
| 2366 set epi "{$epi}" | |
| 2367 } elseif {![string match "{*}" $epi]} { | |
| 2368 append content "\{" $epi "\}" | |
| 2369 } else { | |
| 2370 append content $epi | |
| 2371 } | |
| 2372 #puts "2 content=$content\nepi=$epi" | |
| 2373 } else { | |
| 2374 append content [subst -nocommands -nobackslashes {{ | |
| 2375 -name ${name} | |
| 2376 -name.pkg ${pkgName} | |
| 2377 -name.dist ${pkgName} | |
| 2378 -version ${version} | |
| 2379 -loadPrefix $loadPrefix | |
| 2380 -libDir ${name}${version} | |
| 2381 -vsatisfies {{Tcl 8.5-}} | |
| 2382 -url {} | |
| 2383 -options {} | |
| 2384 -pragmas {full-dist} | |
| 2385 }}] | |
| 2386 #puts "3 content=$content" | |
| 2387 } | |
| 2388 #puts "1 content=$content" | |
| 2389 append content "\n" { | |
| 2390 #proc teaish-options {} { | |
| 2391 # Return a list and/or use \[options-add\] to add new | |
| 2392 # configure flags. This is called before teaish's | |
| 2393 # bootstrapping is finished, so only teaish-* | |
| 2394 # APIs which are explicitly noted as being safe | |
| 2395 # early on may be used here. Any autosetup-related | |
| 2396 # APIs may be used here. | |
| 2397 # | |
| 2398 # Return an empty string if there are no options to | |
| 2399 # add or if they are added using \[options-add\]. | |
| 2400 # | |
| 2401 # If there are no options to add, this proc need | |
| 2402 # not be defined. | |
| 2403 #} | |
| 2404 | |
| 2405 # Called by teaish once bootstrapping is complete. | |
| 2406 # This function is responsible for the client-specific | |
| 2407 # parts of the configuration process. | |
| 2408 proc teaish-configure {} { | |
| 2409 teaish-src-add -dir -dist generic/teaish.c | |
| 2410 teaish-define-to-cflag -quote TEAISH_PKGNAME TEAISH_VERSION | |
| 2411 | |
| 2412 # TODO: your code goes here.. | |
| 2413 } | |
| 2414 }; # $content | |
| 2415 proj-file-write teaish.tcl $content | |
| 2416 teaish__verbose 1 msg-result "Created teaish.tcl" | |
| 2417 | |
| 2418 set content "# Teaish test script. | |
| 2419 # When this tcl script is invoked via 'make test' it will have loaded | |
| 2420 # the package, run any teaish.pkginit.tcl code, and loaded | |
| 2421 # autosetup/teaish/tester.tcl. | |
| 2422 " | |
| 2423 proj-file-write teaish.test.tcl $content | |
| 2424 teaish__verbose 1 msg-result "Created teaish.test.tcl" | |
| 2425 | |
| 2426 set content [subst -nocommands -nobackslashes { | |
| 2427 #include <tcl.h> | |
| 2428 static int | |
| 2429 ${loadPrefix}_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]){ | |
| 2430 Tcl_SetObjResult(interp, Tcl_NewStringObj("this is the ${name} extension", -1)); | |
| 2431 return TCL_OK; | |
| 2432 } | |
| 2433 | |
| 2434 extern int DLLEXPORT ${loadPrefix}_Init(Tcl_Interp *interp){ | |
| 2435 if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { | |
| 2436 return TCL_ERROR; | |
| 2437 } | |
| 2438 if (Tcl_PkgProvide(interp, TEAISH_PKGNAME, TEAISH_VERSION) == TCL_ERROR) { | |
| 2439 return TCL_ERROR; | |
| 2440 } | |
| 2441 Tcl_CreateObjCommand(interp, TEAISH_PKGNAME, ${loadPrefix}_Cmd, NULL, NULL); | |
| 2442 return TCL_OK; | |
| 2443 } | |
| 2444 }] | |
| 2445 proj-file-write generic/teaish.c $content | |
| 2446 teaish__verbose 1 msg-result "Created generic/teaish.c" | |
| 2447 | |
| 2448 set content "# teaish makefile for the ${name} extension | |
| 2449 # tx.src = \$(tx.dir)/generic/teaish.c | |
| 2450 # tx.LDFLAGS = | |
| 2451 # tx.CFLAGS = | |
| 2452 " | |
| 2453 proj-file-write teaish.make.in $content | |
| 2454 teaish__verbose 1 msg-result "Created teaish.make.in" | |
| 2455 | |
| 2456 msg-result "Created new extension \[$dir\]." | |
| 2457 | |
| 2458 cd $cwd | |
| 2459 set ::teaish__Config(install-ext-dir) $dir | |
| 2460 } | |
| 2461 | |
| 2462 # | |
| 2463 # Internal helper for teaish__install | |
| 2464 # | |
| 2465 proc teaish__install_file {f destDir force} { | |
| 2466 set dest $destDir/[file tail $f] | |
| 2467 if {[file isdirectory $f]} { | |
| 2468 file mkdir $dest | |
| 2469 } elseif {!$force && [file exists $dest]} { | |
| 2470 array set st1 [file stat $f] | |
| 2471 array set st2 [file stat $dest] | |
| 2472 if {($st1(mtime) == $st2(mtime)) | |
| 2473 && ($st1(size) == $st2(size))} { | |
| 2474 if {[file tail $f] in { | |
| 2475 pkgIndex.tcl.in | |
| 2476 _teaish.tester.tcl.in | |
| 2477 }} { | |
| 2478 # Assume they're the same. In the scope of the "make dist" | |
| 2479 # rules, this happens legitimately when an extension with a | |
| 2480 # copy of teaish installed in the same dir assumes that the | |
| 2481 # pkgIndex.tcl.in and _teaish.tester.tcl.in belong to the | |
| 2482 # extension, whereas teaish believes they belong to teaish. | |
| 2483 # So we end up with dupes of those. | |
| 2484 return | |
| 2485 } | |
| 2486 } | |
| 2487 proj-error -up "Cowardly refusing to overwrite \[$dest\]." \ | |
| 2488 "Use --teaish-force to enable overwriting." | |
| 2489 } else { | |
| 2490 # file copy -force $f $destDir; # loses +x bit | |
| 2491 # | |
| 2492 # JimTcl doesn't have [file attribute], so we can't use that here | |
| 2493 # (in the context of an autosetup configure script). | |
| 2494 exec cp -p $f $dest | |
| 2495 } | |
| 2496 } | |
| 2497 | |
| 2498 # | |
| 2499 # Installs a copy of teaish, with autosetup, to $dDest, which defaults | |
| 2500 # to the --teaish-install=X or --teash-create-extension=X dir. Won't | |
| 2501 # overwrite files unless --teaish-force is used. | |
| 2502 # | |
| 2503 proc teaish__install {{dDest ""}} { | |
| 2504 if {$dDest in {auto ""}} { | |
| 2505 set dDest [opt-val teaish-install] | |
| 2506 if {$dDest in {auto ""}} { | |
| 2507 if {[info exists ::teaish__Config(install-ext-dir)]} { | |
| 2508 set dDest $::teaish__Config(install-ext-dir) | |
| 2509 } | |
| 2510 } | |
| 2511 } | |
| 2512 set force [opt-bool teaish-force] | |
| 2513 if {$dDest in {auto ""}} { | |
| 2514 proj-error "Cannot determine installation directory." | |
| 2515 } elseif {!$force && [file exists $dDest/auto.def]} { | |
| 2516 proj-error \ | |
| 2517 "Target dir looks like it already contains teaish and/or autosetup: $dDest" \ | |
| 2518 "\nUse --teaish-force to overwrite it." | |
| 2519 } | |
| 2520 | |
| 2521 set dSrc $::autosetup(srcdir) | |
| 2522 set dAS $::autosetup(libdir) | |
| 2523 set dAST $::teaish__Config(core-dir) | |
| 2524 set dASTF $dAST/feature | |
| 2525 teaish__verbose 1 msg-result "Installing teaish to \[$dDest\]..." | |
| 2526 if {$::teaish__Config(verbose)>1} { | |
| 2527 msg-result "dSrc = $dSrc" | |
| 2528 msg-result "dAS = $dAS" | |
| 2529 msg-result "dAST = $dAST" | |
| 2530 msg-result "dASTF = $dASTF" | |
| 2531 msg-result "dDest = $dDest" | |
| 2532 } | |
| 2533 | |
| 2534 # Dest subdirs... | |
| 2535 set ddAS $dDest/autosetup | |
| 2536 set ddAST $ddAS/teaish | |
| 2537 set ddASTF $ddAST/feature | |
| 2538 foreach {srcDir destDir} [list \ | |
| 2539 $dAS $ddAS \ | |
| 2540 $dAST $ddAST \ | |
| 2541 $dASTF $ddASTF \ | |
| 2542 ] { | |
| 2543 teaish__verbose 1 msg-result "Copying files to $destDir..." | |
| 2544 file mkdir $destDir | |
| 2545 foreach f [glob -nocomplain -directory $srcDir *] { | |
| 2546 if {[string match {*~} $f] || [string match "#*#" [file tail $f]]} { | |
| 2547 # Editor-generated backups and emacs lock files | |
| 2548 continue | |
| 2549 } | |
| 2550 teaish__verbose 2 msg-result "\t$f" | |
| 2551 teaish__install_file $f $destDir $force | |
| 2552 } | |
| 2553 } | |
| 2554 teaish__verbose 1 msg-result "Copying files to $dDest..." | |
| 2555 foreach f { | |
| 2556 auto.def configure Makefile.in pkgIndex.tcl.in | |
| 2557 _teaish.tester.tcl.in | |
| 2558 } { | |
| 2559 teaish__verbose 2 msg-result "\t$f" | |
| 2560 teaish__install_file $dSrc/$f $dDest $force | |
| 2561 } | |
| 2562 set ::teaish__Config(install-self-dir) $dDest | |
| 2563 msg-result "Teaish $::teaish__Config(version) installed in \[$dDest\]." | |
| 2564 } |