|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use proj |
|
|
|
|
|
|
|
|
|
|
|
array set teaish__Config [proj-strip-hash-comments { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
version 0.1-beta |
|
|
|
|
|
|
|
|
debug-enabled 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pkgindex-policy 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pkginit-policy 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tm-policy 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
verbose 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pkginfo-f2d { |
|
|
-name TEAISH_NAME |
|
|
-name.dist TEAISH_DIST_NAME |
|
|
-name.pkg TEAISH_PKGNAME |
|
|
-version TEAISH_VERSION |
|
|
-libDir TEAISH_LIBDIR_NAME |
|
|
-loadPrefix TEAISH_LOAD_PREFIX |
|
|
-vsatisfies TEAISH_VSATISFIES |
|
|
-pkgInit.tcl TEAISH_PKGINIT_TCL |
|
|
-pkgInit.tcl.in TEAISH_PKGINIT_TCL_IN |
|
|
-url TEAISH_URL |
|
|
-tm.tcl TEAISH_TM_TCL |
|
|
-tm.tcl.in TEAISH_TM_TCL_IN |
|
|
-options {} |
|
|
-pragmas {} |
|
|
-src {} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
queued-checks-pre {} |
|
|
queued-checks-post {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dist-enabled 1 |
|
|
|
|
|
|
|
|
|
|
|
install-enabled 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dll-enabled 1 |
|
|
|
|
|
|
|
|
dist-files {} |
|
|
|
|
|
|
|
|
extension-src {} |
|
|
|
|
|
|
|
|
teaish.tcl {} |
|
|
|
|
|
|
|
|
extension-dir {} |
|
|
|
|
|
|
|
|
|
|
|
vsatisfies-error 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dist-full-enabled 0 |
|
|
}] |
|
|
set teaish__Config(core-dir) $::autosetup(libdir)/teaish |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
array set teaish__PkgInfo {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish__verbose {lvl args} { |
|
|
if {$lvl <= $::teaish__Config(verbose)} { |
|
|
{*}$args |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-argv-has {args} { |
|
|
foreach glob $args { |
|
|
foreach arg $::argv { |
|
|
if {[string match $glob $arg]} { |
|
|
return 1 |
|
|
} |
|
|
} |
|
|
} |
|
|
return 0 |
|
|
} |
|
|
|
|
|
if {[teaish-argv-has --teaish-verbose --t-v]} { |
|
|
|
|
|
|
|
|
set ::teaish__Config(verbose) 1 |
|
|
|
|
|
} |
|
|
|
|
|
msg-quiet use system |
|
|
if {"--help" ni $::argv} { |
|
|
teaish__verbose 1 msg-result "TEA(ish) Version = $::teaish__Config(version)" |
|
|
teaish__verbose 1 msg-result "Source dir = $::autosetup(srcdir)" |
|
|
teaish__verbose 1 msg-result "Build dir = $::autosetup(builddir)" |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-configure-core {} { |
|
|
proj-tweak-default-env-dirs |
|
|
|
|
|
set ::teaish__Config(install-mode) [teaish-argv-has --teaish-install*] |
|
|
set ::teaish__Config(create-ext-mode) \ |
|
|
[teaish-argv-has --teaish-create-extension=* --t-c-e=*] |
|
|
set gotExt 0 |
|
|
if {!$::teaish__Config(create-ext-mode) |
|
|
&& !$::teaish__Config(install-mode)} { |
|
|
|
|
|
set gotExt [teaish__find_extension] |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
options-add [proj-strip-hash-comments { |
|
|
with-tcl:DIR |
|
|
=> {Directory containing tclConfig.sh or a directory one level up from |
|
|
that, from which we can derive a directory containing tclConfig.sh. |
|
|
Defaults to the $TCL_HOME environment variable.} |
|
|
|
|
|
with-tclsh:PATH |
|
|
=> {Full pathname of tclsh to use. It is used for trying to find |
|
|
tclConfig.sh. Warning: if its containing dir has multiple tclsh |
|
|
versions, it may select the wrong tclConfig.sh! |
|
|
Defaults to the $TCLSH environment variable.} |
|
|
|
|
|
tcl-stubs=0 => {Enable use of Tcl stubs library.} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ted: t-e-d: |
|
|
teaish-extension-dir:DIR |
|
|
=> {Looks for an extension in the given directory instead of the current |
|
|
dir.} |
|
|
|
|
|
t-c-e: |
|
|
teaish-create-extension:TARGET_DIRECTORY |
|
|
=> {Writes stub files for creating an extension. Will refuse to overwrite |
|
|
existing files without --teaish-force.} |
|
|
|
|
|
t-f |
|
|
teaish-force |
|
|
=> {Has a context-dependent meaning (autosetup defines --force for its |
|
|
own use).} |
|
|
|
|
|
t-d-d |
|
|
teaish-dump-defines |
|
|
=> {Dump all configure-defined vars to config.defines.txt} |
|
|
|
|
|
t-v:=0 |
|
|
teaish-verbose:=0 |
|
|
=> {Enable more (often extraneous) messages from the teaish core.} |
|
|
|
|
|
t-d |
|
|
teaish-debug=0 => {Enable teaish-specific debug output} |
|
|
|
|
|
t-i |
|
|
teaish-install:=auto |
|
|
=> {Installs a copy of teaish, including autosetup, to the target dir. |
|
|
When used with --teaish-create-extension=DIR, a value of "auto" |
|
|
(no no value) will inherit that directory.} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
t-e-p: |
|
|
teaish-extension-pkginfo:pkginfo |
|
|
=> {For use with --teaish-create-extension. If used, it must be a |
|
|
list of arguments for use with teaish-pkginfo-set, e.g. |
|
|
--teaish-extension-pkginfo="-name Foo -version 2.3"} |
|
|
|
|
|
t-v-c |
|
|
teaish-vsatisfies-check=1 |
|
|
=> {Disable the configure-time "vsatisfies" check on the target tclsh.} |
|
|
|
|
|
}] |
|
|
|
|
|
if {$gotExt} { |
|
|
|
|
|
set ttcl $::teaish__Config(teaish.tcl) |
|
|
proj-assert {"" ne [teaish-pkginfo-get -name]} |
|
|
proj-assert {[file exists $ttcl]} \ |
|
|
"Expecting to have found teaish.(tcl|config) by now" |
|
|
if {[string match *.tcl $ttcl]} { |
|
|
uplevel 1 {source $::teaish__Config(teaish.tcl)} |
|
|
} else { |
|
|
teaish-pkginfo-set {*}[proj-file-content -trim $ttcl] |
|
|
} |
|
|
unset ttcl |
|
|
|
|
|
|
|
|
|
|
|
array set f2d $::teaish__Config(pkginfo-f2d) |
|
|
foreach {pflag key type val} { |
|
|
- TEAISH_CFLAGS -v "" |
|
|
- TEAISH_LDFLAGS -v "" |
|
|
- TEAISH_MAKEFILE -v "" |
|
|
- TEAISH_MAKEFILE_CODE -v "" |
|
|
- TEAISH_MAKEFILE_IN -v "" |
|
|
- TEAISH_PKGINDEX_TCL -v "" |
|
|
- TEAISH_PKGINDEX_TCL_IN -v "" |
|
|
- TEAISH_PKGINIT_TCL -v "" |
|
|
- TEAISH_PKGINIT_TCL_IN -v "" |
|
|
- TEAISH_PKGINIT_TCL_TAIL -v "" |
|
|
- TEAISH_TEST_TCL -v "" |
|
|
- TEAISH_TEST_TCL_IN -v "" |
|
|
|
|
|
-version - -v 0.0.0 |
|
|
-name.pkg - -e {set ::teaish__PkgInfo(-name)} |
|
|
-name.dist - -e {set ::teaish__PkgInfo(-name)} |
|
|
-libDir - -e { |
|
|
join [list \ |
|
|
$::teaish__PkgInfo(-name.pkg) \ |
|
|
$::teaish__PkgInfo(-version)] "" |
|
|
} |
|
|
-loadPrefix - -e { |
|
|
string totitle $::teaish__PkgInfo(-name.pkg) |
|
|
} |
|
|
-vsatisfies - -v {{Tcl 8.5-}} |
|
|
-pkgInit.tcl - -v "" |
|
|
-pkgInit.tcl.in - -v "" |
|
|
-url - -v "" |
|
|
-tm.tcl - -v "" |
|
|
-tm.tcl.in - -v "" |
|
|
-src - -v "" |
|
|
} { |
|
|
|
|
|
set isPIFlag [expr {"-" ne $pflag}] |
|
|
if {$isPIFlag} { |
|
|
if {[info exists ::teaish__PkgInfo($pflag)]} { |
|
|
|
|
|
continue; |
|
|
} |
|
|
proj-assert {{-} eq $key} |
|
|
set key $f2d($pflag) |
|
|
} |
|
|
if {"" ne $key} { |
|
|
if {"<nope>" ne [get-define $key "<nope>"]} { |
|
|
|
|
|
continue |
|
|
} |
|
|
} |
|
|
switch -exact -- $type { |
|
|
-v {} |
|
|
-e { set val [eval $val] } |
|
|
default { proj-error "Invalid type flag: $type" } |
|
|
} |
|
|
|
|
|
if {$key ne ""} { |
|
|
define $key $val |
|
|
} |
|
|
if {$isPIFlag} { |
|
|
set ::teaish__PkgInfo($pflag) $val |
|
|
} |
|
|
} |
|
|
unset isPIFlag pflag key type val |
|
|
array unset f2d |
|
|
} |
|
|
|
|
|
if {[llength [info proc teaish-options]] > 0} { |
|
|
|
|
|
|
|
|
set o [teaish-options] |
|
|
if {"" ne $o} { |
|
|
options-add $o |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if {[catch {options {}} msg xopts]} { |
|
|
|
|
|
|
|
|
|
|
|
dict incr xopts -level |
|
|
return {*}$xopts $msg |
|
|
} |
|
|
|
|
|
proj-xfer-options-aliases { |
|
|
t-c-e => teaish-create-extension |
|
|
t-d => teaish-debug |
|
|
t-d-d => teaish-dump-defines |
|
|
ted => teaish-extension-dir |
|
|
t-e-d => teaish-extension-dir |
|
|
t-e-p => teaish-extension-pkginfo |
|
|
t-f => teaish-force |
|
|
t-i => teaish-install |
|
|
t-v => teaish-verbose |
|
|
t-v-c => teaish-vsatisfies-check |
|
|
} |
|
|
|
|
|
scan [opt-val teaish-verbose 0] %d ::teaish__Config(verbose) |
|
|
set ::teaish__Config(debug-enabled) [opt-bool teaish-debug] |
|
|
|
|
|
set exitEarly 0 |
|
|
if {[proj-opt-was-provided teaish-create-extension]} { |
|
|
teaish__create_extension [opt-val teaish-create-extension] |
|
|
incr exitEarly |
|
|
} |
|
|
if {$::teaish__Config(install-mode)} { |
|
|
teaish__install |
|
|
incr exitEarly |
|
|
} |
|
|
|
|
|
if {$exitEarly} { |
|
|
file delete -force config.log |
|
|
return |
|
|
} |
|
|
proj-assert {1==$gotExt} "Else we cannot have gotten this far" |
|
|
|
|
|
teaish__configure_phase1 |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-debug {msg} { |
|
|
if {$::teaish__Config(debug-enabled)} { |
|
|
puts stderr [proj-bold "** DEBUG: \[[proj-scope 1]\]: $msg"] |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish__configure_phase1 {} { |
|
|
msg-result \ |
|
|
[join [list "Configuring build of Tcl extension" \ |
|
|
[proj-bold [teaish-pkginfo-get -name] \ |
|
|
[teaish-pkginfo-get -version]] "..."]] |
|
|
|
|
|
uplevel 1 { |
|
|
use cc cc-db cc-shared cc-lib |
|
|
} |
|
|
teaish__check_tcl |
|
|
apply {{} { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach {flag uflag tclVar} { |
|
|
prefix prefix TCL_PREFIX |
|
|
exec-prefix exec_prefix TCL_EXEC_PREFIX |
|
|
} { |
|
|
if {![proj-opt-was-provided $flag]} { |
|
|
if {"exec-prefix" eq $flag} { |
|
|
|
|
|
|
|
|
set v {${prefix}} |
|
|
} else { |
|
|
set v [get-define $tclVar "???"] |
|
|
teaish__verbose 1 msg-result "Using \$$tclVar for --$flag=$v" |
|
|
} |
|
|
proj-assert {"???" ne $v} "Expecting teaish__check_tcl to have defined $tclVar" |
|
|
|
|
|
proj-opt-set $flag $v |
|
|
define $uflag $v |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
}} |
|
|
teaish__check_common_bins |
|
|
|
|
|
|
|
|
|
|
|
proj-file-extensions |
|
|
teaish__define_pkginfo_derived * |
|
|
|
|
|
teaish-checks-run -pre |
|
|
if {[llength [info proc teaish-configure]] > 0} { |
|
|
|
|
|
|
|
|
teaish-configure |
|
|
} |
|
|
teaish-checks-run -post |
|
|
|
|
|
define TEAISH_USE_STUBS [opt-bool tcl-stubs] |
|
|
|
|
|
apply {{} { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set vs [get-define TEAISH_VSATISFIES ""] |
|
|
if {"" eq $vs} return |
|
|
set code {} |
|
|
set n 0 |
|
|
|
|
|
|
|
|
|
|
|
foreach pv $vs { |
|
|
set n [llength $pv] |
|
|
if {$n < 2} { |
|
|
proj-error "-vsatisfies: {$pv} appears malformed. Whole list is: $vs" |
|
|
} |
|
|
set pkg [lindex $pv 0] |
|
|
set vcheck {} |
|
|
for {set i 1} {$i < $n} {incr i} { |
|
|
lappend vcheck [lindex $pv $i] |
|
|
} |
|
|
if {[opt-bool teaish-vsatisfies-check]} { |
|
|
set tclsh [get-define TCLSH_CMD] |
|
|
set vsat "package vsatisfies \[ package provide $pkg \] $vcheck" |
|
|
set vputs "puts \[ $vsat \]" |
|
|
|
|
|
scan [exec echo $vputs | $tclsh] %d vvcheck |
|
|
if {![info exists vvcheck] || 0 == $vvcheck} { |
|
|
proj-fatal -up $tclsh "check failed:" $vsat |
|
|
} |
|
|
} |
|
|
if {$::teaish__Config(vsatisfies-error)} { |
|
|
set vunsat \ |
|
|
[list error [list Package \ |
|
|
$::teaish__PkgInfo(-name) $::teaish__PkgInfo(-version) \ |
|
|
requires $pv]] |
|
|
} else { |
|
|
set vunsat return |
|
|
} |
|
|
lappend code \ |
|
|
[string trim [subst -nocommands \ |
|
|
{if { ![package vsatisfies [package provide $pkg] $vcheck] } {\n $vunsat\n}}]] |
|
|
} |
|
|
define TEAISH_VSATISFIES_CODE [join $code "\n"] |
|
|
}} |
|
|
|
|
|
if {[proj-looks-like-windows]} { |
|
|
|
|
|
|
|
|
msg-result "Using USE_TCL_STUBS for Unix(ish)-on-Windows environment" |
|
|
teaish-cflags-add -DUSE_TCL_STUBS=1 |
|
|
} |
|
|
|
|
|
|
|
|
define TEAISH_TESTUTIL_TCL $::teaish__Config(core-dir)/tester.tcl |
|
|
|
|
|
apply {{} { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if {!$::teaish__Config(pkgindex-policy)} { |
|
|
proj-error "Cannot determine which pkgIndex.tcl to use" |
|
|
} |
|
|
if {0x300 & $::teaish__Config(pkgindex-policy)} { |
|
|
teaish__verbose 1 msg-result "pkgIndex disabled by -tm.tcl(.in)" |
|
|
} else { |
|
|
set tpi [proj-coalesce \ |
|
|
[get-define TEAISH_PKGINDEX_TCL_IN] \ |
|
|
[get-define TEAISH_PKGINDEX_TCL]] |
|
|
proj-assert {$tpi ne ""} \ |
|
|
"TEAISH_PKGINDEX_TCL should have been set up by now" |
|
|
teaish__verbose 1 msg-result "Using pkgIndex from $tpi" |
|
|
if {0x0f & $::teaish__Config(pkgindex-policy)} { |
|
|
|
|
|
|
|
|
file delete -force -- [get-define TEAISH_PKGINDEX_TCL] |
|
|
proj-dot-ins-append [get-define TEAISH_PKGINDEX_TCL_IN] |
|
|
} else { |
|
|
teaish-dist-add [file tail $tpi] |
|
|
} |
|
|
} |
|
|
}} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if {0x0f & $::teaish__Config(pkginit-policy)} { |
|
|
file delete -force -- [get-define TEAISH_PKGINIT_TCL] |
|
|
proj-dot-ins-append [get-define TEAISH_PKGINIT_TCL_IN] \ |
|
|
[get-define TEAISH_PKGINIT_TCL] |
|
|
} |
|
|
if {0x0f & $::teaish__Config(tm-policy)} { |
|
|
file delete -force -- [get-define TEAISH_TM_TCL] |
|
|
proj-dot-ins-append [get-define TEAISH_TM_TCL_IN] |
|
|
} |
|
|
|
|
|
apply {{} { |
|
|
|
|
|
set dotIns [list] |
|
|
foreach {dIn => dOut} { |
|
|
TEAISH_TESTER_TCL_IN => TEAISH_TESTER_TCL |
|
|
TEAISH_TEST_TCL_IN => TEAISH_TEST_TCL |
|
|
TEAISH_MAKEFILE_IN => TEAISH_MAKEFILE |
|
|
} { |
|
|
lappend dotIns [get-define $dIn ""] [get-define $dOut ""] |
|
|
} |
|
|
lappend dotIns $::autosetup(srcdir)/Makefile.in Makefile |
|
|
|
|
|
|
|
|
foreach {i o} $dotIns { |
|
|
if {"" ne $i && "" ne $o} { |
|
|
|
|
|
proj-dot-ins-append $i $o |
|
|
} |
|
|
} |
|
|
}} |
|
|
|
|
|
define TEAISH_DIST_FULL \ |
|
|
[expr { |
|
|
$::teaish__Config(dist-enabled) |
|
|
&& $::teaish__Config(dist-full-enabled) |
|
|
}] |
|
|
|
|
|
define TEAISH_AUTOSETUP_DIR $::teaish__Config(core-dir) |
|
|
define TEAISH_ENABLE_DIST $::teaish__Config(dist-enabled) |
|
|
define TEAISH_ENABLE_INSTALL $::teaish__Config(install-enabled) |
|
|
define TEAISH_ENABLE_DLL $::teaish__Config(dll-enabled) |
|
|
define TEAISH_TCL $::teaish__Config(teaish.tcl) |
|
|
|
|
|
define TEAISH_DIST_FILES [join $::teaish__Config(dist-files)] |
|
|
define TEAISH_EXT_DIR [join $::teaish__Config(extension-dir)] |
|
|
define TEAISH_EXT_SRC [join $::teaish__Config(extension-src)] |
|
|
proj-setup-autoreconfig TEAISH_AUTORECONFIG |
|
|
foreach f { |
|
|
TEAISH_CFLAGS |
|
|
TEAISH_LDFLAGS |
|
|
} { |
|
|
|
|
|
define $f [join [get-define $f]] |
|
|
} |
|
|
proj-remap-autoconf-dir-vars |
|
|
set tdefs [teaish__defines_to_list] |
|
|
define TEAISH__DEFINES_MAP $tdefs |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proj-if-opt-truthy teaish-dump-defines { |
|
|
proj-file-write config.defines.txt $tdefs |
|
|
} |
|
|
proj-dot-ins-process -validate |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish__check_common_bins {} { |
|
|
if {"" eq [proj-bin-define install]} { |
|
|
proj-warn "Cannot find install binary, so 'make install' will not work." |
|
|
define BIN_INSTALL false |
|
|
} |
|
|
if {"" eq [proj-bin-define zip]} { |
|
|
proj-warn "Cannot find zip, so 'make dist.zip' will not work." |
|
|
} |
|
|
if {"" eq [proj-bin-define tar]} { |
|
|
proj-warn "Cannot find tar, so 'make dist.tgz' will not work." |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish__check_tcl {} { |
|
|
define TCLSH_CMD false |
|
|
define TCLLIBDIR "" |
|
|
define TCL_CONFIG_SH "" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proj-tclConfig-sh-to-autosetup "" |
|
|
|
|
|
|
|
|
set srcdir $::autosetup(srcdir) |
|
|
msg-result "Checking for a suitable tcl... " |
|
|
set use_tcl 1 |
|
|
set withSh [opt-val with-tclsh [proj-get-env TCLSH]] |
|
|
set tclHome [opt-val with-tcl [proj-get-env TCL_HOME]] |
|
|
if {[string match */lib $tclHome]} { |
|
|
|
|
|
|
|
|
|
|
|
regsub {/lib^} $tclHome "" tclHome |
|
|
msg-result "NOTE: stripped /lib suffix from --with-tcl=$tclHome (a TEA-ism)" |
|
|
} |
|
|
if {0} { |
|
|
|
|
|
|
|
|
if {"prefix" eq $tclHome} { |
|
|
set tclHome [get-define prefix] |
|
|
} |
|
|
} |
|
|
teaish-debug "use_tcl ${use_tcl}" |
|
|
teaish-debug "withSh=${withSh}" |
|
|
teaish-debug "tclHome=$tclHome" |
|
|
if {"" eq $withSh && "" eq $tclHome} { |
|
|
|
|
|
|
|
|
set withSh [proj-first-bin-of tclsh9.1 tclsh9.0 tclsh8.6 tclsh] |
|
|
teaish-debug "withSh=${withSh}" |
|
|
} |
|
|
|
|
|
set doConfigLookup 1 |
|
|
if {"" ne $withSh} { |
|
|
|
|
|
|
|
|
if {![file-isexec $withSh]} { |
|
|
proj-error "TCL shell $withSh is not executable" |
|
|
} else { |
|
|
define TCLSH_CMD $withSh |
|
|
|
|
|
} |
|
|
if {$doConfigLookup && |
|
|
[catch {exec $withSh $::autosetup(libdir)/find_tclconfig.tcl} result] == 0} { |
|
|
set tclHome $result |
|
|
} |
|
|
if {"" ne $tclHome && [file isdirectory $tclHome]} { |
|
|
teaish__verbose 1 msg-result "$withSh recommends the tclConfig.sh from $tclHome" |
|
|
} else { |
|
|
proj-warn "$withSh is unable to recommend a tclConfig.sh" |
|
|
set use_tcl 0 |
|
|
} |
|
|
} |
|
|
set cfg "" |
|
|
set tclSubdirs {tcl9.1 tcl9.0 tcl8.6 tcl8.5 lib} |
|
|
while {$use_tcl} { |
|
|
if {"" ne $tclHome} { |
|
|
|
|
|
if {$doConfigLookup} { |
|
|
if {[file readable "${tclHome}/tclConfig.sh"]} { |
|
|
set cfg "${tclHome}/tclConfig.sh" |
|
|
} else { |
|
|
foreach i $tclSubdirs { |
|
|
if {[file readable "${tclHome}/$i/tclConfig.sh"]} { |
|
|
set cfg "${tclHome}/$i/tclConfig.sh" |
|
|
break |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if {"" eq $cfg} { |
|
|
proj-error "No tclConfig.sh found under ${tclHome}" |
|
|
} |
|
|
} else { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set libdir [get-define libdir] |
|
|
if {[file readable "${libdir}/tclConfig.sh"]} { |
|
|
set cfg "${libdir}/tclConfig.sh" |
|
|
} else { |
|
|
foreach i $tclSubdirs { |
|
|
if {[file readable "${libdir}/$i/tclConfig.sh"]} { |
|
|
set cfg "${libdir}/$i/tclConfig.sh" |
|
|
break |
|
|
} |
|
|
} |
|
|
} |
|
|
if {![file readable $cfg]} { |
|
|
break |
|
|
} |
|
|
} |
|
|
teaish__verbose 1 msg-result "Using tclConfig.sh = $cfg" |
|
|
break |
|
|
} |
|
|
define TCL_CONFIG_SH $cfg |
|
|
|
|
|
|
|
|
|
|
|
proj-tclConfig-sh-to-autosetup $cfg |
|
|
|
|
|
if {"" eq $withSh && $cfg ne ""} { |
|
|
|
|
|
|
|
|
set tclExecPrefix [get-define TCL_EXEC_PREFIX] |
|
|
proj-assert {"" ne $tclExecPrefix} |
|
|
set tryThese [list \ |
|
|
$tclExecPrefix/bin/tclsh[get-define TCL_VERSION] \ |
|
|
$tclExecPrefix/bin/tclsh ] |
|
|
foreach trySh $tryThese { |
|
|
if {[file-isexec $trySh]} { |
|
|
set withSh $trySh |
|
|
break |
|
|
} |
|
|
} |
|
|
if {![file-isexec $withSh]} { |
|
|
proj-warn "Cannot find a usable tclsh (tried: $tryThese)" |
|
|
} |
|
|
} |
|
|
define TCLSH_CMD $withSh |
|
|
if {$use_tcl} { |
|
|
|
|
|
set tcllibdir [get-env TCLLIBDIR ""] |
|
|
set extDirName [teaish-pkginfo-get -libDir] |
|
|
if {"" eq $tcllibdir} { |
|
|
|
|
|
if {"" ne $withSh && |
|
|
[catch {exec echo "puts stdout \$auto_path" | "$withSh"} result] == 0} { |
|
|
foreach i $result { |
|
|
if {![string match //zip* $i] && [file isdirectory $i]} { |
|
|
|
|
|
|
|
|
set tcllibdir $i/$extDirName |
|
|
break |
|
|
} |
|
|
} |
|
|
} else { |
|
|
proj-error "Cannot determine TCLLIBDIR." |
|
|
} |
|
|
} |
|
|
define TCLLIBDIR $tcllibdir |
|
|
} |
|
|
|
|
|
set gotSh [file-isexec $withSh] |
|
|
set tmdir "" |
|
|
if {$gotSh} { |
|
|
catch { |
|
|
set tmli [exec echo {puts [tcl::tm::list]} | $withSh] |
|
|
|
|
|
|
|
|
|
|
|
set firstDir "" |
|
|
foreach d $tmli { |
|
|
if {"" eq $firstDir && ![string match //*:* $d]} { |
|
|
|
|
|
set firstDir $d |
|
|
} |
|
|
if {[file isdirectory $d]} { |
|
|
set tmdir $d |
|
|
break |
|
|
} |
|
|
} |
|
|
if {"" eq $tmdir} { |
|
|
set tmdir $firstDir |
|
|
} |
|
|
} |
|
|
} |
|
|
define TEAISH_TCL_TM_DIR $tmdir |
|
|
|
|
|
|
|
|
if {$gotSh} { |
|
|
teaish__verbose 1 msg-result "Using tclsh = $withSh" |
|
|
if {$cfg ne ""} { |
|
|
define HAVE_TCL 1 |
|
|
} else { |
|
|
proj-warn "Found tclsh but no tclConfig.sh." |
|
|
} |
|
|
if {"" eq $tmdir} { |
|
|
proj-warn "Did not find tcl::tm directory." |
|
|
} |
|
|
} |
|
|
show-notices |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if {!$gotSh} { |
|
|
proj-error "Did not find tclsh" |
|
|
} elseif {"" eq $cfg} { |
|
|
proj-indented-notice -error { |
|
|
Cannot find a usable tclConfig.sh file. Use --with-tcl=DIR to |
|
|
specify a directory near which tclConfig.sh can be found, or |
|
|
--with-tclsh=/path/to/tclsh to allow the tclsh binary to locate |
|
|
its tclConfig.sh, with the caveat that a symlink to tclsh, or |
|
|
wrapper script around it, e.g. ~/bin/tclsh -> |
|
|
$HOME/tcl/9.0/bin/tclsh9.1, may not work because tclsh emits |
|
|
different library paths for the former than the latter. |
|
|
} |
|
|
} |
|
|
msg-result "Using Tcl [get-define TCL_VERSION] from [get-define TCL_PREFIX]." |
|
|
teaish__tcl_platform_quirks |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish__tcl_platform_quirks {} { |
|
|
define TEAISH_POSTINST_PREREQUIRE "" |
|
|
switch -glob -- [get-define host] { |
|
|
*-haiku { |
|
|
|
|
|
|
|
|
|
|
|
foreach {k d} { |
|
|
vj TCL_MAJOR_VERSION |
|
|
vn TCL_MINOR_VERSION |
|
|
pp TCL_PACKAGE_PATH |
|
|
ld TCLLIBDIR |
|
|
} { |
|
|
set $k [get-define $d] |
|
|
} |
|
|
if {[string match /packages/* $ld]} { |
|
|
set old $ld |
|
|
set tail [file tail $ld] |
|
|
if {8 == $vj} { |
|
|
set ld "${pp}/tcl${vj}.${vn}/${tail}" |
|
|
} else { |
|
|
proj-assert {9 == $vj} |
|
|
set ld "${pp}/${tail}" |
|
|
} |
|
|
define TCLLIBDIR $ld |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
define TEAISH_POSTINST_PREREQUIRE \ |
|
|
[join [list set ::auto_path \ |
|
|
\[ linsert \$::auto_path 0 $ld \] \; \ |
|
|
]] |
|
|
proj-indented-notice [subst -nocommands -nobackslashes { |
|
|
Haiku users take note: patching target installation dir to match |
|
|
Tcl's home because Haiku's is not writable. |
|
|
|
|
|
Original : $old |
|
|
Substitute: $ld |
|
|
}] |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish__find_extension {} { |
|
|
proj-assert {!$::teaish__Config(install-mode)} |
|
|
teaish__verbose 1 msg-result "Looking for teaish extension..." |
|
|
|
|
|
|
|
|
set checkTeaishTcl {{mustHave fid dir} { |
|
|
set f [file join $dir $fid] |
|
|
if {[file readable $f]} { |
|
|
file-normalize $f |
|
|
} elseif {$mustHave} { |
|
|
proj-error "Missing required $dir/$fid" |
|
|
} |
|
|
}} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set dirBld $::autosetup(builddir) |
|
|
set dirSrc $::autosetup(srcdir) |
|
|
set extT "" |
|
|
set largv {} |
|
|
set gotHelpArg 0 |
|
|
foreach arg $::argv { |
|
|
|
|
|
switch -glob -- $arg { |
|
|
--ted=* - |
|
|
--t-e-d=* - |
|
|
--teaish-extension-dir=* { |
|
|
|
|
|
|
|
|
regexp -- {--[^=]+=(.+)} $arg - extD |
|
|
set extD [file-normalize $extD] |
|
|
if {![file isdirectory $extD]} { |
|
|
proj-error "--teaish-extension-dir value is not a directory: $extD" |
|
|
} |
|
|
set extT [apply $checkTeaishTcl 0 teaish.config $extD] |
|
|
if {"" eq $extT} { |
|
|
set extT [apply $checkTeaishTcl 1 teaish.tcl $extD] |
|
|
} |
|
|
set ::teaish__Config(extension-dir) $extD |
|
|
} |
|
|
--help { |
|
|
incr gotHelpArg |
|
|
lappend largv $arg |
|
|
} |
|
|
default { |
|
|
lappend largv $arg |
|
|
} |
|
|
} |
|
|
} |
|
|
set ::argv $largv |
|
|
|
|
|
set dirExt $::teaish__Config(extension-dir) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if {"" eq $extT} { |
|
|
set flist [list] |
|
|
proj-assert {$dirExt eq ""} |
|
|
lappend flist $dirBld/teaish.tcl $dirBld/teaish.config $dirSrc/teaish.tcl |
|
|
if {![proj-first-file-found extT $flist]} { |
|
|
if {$gotHelpArg} { |
|
|
|
|
|
|
|
|
return 0; |
|
|
} |
|
|
proj-indented-notice -error " |
|
|
Did not find any of: $flist |
|
|
|
|
|
If you are attempting an out-of-tree build, use |
|
|
--teaish-extension-dir=/path/to/extension" |
|
|
} |
|
|
} |
|
|
if {![file readable $extT]} { |
|
|
proj-error "extension tcl file is not readable: $extT" |
|
|
} |
|
|
set ::teaish__Config(teaish.tcl) $extT |
|
|
set dirExt [file dirname $extT] |
|
|
|
|
|
set ::teaish__Config(extension-dir) $dirExt |
|
|
set ::teaish__Config(blddir-is-extdir) [expr {$dirBld eq $dirExt}] |
|
|
set ::teaish__Config(dist-enabled) $::teaish__Config(blddir-is-extdir) |
|
|
set ::teaish__Config(dist-full-enabled) \ |
|
|
[expr {[file-normalize $::autosetup(srcdir)] |
|
|
eq [file-normalize $::teaish__Config(extension-dir)]}] |
|
|
|
|
|
set addDist {{file} { |
|
|
teaish-dist-add [file tail $file] |
|
|
}} |
|
|
apply $addDist $extT |
|
|
|
|
|
teaish__verbose 1 msg-result "Extension dir = [teaish-get -dir]" |
|
|
teaish__verbose 1 msg-result "Extension config = $extT" |
|
|
|
|
|
teaish-pkginfo-set -name [file tail [file dirname $extT]] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if {[proj-first-file-found extM \ |
|
|
[list \ |
|
|
$dirExt/teaish.make.in \ |
|
|
$dirExt/teaish.make \ |
|
|
]]} { |
|
|
if {[string match *.in $extM]} { |
|
|
define TEAISH_MAKEFILE_IN $extM |
|
|
define TEAISH_MAKEFILE _[file rootname [file tail $extM]] |
|
|
} else { |
|
|
define TEAISH_MAKEFILE_IN "" |
|
|
define TEAISH_MAKEFILE $extM |
|
|
} |
|
|
apply $addDist $extM |
|
|
teaish__verbose 1 msg-result "Extension makefile = $extM" |
|
|
} else { |
|
|
define TEAISH_MAKEFILE_IN "" |
|
|
define TEAISH_MAKEFILE "" |
|
|
} |
|
|
|
|
|
|
|
|
set piPolicy 0 |
|
|
if {[proj-first-file-found extI \ |
|
|
[list \ |
|
|
$dirExt/teaish.pkginit.tcl.in \ |
|
|
$dirExt/teaish.pkginit.tcl \ |
|
|
]]} { |
|
|
if {[string match *.in $extI]} { |
|
|
|
|
|
define TEAISH_PKGINIT_TCL_IN $extI |
|
|
define TEAISH_PKGINIT_TCL [file rootname [file tail $extI]] |
|
|
set piPolicy 0x01 |
|
|
} else { |
|
|
|
|
|
define TEAISH_PKGINIT_TCL_IN "" |
|
|
define TEAISH_PKGINIT_TCL $extI |
|
|
set piPolicy 0x10 |
|
|
} |
|
|
apply $addDist $extI |
|
|
teaish__verbose 1 msg-result "Extension post-load init = $extI" |
|
|
define TEAISH_PKGINIT_TCL_TAIL \ |
|
|
[file tail [get-define TEAISH_PKGINIT_TCL]] |
|
|
} |
|
|
set ::teaish__Config(pkginit-policy) $piPolicy |
|
|
|
|
|
|
|
|
set piPolicy 0 |
|
|
if {[proj-first-file-found extPI $dirExt/pkgIndex.tcl.in]} { |
|
|
|
|
|
define TEAISH_PKGINDEX_TCL_IN $extPI |
|
|
define TEAISH_PKGINDEX_TCL [file rootname [file tail $extPI]] |
|
|
apply $addDist $extPI |
|
|
set piPolicy 0x01 |
|
|
} elseif {$dirExt ne $dirSrc |
|
|
&& [proj-first-file-found extPI $dirSrc/pkgIndex.tcl.in]} { |
|
|
|
|
|
define TEAISH_PKGINDEX_TCL_IN $extPI |
|
|
define TEAISH_PKGINDEX_TCL [file rootname [file tail $extPI]] |
|
|
set piPolicy 0x02 |
|
|
} elseif {[proj-first-file-found extPI $dirExt/pkgIndex.tcl]} { |
|
|
|
|
|
define TEAISH_PKGINDEX_TCL_IN "" |
|
|
define TEAISH_PKGINDEX_TCL $extPI |
|
|
apply $addDist $extPI |
|
|
set piPolicy 0x10 |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
set ::teaish__Config(pkgindex-policy) $piPolicy |
|
|
|
|
|
|
|
|
proj-assert {"" ne $dirExt} |
|
|
set flist [list $dirExt/teaish.test.tcl.in $dirExt/teaish.test.tcl] |
|
|
if {[proj-first-file-found ttt $flist]} { |
|
|
if {[string match *.in $ttt]} { |
|
|
|
|
|
set xt _[file rootname [file tail $ttt]] |
|
|
file delete -force -- $xt |
|
|
define TEAISH_TEST_TCL $xt |
|
|
define TEAISH_TEST_TCL_IN $ttt |
|
|
} else { |
|
|
define TEAISH_TEST_TCL $ttt |
|
|
define TEAISH_TEST_TCL_IN "" |
|
|
} |
|
|
apply $addDist $ttt |
|
|
} else { |
|
|
define TEAISH_TEST_TCL "" |
|
|
define TEAISH_TEST_TCL_IN "" |
|
|
} |
|
|
|
|
|
|
|
|
set flist [list $dirExt/_teaish.tester.tcl.in $dirSrc/_teaish.tester.tcl.in] |
|
|
if {[proj-first-file-found ttt $flist]} { |
|
|
|
|
|
set xt [file rootname [file tail $ttt]] |
|
|
file delete -force -- $xt |
|
|
define TEAISH_TESTER_TCL $xt |
|
|
define TEAISH_TESTER_TCL_IN $ttt |
|
|
if {[lindex $flist 0] eq $ttt} { |
|
|
apply $addDist $ttt |
|
|
} |
|
|
unset ttt xt |
|
|
} else { |
|
|
if {[file exists [set ttt [file join $dirSrc _teaish.tester.tcl.in]]]} { |
|
|
set xt [file rootname [file tail $ttt]] |
|
|
define TEAISH_TESTER_TCL $xt |
|
|
define TEAISH_TESTER_TCL_IN $ttt |
|
|
} else { |
|
|
define TEAISH_TESTER_TCL "" |
|
|
define TEAISH_TESTER_TCL_IN "" |
|
|
} |
|
|
} |
|
|
unset flist |
|
|
|
|
|
|
|
|
|
|
|
define TEAISH_OUT_OF_EXT_TREE \ |
|
|
[expr {[file-normalize $::autosetup(builddir)] ne \ |
|
|
[file-normalize $::teaish__Config(extension-dir)]}] |
|
|
return 1 |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-cflags-add {args} { |
|
|
proj-define-amend TEAISH_CFLAGS {*}$args |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-define-to-cflag {args} { |
|
|
set flags {} |
|
|
while {[string match -* [lindex $args 0]]} { |
|
|
set arg [lindex $args 0] |
|
|
switch -exact -- $arg { |
|
|
-quote - |
|
|
-zero-undef { |
|
|
lappend flags $arg |
|
|
set args [lassign $args -] |
|
|
} |
|
|
default break |
|
|
} |
|
|
} |
|
|
if {1 == [llength $args]} { |
|
|
set args [list {*}[lindex $args 0]] |
|
|
} |
|
|
|
|
|
teaish-cflags-add [proj-define-to-cflag {*}$flags {*}$args] |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-cflags-for-tea {args} { |
|
|
set name $::teaish__PkgInfo(-name) |
|
|
set version $::teaish__PkgInfo(-version) |
|
|
set pstr [join [list $name $version]] |
|
|
teaish-cflags-add \ |
|
|
{*}$args \ |
|
|
'-DPACKAGE_VERSION="$version"' \ |
|
|
'-DPACKAGE_NAME="$name"' \ |
|
|
'-DPACKAGE_STRING="$pstr"' \ |
|
|
'-DPACKAGE_URL="[teaish-get -url]"' |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-ldflags-add {args} { |
|
|
proj-define-amend TEAISH_LDFLAGS {*}$args |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-ldflags-prepend {args} { |
|
|
teaish-ldflags-add -p {*}$args |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-src-add {args} { |
|
|
proj-parse-simple-flags args flags { |
|
|
-dist 0 {expr 1} |
|
|
-dir 0 {expr 1} |
|
|
} |
|
|
if {$flags(-dist)} { |
|
|
teaish-dist-add {*}$args |
|
|
} |
|
|
if {$flags(-dir)} { |
|
|
set xargs {} |
|
|
foreach arg $args { |
|
|
if {"" ne $arg} { |
|
|
lappend xargs [file join $::teaish__Config(extension-dir) $arg] |
|
|
} |
|
|
} |
|
|
set args $xargs |
|
|
} |
|
|
lappend ::teaish__Config(extension-src) {*}$args |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-dist-add {args} { |
|
|
if {$::teaish__Config(blddir-is-extdir)} { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lappend ::teaish__Config(dist-files) {*}$args |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-make-add {args} { |
|
|
set out [get-define TEAISH_MAKEFILE_CODE ""] |
|
|
foreach a $args { |
|
|
switch -exact -- $a { |
|
|
-bnl { set a " \\\n" } |
|
|
-bnltab { set a " \\\n\t" } |
|
|
-tab { set a "\t" } |
|
|
-nl { set a "\n" } |
|
|
-nltab { set a "\n\t" } |
|
|
} |
|
|
append out $a |
|
|
} |
|
|
define TEAISH_MAKEFILE_CODE $out |
|
|
} |
|
|
|
|
|
|
|
|
proc teaish__cleanup_rule {{tgt clean}} { |
|
|
set x [incr ::teaish__Config(teaish__cleanup_rule-counter-${tgt})] |
|
|
return ${tgt}-_${x}_ |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-make-obj {args} { |
|
|
proj-parse-simple-flags args flags { |
|
|
-clean 0 {expr 1} |
|
|
-recipe => {} |
|
|
-deps => {} |
|
|
-obj => {} |
|
|
-src => {} |
|
|
} |
|
|
|
|
|
if {"" eq $flags(-obj)} { |
|
|
set args [lassign $args flags(-obj)] |
|
|
if {"" eq $flags(-obj)} { |
|
|
proj-error "Missing -obj flag." |
|
|
} |
|
|
} |
|
|
foreach f {-deps -src} { |
|
|
set flags($f) [string trim [string map {\n " "} $flags($f)]] |
|
|
} |
|
|
foreach f {-deps -src} { |
|
|
set flags($f) [string trim $flags($f)] |
|
|
} |
|
|
|
|
|
|
|
|
teaish-make-add \ |
|
|
"# [proj-scope 1] -> [proj-scope] $flags(-obj) $flags(-src)" -nl \ |
|
|
"$flags(-obj): $flags(-src) $::teaish__Config(teaish.tcl)" |
|
|
if {[info exists flags(-deps)]} { |
|
|
teaish-make-add " " [join $flags(-deps)] |
|
|
} |
|
|
teaish-make-add -nltab |
|
|
if {[info exists flags(-recipe)]} { |
|
|
teaish-make-add [string trim $flags(-recipe)] -nl |
|
|
} else { |
|
|
teaish-make-add [join [list \$(CC.tcl) -c $flags(-src) {*}$args]] -nl |
|
|
} |
|
|
if {$flags(-clean)} { |
|
|
set rule [teaish__cleanup_rule] |
|
|
teaish-make-add \ |
|
|
"clean: $rule\n$rule:\n\trm -f \"$flags(-obj)\"\n" |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-make-clean {args} { |
|
|
if {1 == [llength $args]} { |
|
|
set args [list {*}[lindex $args 0]] |
|
|
} |
|
|
|
|
|
set tgt clean |
|
|
set rmflags "-f" |
|
|
proj-parse-simple-flags args flags { |
|
|
-dist 0 { |
|
|
set tgt distclean |
|
|
} |
|
|
-r 0 { |
|
|
set rmflags "-fr" |
|
|
} |
|
|
} |
|
|
set rule [teaish__cleanup_rule $tgt] |
|
|
teaish-make-add "# [proj-scope 1] -> [proj-scope]: [join $args]\n" |
|
|
teaish-make-add "${rule}:\n\trm ${rmflags}" |
|
|
foreach a $args { |
|
|
teaish-make-add " \"$a\"" |
|
|
} |
|
|
teaish-make-add "\n${tgt}: ${rule}\n" |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-make-config-header {filename} { |
|
|
make-config-header $filename \ |
|
|
-none {HAVE_CFLAG_* LDFLAGS_* SH_* TEAISH__* TEAISH_*_CODE} \ |
|
|
-auto {SIZEOF_* HAVE_* TEAISH_* TCL_*} \ |
|
|
-none * |
|
|
proj-touch $filename |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-feature-cache-set {key val} { |
|
|
proj-cache-set -key $key -level 1 $val |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-feature-cache-check {key tgtVar} { |
|
|
upvar $tgtVar tgt |
|
|
proj-cache-check -key $key -level 1 tgt |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish-check-cached {args} { |
|
|
proj-parse-simple-flags args flags { |
|
|
-nostatus 0 {expr 1} |
|
|
-quiet 0 {expr 1} |
|
|
-key => 1 |
|
|
-nomsg 0 {expr 1} |
|
|
-msg-0 => no |
|
|
-msg-1 => ok |
|
|
} |
|
|
set args [lassign $args msg] |
|
|
set script [join $args] |
|
|
if {"" eq $msg} { |
|
|
set msg [proj-scope 1] |
|
|
} |
|
|
if {[teaish-feature-cache-check $flags(-key) check]} { |
|
|
|
|
|
msg-checking "${msg} ... (cached) " |
|
|
|
|
|
|
|
|
msg-result $flags(-msg-[expr {0 != ${check}}]) |
|
|
|
|
|
return $check |
|
|
} else { |
|
|
if {0 == $flags(-nomsg)} { |
|
|
msg-checking "${msg} ... " |
|
|
} |
|
|
if {$flags(-quiet)} { |
|
|
incr ::autosetup(msg-quiet) |
|
|
} |
|
|
set code [catch {uplevel 1 $script} rc xopt] |
|
|
if {$flags(-quiet)} { |
|
|
incr ::autosetup(msg-quiet) -1 |
|
|
} |
|
|
|
|
|
if {$code in {0 2}} { |
|
|
teaish-feature-cache-set 1 $rc |
|
|
if {!$flags(-nostatus)} { |
|
|
msg-result $flags(-msg-[expr {0 != ${rc}}]) |
|
|
} else { |
|
|
|
|
|
|
|
|
if {[info exists ::autosetup(notices)]} { |
|
|
show-notices |
|
|
} |
|
|
} |
|
|
} else { |
|
|
|
|
|
teaish-feature-cache-set 1 0 |
|
|
} |
|
|
|
|
|
return {*}$xopt $rc |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc teaish__quote_str {asList value} { |
|
|
if {$asList} { |
|
|
return "{${value}}" |
|
|
} |
|
|
return \"[string map [list \\ \\\\ \" \\\"] $value]\" |
|
|
} |
|
|
|
|
|
# |
|
|
# Internal helper for teaish__defines_to_list. Expects to be passed |
|
|
# a name and the variadic $args which are passed to |
|
|
# teaish__defines_to_list.. If it finds a pattern match for the |
|
|
# given $name in the various $args, it returns the type flag for that |
|
|
# $name, e.g. "-str" or "-bare", else returns an empty string. |
|
|
# |
|
|
proc teaish__defs_type {name spec} { |
|
|
foreach {type patterns} $spec { |
|
|
foreach pattern $patterns { |
|
|
if {[string match $pattern $name]} { |
|
|
return $type |
|
|
} |
|
|
} |
|
|
} |
|
|
return "" |
|
|
} |
|
|
|
|
|
# |
|
|
# An internal impl detail. Requires a data type specifier, as used by |
|
|
# Autosetup's [make-config-header], and a value. Returns the formatted |
|
|
# value or the value $::teaish__Config(defs-skip) if the caller should |
|
|
# skip emitting that value. |
|
|
# |
|
|
# In addition to -str, -auto, etc., as defined by make-config-header, |
|
|
# it supports: |
|
|
# |
|
|
# -list {...} will cause non-integer values to be quoted in {...} |
|
|
# instead of quotes. |
|
|
# |
|
|
# -autolist {...} works like -auto {...} except that it falls back to |
|
|
# -list {...} type instead of -str {...} style for non-integers. |
|
|
# |
|
|
# -jsarray {...} emits the output in something which, for |
|
|
# conservative inputs, will be a valid JSON array. It can only |
|
|
# handle relatively simple values with no control characters in |
|
|
# them. |
|
|
# |
|
|
set teaish__Config(defs-skip) "-teaish__defs_format sentinel" |
|
|
proc teaish__defs_format {type value} { |
|
|
switch -exact -- $type { |
|
|
-bare { |
|
|
# Just output the value unchanged |
|
|
} |
|
|
-none { |
|
|
set value $::teaish__Config(defs-skip) |
|
|
} |
|
|
-str { |
|
|
set value [teaish__quote_str 0 $value] |
|
|
} |
|
|
-auto { |
|
|
# Automatically determine the type |
|
|
if {![string is integer -strict $value]} { |
|
|
set value [teaish__quote_str 0 $value] |
|
|
} |
|
|
} |
|
|
-autolist { |
|
|
if {![string is integer -strict $value]} { |
|
|
set value [teaish__quote_str 1 $value] |
|
|
} |
|
|
} |
|
|
-list { |
|
|
set value [teaish__quote_str 1 $value] |
|
|
} |
|
|
-jsarray { |
|
|
set ar {} |
|
|
foreach v $value { |
|
|
if {![string is integer -strict $v]} { |
|
|
set v [teaish__quote_str 0 $v] |
|
|
} |
|
|
if {$::teaish__Config(defs-skip) ne $v} { |
|
|
lappend ar $v |
|
|
} |
|
|
} |
|
|
set value [concat \[ [join $ar {, }] \]] |
|
|
} |
|
|
"" { |
|
|
# (Much later:) Why do we do this? |
|
|
set value $::teaish__Config(defs-skip) |
|
|
} |
|
|
default { |
|
|
proj-error \ |
|
|
"Unknown [proj-scope] -type ($type) called from" \ |
|
|
[proj-scope 1] |
|
|
} |
|
|
} |
|
|
return $value |
|
|
} |
|
|
|
|
|
# |
|
|
# Returns Tcl code in the form of code which evaluates to a list of |
|
|
# configure-time DEFINEs in the form {key val key2 val...}. It may |
|
|
# misbehave for values which are not numeric or simple strings. Some |
|
|
# defines are specifically filtered out of the result, either because |
|
|
# their irrelevant to teaish or because they may be arbitrarily large |
|
|
# (e.g. makefile content). |
|
|
# |
|
|
# The $args are explained in the docs for internal-use-only |
|
|
# [teaish__defs_format]. The default mode is -autolist. |
|
|
# |
|
|
proc teaish__defines_to_list {args} { |
|
|
set lines {} |
|
|
lappend lines "\{" |
|
|
set skipper $::teaish__Config(defs-skip) |
|
|
set args [list \ |
|
|
-none { |
|
|
TEAISH__* |
|
|
TEAISH_*_CODE |
|
|
AM_* AS_* |
|
|
} \ |
|
|
{*}$args \ |
|
|
-autolist *] |
|
|
foreach d [lsort [dict keys [all-defines]]] { |
|
|
set type [teaish__defs_type $d $args] |
|
|
set value [teaish__defs_format $type [get-define $d]] |
|
|
if {$skipper ne $value} { |
|
|
lappend lines "$d $value" |
|
|
} |
|
|
} |
|
|
lappend lines "\}" |
|
|
tailcall join $lines "\n" |
|
|
} |
|
|
|
|
|
# |
|
|
# teaish__pragma ...flags |
|
|
# |
|
|
# Offers a way to tweak how teaish's core behaves in some cases, in |
|
|
# particular those which require changing how the core looks for an |
|
|
# extension and its files. |
|
|
# |
|
|
# Accepts the following flags. Those marked with [L] are safe to use |
|
|
# during initial loading of tclish.tcl (recall that most teaish APIs |
|
|
# cannot be used until [teaish-configure] is called). |
|
|
# |
|
|
# static-pkgIndex.tcl [L]: Tells teaish that ./pkgIndex.tcl is not |
|
|
# a generated file, so it will not try to overwrite or delete |
|
|
# it. Errors out if it does not find pkgIndex.tcl in the |
|
|
# extension's dir. |
|
|
# |
|
|
# no-dist [L]: tells teaish to elide the 'make dist' recipe |
|
|
# from the generated Makefile. |
|
|
# |
|
|
# no-dll [L]: tells teaish to elide the DLL-building recipe |
|
|
# from the generated Makefile. |
|
|
# |
|
|
# no-vsatisfies-error [L]: tells teaish that failure to match the |
|
|
# -vsatisfies value should simply "return" instead of "error". |
|
|
# |
|
|
# no-tester [L]: disables automatic generation of teaish.test.tcl |
|
|
# even if a copy of _teaish.tester.tcl.in is found. |
|
|
# |
|
|
# no-full-dist [L]: changes the "make dist" rules to never include |
|
|
# a copy of teaish itself. By default it will include itself only |
|
|
# if the extension lives in the same directory as teaish. |
|
|
# |
|
|
# full-dist [L]: changes the "make dist" rules to always include |
|
|
# a copy of teaish itself. |
|
|
# |
|
|
# Emits a warning message for unknown arguments. |
|
|
# |
|
|
proc teaish__pragma {args} { |
|
|
foreach arg $args { |
|
|
switch -exact -- $arg { |
|
|
|
|
|
static-pkgIndex.tcl { |
|
|
if {$::teaish__Config(tm-policy)} { |
|
|
proj-fatal -up "Cannot use pragma $arg together with -tm.tcl or -tm.tcl.in." |
|
|
} |
|
|
set tpi [file join $::teaish__Config(extension-dir) pkgIndex.tcl] |
|
|
if {[file exists $tpi]} { |
|
|
define TEAISH_PKGINDEX_TCL_IN "" |
|
|
define TEAISH_PKGINDEX_TCL $tpi |
|
|
set ::teaish__Config(pkgindex-policy) 0x20 |
|
|
} else { |
|
|
proj-error "pragma $arg: found no package-local pkgIndex.tcl\[.in]" |
|
|
} |
|
|
} |
|
|
|
|
|
no-dist { |
|
|
set ::teaish__Config(dist-enabled) 0 |
|
|
} |
|
|
|
|
|
no-install { |
|
|
set ::teaish__Config(install-enabled) 0 |
|
|
} |
|
|
|
|
|
full-dist { |
|
|
set ::teaish__Config(dist-full-enabled) 1 |
|
|
} |
|
|
|
|
|
no-full-dist { |
|
|
set ::teaish__Config(dist-full-enabled) 0 |
|
|
} |
|
|
|
|
|
no-dll { |
|
|
set ::teaish__Config(dll-enabled) 0 |
|
|
} |
|
|
|
|
|
no-vsatisfies-error { |
|
|
set ::teaish__Config(vsatisfies-error) 0 |
|
|
} |
|
|
|
|
|
no-tester { |
|
|
define TEAISH_TESTER_TCL_IN "" |
|
|
define TEAISH_TESTER_TCL "" |
|
|
} |
|
|
|
|
|
default { |
|
|
proj-error "Unknown flag: $arg" |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
# |
|
|
# @teaish-pkginfo-set ...flags |
|
|
# |
|
|
# The way to set up the initial package state. Used like: |
|
|
# |
|
|
# teaish-pkginfo-set -name foo -version 0.1.2 |
|
|
# |
|
|
# Or: |
|
|
# |
|
|
# teaish-pkginfo-set ?-vars|-subst? {-name foo -version 0.1.2} |
|
|
# |
|
|
# The latter may be easier to write for a multi-line invocation. |
|
|
# |
|
|
# For the second call form, passing the -vars flag tells it to perform |
|
|
# a [subst] of (only) variables in the {...} part from the calling |
|
|
# scope. The -subst flag will cause it to [subst] the {...} with |
|
|
# command substitution as well (but no backslash substitution). When |
|
|
# using -subst for string concatenation, e.g. with -libDir |
|
|
# foo[get-version-number], be sure to wrap the value in braces: |
|
|
# -libDir {foo[get-version-number]}. |
|
|
# |
|
|
# Each pkginfo flag corresponds to one piece of extension package |
|
|
# info. Teaish provides usable default values for all of these flags, |
|
|
# but at least the -name and -version should be set by clients. |
|
|
# e.g. the default -name is the directory name the extension lives in, |
|
|
# which may change (e.g. when building it from a "make dist" bundle). |
|
|
# |
|
|
# The flags: |
|
|
# |
|
|
# -name theName: The extension's name. It defaults to the name of the |
|
|
# directory containing the extension. (In TEA this would be the |
|
|
# PACKAGE_NAME, not to be confused with...) |
|
|
# |
|
|
# -name.pkg pkg-provide-name: The extension's name for purposes of |
|
|
# Tcl_PkgProvide(), [package require], and friends. It defaults to |
|
|
# the `-name`, and is normally the same, but some projects (like |
|
|
# SQLite) have a different name here than they do in their |
|
|
# historical TEA PACKAGE_NAME. |
|
|
# |
|
|
# -version version: The extension's package version. Defaults to |
|
|
# 0.0.0. |
|
|
# |
|
|
# -libDir dirName: The base name of the directory into which this |
|
|
# extension should be installed. It defaults to a concatenation of |
|
|
# `-name.pkg` and `-version`. |
|
|
# |
|
|
# -loadPrefix prefix: For use as the second argument passed to |
|
|
# Tcl's `load` command in the package-loading process. It defaults |
|
|
# to title-cased `-name.pkg` because Tcl's `load` plugin system |
|
|
# expects it in that form. |
|
|
# |
|
|
# -options {...}: If provided, it must be a list compatible with |
|
|
# Autosetup's `options-add` function. These can also be set up via |
|
|
# `teaish-options`. |
|
|
# |
|
|
# -vsatisfies {{...} ...}: Expects a list-of-lists of conditions |
|
|
# for Tcl's `package vsatisfies` command: each list entry is a |
|
|
# sub-list of `{PkgName Condition...}`. Teaish inserts those |
|
|
# checks via its default pkgIndex.tcl.in and _teaish.tester.tcl.in |
|
|
# templates to verify that the system's package dependencies meet |
|
|
# these requirements. The default value is `{{Tcl 8.5-}}` (recall |
|
|
# that it's a list-of-lists), as 8.5 is the minimum Tcl version |
|
|
# teaish will run on, but some extensions may require newer |
|
|
# versions or dependencies on other packages. As a special case, |
|
|
# if `-vsatisfies` is given a single token, e.g. `8.6-`, then it |
|
|
# is transformed into `{Tcl $thatToken}`, i.e. it checks the Tcl |
|
|
# version which the package is being run with. If given multiple |
|
|
# lists, each `package provides` check is run in the given |
|
|
# order. Failure to meet a `vsatisfies` condition triggers an |
|
|
# error. |
|
|
# |
|
|
# -url {...}: an optional URL for the extension. |
|
|
# |
|
|
# -pragmas {...} A list of infrequently-needed lower-level |
|
|
# directives which can influence teaish, including: |
|
|
# |
|
|
# static-pkgIndex.tcl: tells teaish that the client manages their |
|
|
# own pkgIndex.tcl, so that teaish won't try to overwrite it |
|
|
# using a template. |
|
|
# |
|
|
# no-dist: tells teaish to elide the "make dist" recipe from the |
|
|
# makefile so that the client can implement it. |
|
|
# |
|
|
# no-dll: tells teaish to elide the makefile rules which build |
|
|
# the DLL, as well as any templated test script and pkgIndex.tcl |
|
|
# references to them. The intent here is to (A) support |
|
|
# client-defined build rules for the DLL and (B) eventually |
|
|
# support script-only extensions. |
|
|
# |
|
|
# Unsupported flags or pragmas will trigger an error. |
|
|
# |
|
|
# Potential pothole: setting certain state, e.g. -version, after the |
|
|
# initial call requires recalculating of some [define]s. Any such |
|
|
# changes should be made as early as possible in teaish-configure so |
|
|
# that any later use of those [define]s gets recorded properly (not |
|
|
# with the old value). This is particularly relevant when it is not |
|
|
# possible to determine the -version or -name until teaish-configure |
|
|
# has been called, and it's updated dynamically from |
|
|
# teaish-configure. Notably: |
|
|
# |
|
|
# - If -version or -name are updated, -libDir will almost certainly |
|
|
# need to be explicitly set along with them. |
|
|
# |
|
|
# - If -name is updated, -loadPrefix probably needs to be as well. |
|
|
# |
|
|
proc teaish-pkginfo-set {args} { |
|
|
set doVars 0 |
|
|
set doCommands 0 |
|
|
set xargs $args |
|
|
set recalc {} |
|
|
foreach arg $args { |
|
|
switch -exact -- $arg { |
|
|
-vars { |
|
|
incr doVars |
|
|
set xargs [lassign $xargs -] |
|
|
} |
|
|
-subst { |
|
|
incr doVars |
|
|
incr doCommands |
|
|
set xargs [lassign $xargs -] |
|
|
} |
|
|
default { |
|
|
break |
|
|
} |
|
|
} |
|
|
} |
|
|
set args $xargs |
|
|
unset xargs |
|
|
if {1 == [llength $args] && [llength [lindex $args 0]] > 1} { |
|
|
# Transform a single {...} arg into the canonical call form |
|
|
set a [list {*}[lindex $args 0]] |
|
|
if {$doVars || $doCommands} { |
|
|
set sflags -nobackslashes |
|
|
if {!$doCommands} { |
|
|
lappend sflags -nocommands |
|
|
} |
|
|
set a [uplevel 1 [list subst {*}$sflags $a]] |
|
|
} |
|
|
set args $a |
|
|
} |
|
|
set sentinel "<nope>" |
|
|
set flagDefs [list] |
|
|
foreach {f d} $::teaish__Config(pkginfo-f2d) { |
|
|
lappend flagDefs $f => $sentinel |
|
|
} |
|
|
proj-parse-simple-flags args flags $flagDefs |
|
|
if {[llength $args]} { |
|
|
proj-error -up "Too many (or unknown) arguments to [proj-scope]: $args" |
|
|
} |
|
|
foreach {f d} $::teaish__Config(pkginfo-f2d) { |
|
|
if {$sentinel eq [set v $flags($f)]} continue |
|
|
switch -exact -- $f { |
|
|
|
|
|
-options { |
|
|
proj-assert {"" eq $d} |
|
|
options-add $v |
|
|
} |
|
|
|
|
|
-pragmas { |
|
|
teaish__pragma {*}$v |
|
|
} |
|
|
|
|
|
-vsatisfies { |
|
|
if {1 == [llength $v] && 1 == [llength [lindex $v 0]]} { |
|
|
# Transform X to {Tcl $X} |
|
|
set v [list [join [list Tcl $v]]] |
|
|
} |
|
|
define $d $v |
|
|
} |
|
|
|
|
|
-pkgInit.tcl - |
|
|
-pkgInit.tcl.in { |
|
|
if {0x22 & $::teaish__Config(pkginit-policy)} { |
|
|
proj-fatal "Cannot use -pkgInit.tcl(.in) more than once." |
|
|
} |
|
|
set x [file join $::teaish__Config(extension-dir) $v] |
|
|
set tTail [file tail $v] |
|
|
if {"-pkgInit.tcl.in" eq $f} { |
|
|
# Generate pkginit file X from X.in |
|
|
set pI 0x02 |
|
|
set tIn $x |
|
|
set tOut [file rootname $tTail] |
|
|
set other -pkgInit.tcl |
|
|
} else { |
|
|
# Static pkginit file X |
|
|
set pI 0x20 |
|
|
set tIn "" |
|
|
set tOut $x |
|
|
set other -pkgInit.tcl.in |
|
|
} |
|
|
set ::teaish__Config(pkginit-policy) $pI |
|
|
set ::teaish__PkgInfo($other) {} |
|
|
define TEAISH_PKGINIT_TCL_IN $tIn |
|
|
define TEAISH_PKGINIT_TCL $tOut |
|
|
define TEAISH_PKGINIT_TCL_TAIL $tTail |
|
|
teaish-dist-add $v |
|
|
set v $x |
|
|
} |
|
|
|
|
|
-src { |
|
|
set d $::teaish__Config(extension-dir) |
|
|
foreach f $v { |
|
|
lappend ::teaish__Config(dist-files) $f |
|
|
lappend ::teaish__Config(extension-src) $d/$f |
|
|
lappend ::teaish__PkgInfo(-src) $f |
|
|
# ^^^ so that default-value initialization in |
|
|
# teaish-configure-core recognizes that it's been set. |
|
|
} |
|
|
} |
|
|
|
|
|
-tm.tcl - |
|
|
-tm.tcl.in { |
|
|
if {0x30 & $::teaish__Config(pkgindex-policy)} { |
|
|
proj-fatal "Cannot use $f together with a pkgIndex.tcl." |
|
|
} elseif {$::teaish__Config(tm-policy)} { |
|
|
proj-fatal "Cannot use -tm.tcl(.in) more than once." |
|
|
} |
|
|
set x [file join $::teaish__Config(extension-dir) $v] |
|
|
if {"-tm.tcl.in" eq $f} { |
|
|
# Generate tm file X from X.in |
|
|
set pT 0x02 |
|
|
set pI 0x100 |
|
|
set tIn $x |
|
|
set tOut [file rootname [file tail $v]] |
|
|
set other -tm.tcl |
|
|
} else { |
|
|
# Static tm file X |
|
|
set pT 0x20 |
|
|
set pI 0x200 |
|
|
set tIn "" |
|
|
set tOut $x |
|
|
set other -tm.tcl.in |
|
|
} |
|
|
set ::teaish__Config(pkgindex-policy) $pI |
|
|
set ::teaish__Config(tm-policy) $pT |
|
|
set ::teaish__PkgInfo($other) {} |
|
|
define TEAISH_TM_TCL_IN $tIn |
|
|
define TEAISH_TM_TCL $tOut |
|
|
define TEAISH_PKGINDEX_TCL "" |
|
|
define TEAISH_PKGINDEX_TCL_IN "" |
|
|
define TEAISH_PKGINDEX_TCL_TAIL "" |
|
|
teaish-dist-add $v |
|
|
teaish__pragma no-dll |
|
|
set v $x |
|
|
} |
|
|
|
|
|
default { |
|
|
proj-assert {"" ne $d} |
|
|
define $d $v |
|
|
} |
|
|
} |
|
|
set ::teaish__PkgInfo($f) $v |
|
|
if {$f in {-name -version -libDir -loadPrefix}} { |
|
|
lappend recalc $f |
|
|
} |
|
|
} |
|
|
if {"" ne $recalc} { |
|
|
teaish__define_pkginfo_derived $recalc |
|
|
} |
|
|
} |
|
|
|
|
|
# |
|
|
# @teaish-pkginfo-get ?arg? |
|
|
# |
|
|
# If passed no arguments, it returns the extension config info in the |
|
|
# same form accepted by teaish-pkginfo-set. |
|
|
# |
|
|
# If passed one -flagname arg then it returns the value of that config |
|
|
# option. |
|
|
# |
|
|
# Else it treats arg as the name of caller-scoped variable to |
|
|
# which this function assigns an array containing the configuration |
|
|
# state of this extension, in the same structure accepted by |
|
|
# teaish-pkginfo-set. In this case it returns an empty string. |
|
|
# |
|
|
proc teaish-pkginfo-get {args} { |
|
|
set cases {} |
|
|
set argc [llength $args] |
|
|
set rv {} |
|
|
switch -exact $argc { |
|
|
0 { |
|
|
# Return a list of (-flag value) pairs |
|
|
lappend cases default {{ |
|
|
if {[info exists ::teaish__PkgInfo($flag)]} { |
|
|
lappend rv $flag $::teaish__PkgInfo($flag) |
|
|
} else { |
|
|
lappend rv $flag [get-define $defName] |
|
|
} |
|
|
}} |
|
|
} |
|
|
|
|
|
1 { |
|
|
set arg $args |
|
|
if {[string match -* $arg]} { |
|
|
# Return the corresponding -flag's value |
|
|
lappend cases $arg {{ |
|
|
if {[info exists ::teaish__PkgInfo($flag)]} { |
|
|
return $::teaish__PkgInfo($flag) |
|
|
} else { |
|
|
return [get-define $defName] |
|
|
} |
|
|
}} |
|
|
} else { |
|
|
# Populate target with an array of (-flag value). |
|
|
upvar $arg tgt |
|
|
array set tgt {} |
|
|
lappend cases default {{ |
|
|
if {[info exists ::teaish__PkgInfo($flag)]} { |
|
|
set tgt($flag) $::teaish__PkgInfo($flag) |
|
|
} else { |
|
|
set tgt($flag) [get-define $defName] |
|
|
} |
|
|
}} |
|
|
} |
|
|
} |
|
|
|
|
|
default { |
|
|
proj-error "invalid arg count from [proj-scope 1]" |
|
|
} |
|
|
} |
|
|
|
|
|
foreach {flag defName} $::teaish__Config(pkginfo-f2d) { |
|
|
switch -exact -- $flag [join $cases] |
|
|
} |
|
|
if {0 == $argc} { return $rv } |
|
|
} |
|
|
|
|
|
# (Re)set some defines based on pkginfo state. $flags is the list of |
|
|
# pkginfo -flags which triggered this, or "*" for the initial call. |
|
|
proc teaish__define_pkginfo_derived {flags} { |
|
|
set all [expr {{*} in $flags}] |
|
|
if {$all || "-version" in $flags || "-name" in $flags} { |
|
|
set name $::teaish__PkgInfo(-name) ; # _not_ -name.pkg |
|
|
if {[info exists ::teaish__PkgInfo(-version)]} { |
|
|
set pkgver $::teaish__PkgInfo(-version) |
|
|
set libname "lib" |
|
|
if {[string match *-cygwin [get-define host]]} { |
|
|
set libname cyg |
|
|
} |
|
|
define TEAISH_DLL8_BASENAME $libname$name$pkgver |
|
|
define TEAISH_DLL9_BASENAME ${libname}tcl9$name$pkgver |
|
|
set ext [get-define TARGET_DLLEXT] |
|
|
define TEAISH_DLL8 [get-define TEAISH_DLL8_BASENAME]$ext |
|
|
define TEAISH_DLL9 [get-define TEAISH_DLL9_BASENAME]$ext |
|
|
} |
|
|
} |
|
|
if {$all || "-libDir" in $flags} { |
|
|
if {[info exists ::teaish__PkgInfo(-libDir)]} { |
|
|
define TCLLIBDIR \ |
|
|
[file dirname [get-define TCLLIBDIR]]/$::teaish__PkgInfo(-libDir) |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
# |
|
|
# @teaish-checks-queue -pre|-post args... |
|
|
# |
|
|
# Queues one or more arbitrary "feature test" functions to be run when |
|
|
# teaish-checks-run is called. $flag must be one of -pre or -post to |
|
|
# specify whether the tests should be run before or after |
|
|
# teaish-configure is run. Each additional arg is the name of a |
|
|
# feature-test proc. |
|
|
# |
|
|
proc teaish-checks-queue {flag args} { |
|
|
if {$flag ni {-pre -post}} { |
|
|
proj-error "illegal flag: $flag" |
|
|
} |
|
|
lappend ::teaish__Config(queued-checks${flag}) {*}$args |
|
|
} |
|
|
|
|
|
# |
|
|
# @teaish-checks-run -pre|-post |
|
|
# |
|
|
# Runs all feature checks queued using teaish-checks-queue |
|
|
# then cleares the queue. |
|
|
# |
|
|
proc teaish-checks-run {flag} { |
|
|
if {$flag ni {-pre -post}} { |
|
|
proj-error "illegal flag: $flag" |
|
|
} |
|
|
#puts "*** running $flag: $::teaish__Config(queued-checks${flag})" |
|
|
set foo 0 |
|
|
foreach f $::teaish__Config(queued-checks${flag}) { |
|
|
if {![teaish-feature-cache-check $f foo]} { |
|
|
set v [$f] |
|
|
teaish-feature-cache-set $f $v |
|
|
} |
|
|
} |
|
|
set ::teaish__Config(queued-checks${flag}) {} |
|
|
} |
|
|
|
|
|
# |
|
|
# A general-purpose getter for various teaish state. Requires one |
|
|
# flag, which determines its result value. Flags marked with [L] below |
|
|
# are safe for using at load-time, before teaish-pkginfo-set is called |
|
|
# |
|
|
# -dir [L]: returns the extension's directory, which may differ from |
|
|
# the teaish core dir or the build dir. |
|
|
# |
|
|
# -teaish-home [L]: the "home" dir of teaish itself, which may |
|
|
# differ from the extension dir or build dir. |
|
|
# |
|
|
# -build-dir [L]: the build directory (typically the current working |
|
|
# -dir). |
|
|
# |
|
|
# Any of the teaish-pkginfo-get/get flags: returns the same as |
|
|
# teaish-pkginfo-get. Not safe for use until teaish-pkginfo-set has |
|
|
# been called. |
|
|
# |
|
|
# Triggers an error if passed an unknown flag. |
|
|
# |
|
|
proc teaish-get {flag} { |
|
|
#-teaish.tcl {return $::teaish__Config(teaish.tcl)} |
|
|
switch -exact -- $flag { |
|
|
-dir { |
|
|
return $::teaish__Config(extension-dir) |
|
|
} |
|
|
-teaish-home { |
|
|
return $::autosetup(srcdir) |
|
|
} |
|
|
-build-dir { |
|
|
return $::autosetup(builddir) |
|
|
} |
|
|
default { |
|
|
if {[info exists ::teaish__PkgInfo($flag)]} { |
|
|
return $::teaish__PkgInfo($flag) |
|
|
} |
|
|
} |
|
|
} |
|
|
proj-error "Unhandled flag: $flag" |
|
|
} |
|
|
|
|
|
# |
|
|
# Handles --teaish-create-extension=TARGET-DIR |
|
|
# |
|
|
proc teaish__create_extension {dir} { |
|
|
set force [opt-bool teaish-force] |
|
|
if {"" eq $dir} { |
|
|
proj-error "--teaish-create-extension=X requires a directory name." |
|
|
} |
|
|
file mkdir $dir/generic |
|
|
set cwd [pwd] |
|
|
#set dir [file-normalize [file join $cwd $dir]] |
|
|
teaish__verbose 1 msg-result "Created dir $dir" |
|
|
cd $dir |
|
|
if {!$force} { |
|
|
# Ensure that we don't blindly overwrite anything |
|
|
foreach f { |
|
|
generic/teaish.c |
|
|
teaish.tcl |
|
|
teaish.make.in |
|
|
teaish.test.tcl |
|
|
} { |
|
|
if {[file exists $f]} { |
|
|
error "Cowardly refusing to overwrite $dir/$f. Use --teaish-force to overwrite." |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
set name [file tail $dir] |
|
|
set pkgName $name |
|
|
set version 0.0.1 |
|
|
set loadPrefix [string totitle $pkgName] |
|
|
set content {teaish-pkginfo-set } |
|
|
#puts "0 content=$content" |
|
|
if {[opt-str teaish-extension-pkginfo epi]} { |
|
|
set epi [string trim $epi] |
|
|
if {[string match "*\n*" $epi]} { |
|
|
set epi "{$epi}" |
|
|
} elseif {![string match "{*}" $epi]} { |
|
|
append content "\{" $epi "\}" |
|
|
} else { |
|
|
append content $epi |
|
|
} |
|
|
#puts "2 content=$content\nepi=$epi" |
|
|
} else { |
|
|
append content [subst -nocommands -nobackslashes {{ |
|
|
-name ${name} |
|
|
-name.pkg ${pkgName} |
|
|
-name.dist ${pkgName} |
|
|
-version ${version} |
|
|
-loadPrefix $loadPrefix |
|
|
-libDir ${name}${version} |
|
|
-vsatisfies {{Tcl 8.5-}} |
|
|
-url {} |
|
|
-options {} |
|
|
-pragmas {full-dist} |
|
|
}}] |
|
|
#puts "3 content=$content" |
|
|
} |
|
|
#puts "1 content=$content" |
|
|
append content "\n" { |
|
|
#proc teaish-options {} { |
|
|
# Return a list and/or use \[options-add\] to add new |
|
|
# configure flags. This is called before teaish's |
|
|
# bootstrapping is finished, so only teaish-* |
|
|
# APIs which are explicitly noted as being safe |
|
|
# early on may be used here. Any autosetup-related |
|
|
# APIs may be used here. |
|
|
# |
|
|
# Return an empty string if there are no options to |
|
|
# add or if they are added using \[options-add\]. |
|
|
# |
|
|
# If there are no options to add, this proc need |
|
|
# not be defined. |
|
|
#} |
|
|
|
|
|
# Called by teaish once bootstrapping is complete. |
|
|
# This function is responsible for the client-specific |
|
|
# parts of the configuration process. |
|
|
proc teaish-configure {} { |
|
|
teaish-src-add -dir -dist generic/teaish.c |
|
|
teaish-define-to-cflag -quote TEAISH_PKGNAME TEAISH_VERSION |
|
|
|
|
|
# TODO: your code goes here.. |
|
|
} |
|
|
}; # $content |
|
|
proj-file-write teaish.tcl $content |
|
|
teaish__verbose 1 msg-result "Created teaish.tcl" |
|
|
|
|
|
set content "# Teaish test script. |
|
|
|
|
|
|
|
|
|
|
|
" |
|
|
proj-file-write teaish.test.tcl $content |
|
|
teaish__verbose 1 msg-result "Created teaish.test.tcl" |
|
|
|
|
|
set content [subst -nocommands -nobackslashes { |
|
|
#include <tcl.h> |
|
|
static int |
|
|
${loadPrefix}_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]){ |
|
|
Tcl_SetObjResult(interp, Tcl_NewStringObj("this is the ${name} extension", -1)); |
|
|
return TCL_OK; |
|
|
} |
|
|
|
|
|
extern int DLLEXPORT ${loadPrefix}_Init(Tcl_Interp *interp){ |
|
|
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { |
|
|
return TCL_ERROR; |
|
|
} |
|
|
if (Tcl_PkgProvide(interp, TEAISH_PKGNAME, TEAISH_VERSION) == TCL_ERROR) { |
|
|
return TCL_ERROR; |
|
|
} |
|
|
Tcl_CreateObjCommand(interp, TEAISH_PKGNAME, ${loadPrefix}_Cmd, NULL, NULL); |
|
|
return TCL_OK; |
|
|
} |
|
|
}] |
|
|
proj-file-write generic/teaish.c $content |
|
|
teaish__verbose 1 msg-result "Created generic/teaish.c" |
|
|
|
|
|
set content "# teaish makefile for the ${name} extension |
|
|
|
|
|
|
|
|
|
|
|
" |
|
|
proj-file-write teaish.make.in $content |
|
|
teaish__verbose 1 msg-result "Created teaish.make.in" |
|
|
|
|
|
msg-result "Created new extension \[$dir\]." |
|
|
|
|
|
cd $cwd |
|
|
set ::teaish__Config(install-ext-dir) $dir |
|
|
} |
|
|
|
|
|
# |
|
|
# Internal helper for teaish__install |
|
|
# |
|
|
proc teaish__install_file {f destDir force} { |
|
|
set dest $destDir/[file tail $f] |
|
|
if {[file isdirectory $f]} { |
|
|
file mkdir $dest |
|
|
} elseif {!$force && [file exists $dest]} { |
|
|
array set st1 [file stat $f] |
|
|
array set st2 [file stat $dest] |
|
|
if {($st1(mtime) == $st2(mtime)) |
|
|
&& ($st1(size) == $st2(size))} { |
|
|
if {[file tail $f] in { |
|
|
pkgIndex.tcl.in |
|
|
_teaish.tester.tcl.in |
|
|
}} { |
|
|
# Assume they're the same. In the scope of the "make dist" |
|
|
# rules, this happens legitimately when an extension with a |
|
|
# copy of teaish installed in the same dir assumes that the |
|
|
# pkgIndex.tcl.in and _teaish.tester.tcl.in belong to the |
|
|
# extension, whereas teaish believes they belong to teaish. |
|
|
# So we end up with dupes of those. |
|
|
return |
|
|
} |
|
|
} |
|
|
proj-error -up "Cowardly refusing to overwrite \[$dest\]." \ |
|
|
"Use --teaish-force to enable overwriting." |
|
|
} else { |
|
|
# file copy -force $f $destDir; # loses +x bit |
|
|
# |
|
|
# JimTcl doesn't have [file attribute], so we can't use that here |
|
|
# (in the context of an autosetup configure script). |
|
|
exec cp -p $f $dest |
|
|
} |
|
|
} |
|
|
|
|
|
# |
|
|
# Installs a copy of teaish, with autosetup, to $dDest, which defaults |
|
|
# to the --teaish-install=X or --teash-create-extension=X dir. Won't |
|
|
# overwrite files unless --teaish-force is used. |
|
|
# |
|
|
proc teaish__install {{dDest ""}} { |
|
|
if {$dDest in {auto ""}} { |
|
|
set dDest [opt-val teaish-install] |
|
|
if {$dDest in {auto ""}} { |
|
|
if {[info exists ::teaish__Config(install-ext-dir)]} { |
|
|
set dDest $::teaish__Config(install-ext-dir) |
|
|
} |
|
|
} |
|
|
} |
|
|
set force [opt-bool teaish-force] |
|
|
if {$dDest in {auto ""}} { |
|
|
proj-error "Cannot determine installation directory." |
|
|
} elseif {!$force && [file exists $dDest/auto.def]} { |
|
|
proj-error \ |
|
|
"Target dir looks like it already contains teaish and/or autosetup: $dDest" \ |
|
|
"\nUse --teaish-force to overwrite it." |
|
|
} |
|
|
|
|
|
set dSrc $::autosetup(srcdir) |
|
|
set dAS $::autosetup(libdir) |
|
|
set dAST $::teaish__Config(core-dir) |
|
|
set dASTF $dAST/feature |
|
|
teaish__verbose 1 msg-result "Installing teaish to \[$dDest\]..." |
|
|
if {$::teaish__Config(verbose)>1} { |
|
|
msg-result "dSrc = $dSrc" |
|
|
msg-result "dAS = $dAS" |
|
|
msg-result "dAST = $dAST" |
|
|
msg-result "dASTF = $dASTF" |
|
|
msg-result "dDest = $dDest" |
|
|
} |
|
|
|
|
|
# Dest subdirs... |
|
|
set ddAS $dDest/autosetup |
|
|
set ddAST $ddAS/teaish |
|
|
set ddASTF $ddAST/feature |
|
|
foreach {srcDir destDir} [list \ |
|
|
$dAS $ddAS \ |
|
|
$dAST $ddAST \ |
|
|
$dASTF $ddASTF \ |
|
|
] { |
|
|
teaish__verbose 1 msg-result "Copying files to $destDir..." |
|
|
file mkdir $destDir |
|
|
foreach f [glob -nocomplain -directory $srcDir *] { |
|
|
if {[string match {*~} $f] || [string match "#*#" [file tail $f]]} { |
|
|
# Editor-generated backups and emacs lock files |
|
|
continue |
|
|
} |
|
|
teaish__verbose 2 msg-result "\t$f" |
|
|
teaish__install_file $f $destDir $force |
|
|
} |
|
|
} |
|
|
teaish__verbose 1 msg-result "Copying files to $dDest..." |
|
|
foreach f { |
|
|
auto.def configure Makefile.in pkgIndex.tcl.in |
|
|
_teaish.tester.tcl.in |
|
|
} { |
|
|
teaish__verbose 2 msg-result "\t$f" |
|
|
teaish__install_file $dSrc/$f $dDest $force |
|
|
} |
|
|
set ::teaish__Config(install-self-dir) $dDest |
|
|
msg-result "Teaish $::teaish__Config(version) installed in \[$dDest\]." |
|
|
} |
|
|
|