summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2017-01-13 20:09:48 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2017-01-13 20:09:48 (GMT)
commita7489af757aca1fe38a1f8421e85231f7547e196 (patch)
tree7973b489aa2aefe95b34092c6a9005822d435c75
parentedea206c533053ec8d8a0851685c87551d035da3 (diff)
downloadblt-a7489af757aca1fe38a1f8421e85231f7547e196.zip
blt-a7489af757aca1fe38a1f8421e85231f7547e196.tar.gz
blt-a7489af757aca1fe38a1f8421e85231f7547e196.tar.bz2
update TEA 3.10
-rw-r--r--tclconfig/ChangeLog37
-rw-r--r--tclconfig/config.tcl.in82
-rw-r--r--tclconfig/practcl.tcl4923
-rw-r--r--tclconfig/tcl.m4564
4 files changed, 5470 insertions, 136 deletions
diff --git a/tclconfig/ChangeLog b/tclconfig/ChangeLog
index ffda2bb..9504def 100644
--- a/tclconfig/ChangeLog
+++ b/tclconfig/ChangeLog
@@ -1,32 +1,55 @@
+2016-03-11 Sean Woods <yoda@etoyoc.com>
+ *tcl.m4 Fixed the search for Tcl and Wish shells under MinGW. Static builds and threaded builds
+ get an "s" or "t" added to the name.
+
+2015-08-28 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * tcl.m4: Rfe [00189c4afc]: Allow semi-static UCRT build on
+ Windows with VC 14.0
+
+2013-10-08 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * tcl.m4: Bug [172223e008]: Wrong filename in
+ --disable-shared compile on MinGW
+
+2013-10-04 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * tcl.m4: stub library is no longer linked with msvcrt??.dll.
+
+2013-10-01 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * tcl.m4: Workaround for MinGW bug #2065: "gcc --shared" links
+ with libgcc_s_dw2-1.dll when using 64-bit division in C
+
2013-07-04 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/tcl.m4: Bug [3324676]: AC_PROG_INSTALL incompat,
+ * tcl.m4: Bug [3324676]: AC_PROG_INSTALL incompat,
Bug [3606445]: Unneeded -DHAVE_NO_SEH=1 when not building on Windows
2013-07-02 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4
+ * tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4
(thanks to Brian Griffin)
2013-06-20 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/tcl.m4: Use X11/Xlib.h for checking where X11 can be found
+ * tcl.m4: Use X11/Xlib.h for checking where X11 can be found
in stead of X11/XIntrinsic.h. Suggested by Pietro Cerutti.
2013-06-04 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/tcl.m4: Eliminate NO_VIZ macro as current
+ * tcl.m4: Eliminate NO_VIZ macro as current
zlib uses HAVE_HIDDEN in stead. One more last-moment
fix for FreeBSD by Pietro Cerutti
2013-05-19 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/tcl.m4: Fix for FreeBSD, and remove support for old
- FreeBSD versions. Patch by Pietro Cerutti
+ * tcl.m4: Fix for FreeBSD, and remove support for old
+ FreeBSD versions. Patch by Pietro Cerutti
2013-03-12 Jan Nijtmans <nijtmans@users.sf.net>
- * unix/tcl.m4: Patch by Andrew Shadura, providing better support for
+ * tcl.m4: Patch by Andrew Shadura, providing better support for
* three architectures they have in Debian.
2012-08-07 Stuart Cassoff <stwo@users.sourceforge.net>
diff --git a/tclconfig/config.tcl.in b/tclconfig/config.tcl.in
new file mode 100644
index 0000000..ffc1c9d
--- /dev/null
+++ b/tclconfig/config.tcl.in
@@ -0,0 +1,82 @@
+###
+# Tcl Parsable version of data from xxxConfig.sh
+###
+name {@PACKAGE_NAME@}
+version {@PACKAGE_VERSION@}
+libfile {@PKG_LIB_FILE@}
+srcdir {@srcdir@}
+prefix {@prefix@}
+exec_prefix {@exec_prefix@}
+exeext {@EXEEXT@}
+tk {@TEA_TK_EXTENSION@}
+
+bindir {@bindir@}
+libdir {@libdir@}
+includedir {@includedir@}
+datarootdir {@datarootdir@}
+datadir {@datadir@}
+mandir {@mandir@}
+cleanfiles {@CLEANFILES@}
+
+AR {@AR@}
+CC {@CC@}
+CFLAGS {@CFLAGS@}
+CFLAGS_DEBUG {@CFLAGS_DEBUG@}
+CFLAGS_OPTIMIZE {@CFLAGS_OPTIMIZE@}
+CFLAGS_DEFAULT {@CFLAGS_DEFAULT@}
+CFLAGS_WARNING {@CFLAGS_WARNING@}
+CPPFLAGS {@CPPFLAGS@}
+DEFS {@DEFS@ @PKG_CFLAGS@}
+EXEEXT {@EXEEXT@}
+LDFLAGS {@LDFLAGS@}
+LDFLAGS_DEFAULT {@LDFLAGS_DEFAULT@}
+LIBS {@PKG_LIBS@ @LIBS@}
+MAKE_LIB {@MAKE_LIB@}
+MAKE_SHARED_LIB {@MAKE_SHARED_LIB@}
+MAKE_STATIC_LIB {@MAKE_STATIC_LIB@}
+MAKE_STUB_LIB {@MAKE_STUB_LIB@}
+OBJEXT {@OBJEXT@}
+PKG_CFLAGS {@PKG_CFLAGS@}
+RANLIB {@RANLIB@}
+RANLIB_STUB {@RANLIB_STUB@}
+
+SHELL {@SHELL@}
+
+SHARED_BUILD {@SHARED_BUILD@}
+
+SHLIB_CFLAGS {@SHLIB_CFLAGS@}
+SHLIB_LD {@SHLIB_LD@}
+SHLIB_LD_LIBS {@SHLIB_LD_LIBS@}
+SHLIB_SUFFIX {@SHLIB_SUFFIX@}
+STLIB_LD {@STLIB_LD@}
+TCL_DEFS {@TCL_DEFS@}
+TCL_VERSION {@TCL_VERSION@}
+TCL_PATCH_LEVEL {@TCL_PATCH_LEVEL@}
+TCL_BIN_DIR {@TCL_BIN_DIR@}
+TCL_SRC_DIR {@TCL_SRC_DIR@}
+TEA_TK_EXTENSION {@TEA_TK_EXTENSION@}
+
+TK_VERSION {@TK_VERSION@}
+TK_PATCH_LEVEL {@TK_PATCH_LEVEL@}
+TK_BIN_DIR {@TK_BIN_DIR@}
+TK_SRC_DIR {@TK_SRC_DIR@}
+
+TEA_PLATFORM {@TEA_PLATFORM@}
+TEA_WINDOWINGSYSTEM {@TEA_WINDOWINGSYSTEM@}
+TEA_SYSTEM {@TEA_SYSTEM@}
+TEACUP_OS {@TEACUP_OS@}
+TEACUP_ARCH {@TEACUP_ARCH@}
+TEACUP_TOOLSET {@TEACUP_TOOLSET@}
+TEACUP_PROFILE {@TEACUP_PROFILE@}
+
+PRACTCL_DEFS {@PRACTCL_DEFS@}
+PRACTCL_TOOLSET {@PRACTCL_TOOLSET@}
+PRACTCL_SHARED_LIB {@PRACTCL_SHARED_LIB@}
+PRACTCL_STATIC_LIB {@PRACTCL_STATIC_LIB@}
+PRACTCL_STUB_LIB {@PRACTCL_STUB_LIB@}
+PRACTCL_LIBS {@PKG_LIBS@ @LIBS@}
+PRACTCL_VC_MANIFEST_EMBED_DLL {@PRACTCL_VC_MANIFEST_EMBED_DLL@}
+PRACTCL_VC_MANIFEST_EMBED_EXE {@PRACTCL_VC_MANIFEST_EMBED_EXE@}
+PRACTCL_NAME_LIBRARY {@PRACTCL_NAME_LIBRARY@}
+
+PRACTCL_PKG_LIBS {@PKG_LIBS@} \ No newline at end of file
diff --git a/tclconfig/practcl.tcl b/tclconfig/practcl.tcl
new file mode 100644
index 0000000..ecabbf8
--- /dev/null
+++ b/tclconfig/practcl.tcl
@@ -0,0 +1,4923 @@
+###
+# Practcl
+# An object oriented templating system for stamping out Tcl API calls to C
+###
+puts [list LOADED practcl.tcl from [info script]]
+
+package require TclOO
+###
+# Seek out Tcllib if it's available
+###
+set tcllib_path {}
+foreach path {.. ../.. ../../..} {
+ foreach path [glob -nocomplain [file join [file normalize $path] tcllib* modules]] {
+ set tclib_path $path
+ lappend ::auto_path $path
+ break
+ }
+ if {$tcllib_path ne {}} break
+}
+
+###
+# Build utility functions
+###
+
+
+###
+# Extend http to follow redirects (ala Sourceforge downloads)
+###
+namespace eval ::http {}
+proc ::http::_followRedirects {url args} {
+ while 1 {
+ set token [geturl $url -validate 1]
+ set ncode [ncode $token]
+ if { $ncode eq "404" } {
+ error "URL Not found"
+ }
+ switch -glob $ncode {
+ 30[1237] {### redirect - see below ###}
+ default {cleanup $token ; return $url}
+ }
+ upvar #0 $token state
+ array set meta [set ${token}(meta)]
+ cleanup $token
+ if {![info exists meta(Location)]} {
+ return $url
+ }
+ set url $meta(Location)
+ unset meta
+ }
+ return $url
+}
+
+proc ::http::wget {url destfile {verbose 1}} {
+ package require http
+ set tmpchan [open $destfile w]
+ fconfigure $tmpchan -translation binary
+ if { $verbose } {
+ puts [list GETTING [file tail $destfile] from $url]
+ }
+ set real_url [_followRedirects $url]
+ set token [geturl $real_url -channel $tmpchan -binary yes]
+ if {[ncode $token] != "200"} {
+ error "DOWNLOAD FAILED"
+ }
+ cleanup $token
+ close $tmpchan
+}
+
+namespace eval ::practcl {}
+
+###
+# A command to do nothing. A handy way of
+# negating an instruction without
+# having to comment it completely out.
+# It's also a handy attachment point for
+# an object to be named later
+###
+if {[info command ::noop] eq {}} {
+ proc ::noop args {}
+}
+
+proc ::practcl::debug args {
+ #puts $args
+ ::practcl::cputs ::DEBUG_INFO $args
+}
+
+###
+# Drop in a static copy of Tcl
+###
+proc ::practcl::doexec args {
+ puts [list {*}$args]
+ exec {*}$args >&@ stdout
+}
+
+proc ::practcl::doexec_in {path args} {
+ set PWD [pwd]
+ cd $path
+ puts [list {*}$args]
+ exec {*}$args >&@ stdout
+ cd $PWD
+}
+
+proc ::practcl::dotclexec args {
+ puts [list [info nameofexecutable] {*}$args]
+ exec [info nameofexecutable] {*}$args >&@ stdout
+}
+
+proc ::practcl::domake {path args} {
+ set PWD [pwd]
+ cd $path
+ puts [list *** $path ***]
+ puts [list make {*}$args]
+ exec make {*}$args >&@ stdout
+ cd $PWD
+}
+
+proc ::practcl::domake.tcl {path args} {
+ set PWD [pwd]
+ cd $path
+ puts [list *** $path ***]
+ puts [list make.tcl {*}$args]
+ exec [info nameofexecutable] make.tcl {*}$args >&@ stdout
+ cd $PWD
+}
+
+proc ::practcl::fossil {path args} {
+ set PWD [pwd]
+ cd $path
+ puts [list {*}$args]
+ exec fossil {*}$args >&@ stdout
+ cd $PWD
+}
+
+
+proc ::practcl::fossil_status {dir} {
+ if {[info exists ::fosdat($dir)]} {
+ return $::fosdat($dir)
+ }
+ set result {
+tags experimental
+version {}
+ }
+ set pwd [pwd]
+ cd $dir
+ set info [exec fossil status]
+ cd $pwd
+ foreach line [split $info \n] {
+ if {[lindex $line 0] eq "checkout:"} {
+ set hash [lindex $line end-3]
+ set maxdate [lrange $line end-2 end-1]
+ dict set result hash $hash
+ dict set result maxdate $maxdate
+ regsub -all {[^0-9]} $maxdate {} isodate
+ dict set result isodate $isodate
+ }
+ if {[lindex $line 0] eq "tags:"} {
+ set tags [lrange $line 1 end]
+ dict set result tags $tags
+ break
+ }
+ }
+ set ::fosdat($dir) $result
+ return $result
+}
+
+proc ::practcl::os {} {
+ return [${::practcl::MAIN} define get TEACUP_OS]
+}
+
+if {[::package vcompare $::tcl_version 8.6] < 0} {
+ # Approximate ::zipfile::mkzip with exec calls
+ proc ::practcl::mkzip {exename barekit vfspath} {
+ set path [file dirname [file normalize $exename]]
+ set zipfile [file join $path [file rootname $exename].zip]
+ file copy -force $barekit $exename
+ set pwd [pwd]
+ cd $vfspath
+ exec zip -r $zipfile .
+ cd $pwd
+ set fout [open $exename a]
+ set fin [open $zipfile r]
+ chan configure $fout -translation binary
+ chan configure $fin -translation binary
+ chan copy $fin $fout
+ chan close $fin
+ chan close $fout
+ exec zip -A $exename
+ }
+ proc ::practcl::sort_dict list {
+ set result {}
+ foreach key [lsort -dictionary [dict keys $list]] {
+ dict set result $key [dict get $list $key]
+ }
+ return $result
+ }
+} else {
+ proc ::practcl::mkzip {exename barekit vfspath} {
+ ::practcl::tcllib_require zipfile::mkzip
+ ::zipfile::mkzip::mkzip $exename -runtime $barekit -directory $vfspath
+ }
+ proc ::practcl::sort_dict list {
+ return [::lsort -stride 2 -dictionary $list]
+ }
+}
+
+proc ::practcl::local_os {} {
+ # If we have already run this command, return
+ # a cached copy of the data
+ if {[info exists ::practcl::LOCAL_INFO]} {
+ return $::practcl::LOCAL_INFO
+ }
+ set result [array get ::practcl::CONFIG]
+ dict set result TEACUP_PROFILE unknown
+ dict set result TEACUP_OS unknown
+ dict set result EXEEXT {}
+ set windows 0
+ if {$::tcl_platform(platform) eq "windows"} {
+ set windows 1
+ }
+ if {$windows} {
+ set system "windows"
+ set arch ix86
+ dict set result TEACUP_PROFILE win32-ix86
+ dict set result TEACUP_OS windows
+ dict set result EXEEXT .exe
+ } else {
+ set system [exec uname -s]-[exec uname -r]
+ set arch unknown
+ dict set result TEACUP_OS generic
+ }
+ dict set result TEA_PLATFORM $system
+ dict set result TEA_SYSTEM $system
+ if {[info exists ::SANDBOX]} {
+ dict set result sandbox $::SANDBOX
+ }
+ switch -glob $system {
+ Linux* {
+ dict set result TEACUP_OS linux
+ set arch [exec uname -m]
+ dict set result TEACUP_PROFILE "linux-glibc2.3-$arch"
+ }
+ GNU* {
+ set arch [exec uname -m]
+ dict set result TEACUP_OS "gnu"
+ }
+ NetBSD-Debian {
+ set arch [exec uname -m]
+ dict set result TEACUP_OS "netbsd-debian"
+ }
+ OpenBSD-* {
+ set arch [exec arch -s]
+ dict set result TEACUP_OS "openbsd"
+ }
+ Darwin* {
+ set arch [exec uname -m]
+ dict set result TEACUP_OS "macosx"
+ if {$arch eq "x86_64"} {
+ dict set result TEACUP_PROFILE "macosx10.5-i386-x86_84"
+ } else {
+ dict set result TEACUP_PROFILE "macosx-universal"
+ }
+ }
+ OpenBSD* {
+ set arch [exec arch -s]
+ dict set result TEACUP_OS "openbsd"
+ }
+ }
+ if {$arch eq "unknown"} {
+ catch {set arch [exec uname -m]}
+ }
+ switch -glob $arch {
+ i*86 {
+ set arch "ix86"
+ }
+ amd64 {
+ set arch "x86_64"
+ }
+ }
+ dict set result TEACUP_ARCH $arch
+ if {[dict get $result TEACUP_PROFILE] eq "unknown"} {
+ dict set result TEACUP_PROFILE [dict get $result TEACUP_OS]-$arch
+ }
+ set OS [dict get $result TEACUP_OS]
+ dict set result os $OS
+
+ # Look for a local preference file
+ set pathlist {}
+ set userhome [file normalize ~/tcl]
+ set local_install [file join $userhome lib]
+ switch $OS {
+ windows {
+ set userhome [file join [file normalize $::env(LOCALAPPDATA)] Tcl]
+ if {[file exists c:/Tcl/Teapot]} {
+ dict set result teapot c:/Tcl/Teapot
+ }
+ }
+ macosx {
+ set userhome [file join [file normalize {~/Library/Application Support/}] Tcl]
+ if {[file exists {~/Library/Application Support/ActiveState/Teapot/repository/}]} {
+ dict set result teapot [file normalize {~/Library/Application Support/ActiveState/Teapot/repository/}]
+ }
+ dict set result local_install [file normalize ~/Library/Tcl]
+ if {![dict exists $result sandbox]} {
+ dict set result sandbox [file normalize ~/Library/Tcl/sandbox]
+ }
+ }
+ default {
+ }
+ }
+ dict set result userhome $userhome
+ # Load user preferences
+ if {[file exists [file join $userhome practcl.rc]]} {
+ set dat [::practcl::cat [file join $path practcl.rc]]
+ }
+ if {![dict exists $result prefix]} {
+ dict set result prefix $userhome
+ }
+
+ # Create a default path for the teapot
+ if {![dict exists $result teapot]} {
+ dict set result teapot [file join $userhome teapot]
+ }
+ # Create a default path for the local sandbox
+ if {![dict exists $result sandbox]} {
+ dict set result sandbox [file join $userhome sandbox]
+ }
+ # Create a default path for download folder
+ if {![dict exists $result download]} {
+ dict set result download [file join $userhome download]
+ }
+ # Path to install local packages
+ if {![dict exists $result local_install]} {
+ dict set result local_install [file join $userhome lib]
+ }
+ if {![dict exists result fossil_mirror] && [::info exists ::env(FOSSIL_MIRROR)]} {
+ dict set result fossil_mirror $::env(FOSSIL_MIRROR)
+ }
+
+ set ::practcl::LOCAL_INFO $result
+ return $result
+}
+
+
+###
+# Detect local platform
+###
+proc ::practcl::config.tcl {path} {
+ dict set result buildpath $path
+ set result [local_os]
+ set OS [dict get $result TEACUP_OS]
+ set windows 0
+ dict set result USEMSVC 0
+ if {[file exists [file join $path config.tcl]]} {
+ # We have a definitive configuration file. Read its content
+ # and take it as gospel
+ set cresult [read_rc_file [file join $path config.tcl]]
+ set cresult [::practcl::de_shell $cresult]
+ if {[dict exists $cresult srcdir] && ![dict exists $cresult sandbox]} {
+ dict set cresult sandbox [file dirname [dict get $cresult srcdir]]
+ }
+ set result [dict merge $result [::practcl::de_shell $cresult]]
+ }
+ if {[file exists [file join $path config.site]]} {
+ # No config.tcl file is present but we do seed
+ dict set result USEMSVC 0
+ foreach {f v} [::practcl::de_shell [::practcl::read_sh_file [file join $path config.site]]] {
+ dict set result $f $v
+ dict set result XCOMPILE_${f} $v
+ }
+ dict set result CONFIG_SITE [file join $path config.site]
+ if {[dict exist $result XCOMPILE_CC] && [regexp mingw [dict get $result XCOMPILE_CC]]} {
+ set windows 1
+ }
+ } elseif {[info exists ::env(VisualStudioVersion)]} {
+ set windows 1
+ dict set result USEMSVC 1
+ }
+ if {$windows && [dict get $result TEACUP_OS] ne "windows"} {
+ if {![dict exists exists $result TEACUP_ARCH]} {
+ dict set result TEACUP_ARCH ix86
+ }
+ dict set result TEACUP_PROFILE win32-[dict get $result TEACUP_ARCH]
+ dict set result TEACUP_OS windows
+ dict set result EXEEXT .exe
+ }
+ return $result
+}
+
+
+###
+# Convert an MSYS path to a windows native path
+###
+if {$::tcl_platform(platform) eq "windows"} {
+proc ::practcl::msys_to_tclpath msyspath {
+ return [exec sh -c "cd $msyspath ; pwd -W"]
+}
+} else {
+proc ::practcl::msys_to_tclpath msyspath {
+ return [file normalize $msyspath]
+}
+}
+
+###
+# Bits stolen from fileutil
+###
+proc ::practcl::cat fname {
+ set fname [open $fname r]
+ set data [read $fname]
+ close $fname
+ return $data
+}
+
+proc ::practcl::file_lexnormalize {sp} {
+ set spx [file split $sp]
+
+ # Resolution of embedded relative modifiers (., and ..).
+
+ if {
+ ([lsearch -exact $spx . ] < 0) &&
+ ([lsearch -exact $spx ..] < 0)
+ } {
+ # Quick path out if there are no relative modifiers
+ return $sp
+ }
+
+ set absolute [expr {![string equal [file pathtype $sp] relative]}]
+ # A volumerelative path counts as absolute for our purposes.
+
+ set sp $spx
+ set np {}
+ set noskip 1
+
+ while {[llength $sp]} {
+ set ele [lindex $sp 0]
+ set sp [lrange $sp 1 end]
+ set islast [expr {[llength $sp] == 0}]
+
+ if {[string equal $ele ".."]} {
+ if {
+ ($absolute && ([llength $np] > 1)) ||
+ (!$absolute && ([llength $np] >= 1))
+ } {
+ # .. : Remove the previous element added to the
+ # new path, if there actually is enough to remove.
+ set np [lrange $np 0 end-1]
+ }
+ } elseif {[string equal $ele "."]} {
+ # Ignore .'s, they stay at the current location
+ continue
+ } else {
+ # A regular element.
+ lappend np $ele
+ }
+ }
+ if {[llength $np] > 0} {
+ return [eval [linsert $np 0 file join]]
+ # 8.5: return [file join {*}$np]
+ }
+ return {}
+}
+
+proc ::practcl::file_relative {base dst} {
+ # Ensure that the link to directory 'dst' is properly done relative to
+ # the directory 'base'.
+
+ if {![string equal [file pathtype $base] [file pathtype $dst]]} {
+ return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)"
+ }
+
+ set base [file_lexnormalize [file join [pwd] $base]]
+ set dst [file_lexnormalize [file join [pwd] $dst]]
+
+ set save $dst
+ set base [file split $base]
+ set dst [file split $dst]
+
+ while {[string equal [lindex $dst 0] [lindex $base 0]]} {
+ set dst [lrange $dst 1 end]
+ set base [lrange $base 1 end]
+ if {![llength $dst]} {break}
+ }
+
+ set dstlen [llength $dst]
+ set baselen [llength $base]
+
+ if {($dstlen == 0) && ($baselen == 0)} {
+ # Cases:
+ # (a) base == dst
+
+ set dst .
+ } else {
+ # Cases:
+ # (b) base is: base/sub = sub
+ # dst is: base = {}
+
+ # (c) base is: base = {}
+ # dst is: base/sub = sub
+
+ while {$baselen > 0} {
+ set dst [linsert $dst 0 ..]
+ incr baselen -1
+ }
+ # 8.5: set dst [file join {*}$dst]
+ set dst [eval [linsert $dst 0 file join]]
+ }
+
+ return $dst
+}
+
+# Try to load a package, and failing that
+# retrieve tcllib
+proc ::practcl::tcllib_require {pkg args} {
+ # Try to load the package from the local environment
+ if {[catch [list ::package require $pkg {*}$args] err]==0} {
+ return $err
+ }
+ ::practcl::LOCAL tool tcllib load
+ uplevel #0 [list ::package require $pkg {*}$args]
+}
+
+namespace eval ::practcl::platform {}
+
+proc ::practcl::platform::tcl_core_options {os} {
+ ###
+ # Download our required packages
+ ###
+ set tcl_config_opts {}
+ # Auto-guess options for the local operating system
+ switch $os {
+ windows {
+ #lappend tcl_config_opts --disable-stubs
+ }
+ linux {
+ }
+ macosx {
+ lappend tcl_config_opts --enable-corefoundation=yes --enable-framework=no
+ }
+ }
+ lappend tcl_config_opts --with-tzdata
+ return $tcl_config_opts
+}
+
+proc ::practcl::platform::tk_core_options {os} {
+ ###
+ # Download our required packages
+ ###
+ set tk_config_opts {}
+
+ # Auto-guess options for the local operating system
+ switch $os {
+ windows {
+ }
+ linux {
+ lappend tk_config_opts --enable-xft=no --enable-xss=no
+ }
+ macosx {
+ lappend tk_config_opts --enable-aqua=yes
+ }
+ }
+ return $tk_config_opts
+}
+
+###
+# Read a stylized key/value list stored in a file
+###
+proc ::practcl::read_rc_file {filename {localdat {}}} {
+ set result $localdat
+ set fin [open $filename r]
+ set bufline {}
+ set rawcount 0
+ set linecount 0
+ while {[gets $fin thisline]>=0} {
+ incr rawcount
+ append bufline \n $thisline
+ if {![info complete $bufline]} continue
+ set line [string trimleft $bufline]
+ set bufline {}
+ if {[string index [string trimleft $line] 0] eq "#"} continue
+ append result \n $line
+ #incr linecount
+ #set key [lindex $line 0]
+ #set value [lindex $line 1]
+ #dict set result $key $value
+ }
+ return $result
+}
+
+###
+# topic: e71f3f61c348d56292011eec83e95f0aacc1c618
+# description: Converts a XXX.sh file into a series of Tcl variables
+###
+proc ::practcl::read_sh_subst {line info} {
+ regsub -all {\x28} $line \x7B line
+ regsub -all {\x29} $line \x7D line
+
+ #set line [string map $key [string trim $line]]
+ foreach {field value} $info {
+ catch {set $field $value}
+ }
+ if [catch {subst $line} result] {
+ return {}
+ }
+ set result [string trim $result]
+ return [string trim $result ']
+}
+
+###
+# topic: 03567140cca33c814664c7439570f669b9ab88e6
+###
+proc ::practcl::read_sh_file {filename {localdat {}}} {
+ set fin [open $filename r]
+ set result {}
+ if {$localdat eq {}} {
+ set top 1
+ set local [array get ::env]
+ dict set local EXE {}
+ } else {
+ set top 0
+ set local $localdat
+ }
+ while {[gets $fin line] >= 0} {
+ set line [string trim $line]
+ if {[string index $line 0] eq "#"} continue
+ if {$line eq {}} continue
+ catch {
+ if {[string range $line 0 6] eq "export "} {
+ set eq [string first "=" $line]
+ set field [string trim [string range $line 6 [expr {$eq - 1}]]]
+ set value [read_sh_subst [string range $line [expr {$eq+1}] end] $local]
+ dict set result $field [read_sh_subst $value $local]
+ dict set local $field $value
+ } elseif {[string range $line 0 7] eq "include "} {
+ set subfile [read_sh_subst [string range $line 7 end] $local]
+ foreach {field value} [read_sh_file $subfile $local] {
+ dict set result $field $value
+ }
+ } else {
+ set eq [string first "=" $line]
+ if {$eq > 0} {
+ set field [read_sh_subst [string range $line 0 [expr {$eq - 1}]] $local]
+ set value [string trim [string range $line [expr {$eq+1}] end] ']
+ #set value [read_sh_subst [string range $line [expr {$eq+1}] end] $local]
+ dict set local $field $value
+ dict set result $field $value
+ }
+ }
+ } err opts
+ if {[dict get $opts -code] != 0} {
+ #puts $opts
+ puts "Error reading line:\n$line\nerr: $err\n***"
+ return $err {*}$opts
+ }
+ }
+ return $result
+}
+
+###
+# A simpler form of read_sh_file tailored
+# to pulling data from (tcl|tk)Config.sh
+###
+proc ::practcl::read_Config.sh filename {
+ set fin [open $filename r]
+ set result {}
+ set linecount 0
+ while {[gets $fin line] >= 0} {
+ set line [string trim $line]
+ if {[string index $line 0] eq "#"} continue
+ if {$line eq {}} continue
+ catch {
+ set eq [string first "=" $line]
+ if {$eq > 0} {
+ set field [string range $line 0 [expr {$eq - 1}]]
+ set value [string trim [string range $line [expr {$eq+1}] end] ']
+ #set value [read_sh_subst [string range $line [expr {$eq+1}] end] $local]
+ dict set result $field $value
+ incr $linecount
+ }
+ } err opts
+ if {[dict get $opts -code] != 0} {
+ #puts $opts
+ puts "Error reading line:\n$line\nerr: $err\n***"
+ return $err {*}$opts
+ }
+ }
+ return $result
+}
+
+###
+# A simpler form of read_sh_file tailored
+# to pulling data from a Makefile
+###
+proc ::practcl::read_Makefile filename {
+ set fin [open $filename r]
+ set result {}
+ while {[gets $fin line] >= 0} {
+ set line [string trim $line]
+ if {[string index $line 0] eq "#"} continue
+ if {$line eq {}} continue
+ catch {
+ set eq [string first "=" $line]
+ if {$eq > 0} {
+ set field [string trim [string range $line 0 [expr {$eq - 1}]]]
+ set value [string trim [string trim [string range $line [expr {$eq+1}] end] ']]
+ switch $field {
+ PKG_LIB_FILE {
+ dict set result libfile $value
+ }
+ srcdir {
+ if {$value eq "."} {
+ dict set result srcdir [file dirname $filename]
+ } else {
+ dict set result srcdir $value
+ }
+ }
+ PACKAGE_NAME {
+ dict set result name $value
+ }
+ PACKAGE_VERSION {
+ dict set result version $value
+ }
+ LIBS {
+ dict set result PRACTCL_LIBS $value
+ }
+ PKG_LIB_FILE {
+ dict set result libfile $value
+ }
+ }
+ }
+ } err opts
+ if {[dict get $opts -code] != 0} {
+ #puts $opts
+ puts "Error reading line:\n$line\nerr: $err\n***"
+ return $err {*}$opts
+ }
+ # the Compile field is about where most TEA files start getting silly
+ if {$field eq "compile"} {
+ break
+ }
+ }
+ return $result
+}
+
+## Append arguments to a buffer
+# The command works like puts in that each call will also insert
+# a line feed. Unlike puts, blank links in the interstitial are
+# suppressed
+proc ::practcl::cputs {varname args} {
+ upvar 1 $varname buffer
+ if {[llength $args]==1 && [string length [string trim [lindex $args 0]]] == 0} {
+
+ }
+ if {[info exist buffer]} {
+ if {[string index $buffer end] ne "\n"} {
+ append buffer \n
+ }
+ } else {
+ set buffer \n
+ }
+ # Trim leading \n's
+ append buffer [string trimleft [lindex $args 0] \n] {*}[lrange $args 1 end]
+}
+
+
+proc ::practcl::tcl_to_c {body} {
+ set result {}
+ foreach rawline [split $body \n] {
+ set line [string map [list \" \\\" \\ \\\\] $rawline]
+ cputs result "\n \"$line\\n\" \\"
+ }
+ return [string trimright $result \\]
+}
+
+
+proc ::practcl::_tagblock {text {style tcl} {note {}}} {
+ if {[string length [string trim $text]]==0} {
+ return {}
+ }
+ set output {}
+ switch $style {
+ tcl {
+ ::practcl::cputs output "# BEGIN $note"
+ }
+ c {
+ ::practcl::cputs output "/* BEGIN $note */"
+ }
+ default {
+ ::practcl::cputs output "# BEGIN $note"
+ }
+ }
+ ::practcl::cputs output $text
+ switch $style {
+ tcl {
+ ::practcl::cputs output "# END $note"
+ }
+ c {
+ ::practcl::cputs output "/* END $note */"
+ }
+ default {
+ ::practcl::cputs output "# END $note"
+ }
+ }
+ return $output
+}
+
+proc ::practcl::_isdirectory name {
+ return [file isdirectory $name]
+}
+
+###
+# Return true if the pkgindex file contains
+# any statement other than "package ifneeded"
+# and/or if any package ifneeded loads a DLL
+###
+proc ::practcl::_pkgindex_directory {path} {
+ set buffer {}
+ set pkgidxfile [file join $path pkgIndex.tcl]
+ if {![file exists $pkgidxfile]} {
+ # No pkgIndex file, read the source
+ foreach file [glob -nocomplain $path/*.tm] {
+ set file [file normalize $file]
+ set fname [file rootname [file tail $file]]
+ ###
+ # We used to be able to ... Assume the package is correct in the filename
+ # No hunt for a "package provides"
+ ###
+ set package [lindex [split $fname -] 0]
+ set version [lindex [split $fname -] 1]
+ ###
+ # Read the file, and override assumptions as needed
+ ###
+ set fin [open $file r]
+ set dat [read $fin]
+ close $fin
+ # Look for a teapot style Package statement
+ foreach line [split $dat \n] {
+ set line [string trim $line]
+ if { [string range $line 0 9] != "# Package " } continue
+ set package [lindex $line 2]
+ set version [lindex $line 3]
+ break
+ }
+ # Look for a package provide statement
+ foreach line [split $dat \n] {
+ set line [string trim $line]
+ if { [string range $line 0 14] != "package provide" } continue
+ set package [lindex $line 2]
+ set version [lindex $line 3]
+ break
+ }
+ append buffer "package ifneeded $package $version \[list source \[file join \$dir [file tail $file]\]\]" \n
+ }
+ foreach file [glob -nocomplain $path/*.tcl] {
+ if { [file tail $file] == "version_info.tcl" } continue
+ set fin [open $file r]
+ set dat [read $fin]
+ close $fin
+ if {![regexp "package provide" $dat]} continue
+ set fname [file rootname [file tail $file]]
+ # Look for a package provide statement
+ foreach line [split $dat \n] {
+ set line [string trim $line]
+ if { [string range $line 0 14] != "package provide" } continue
+ set package [lindex $line 2]
+ set version [lindex $line 3]
+ if {[string index $package 0] in "\$ \["} continue
+ if {[string index $version 0] in "\$ \["} continue
+ append buffer "package ifneeded $package $version \[list source \[file join \$dir [file tail $file]\]\]" \n
+ break
+ }
+ }
+ return $buffer
+ }
+ set fin [open $pkgidxfile r]
+ set dat [read $fin]
+ close $fin
+ set trace 0
+ #if {[file tail $path] eq "tool"} {
+ # set trace 1
+ #}
+ set thisline {}
+ foreach line [split $dat \n] {
+ append thisline $line \n
+ if {![info complete $thisline]} continue
+ set line [string trim $line]
+ if {[string length $line]==0} {
+ set thisline {} ; continue
+ }
+ if {[string index $line 0] eq "#"} {
+ set thisline {} ; continue
+ }
+ if {[regexp "if.*catch.*package.*Tcl.*return" $thisline]} {
+ if {$trace} {puts "[file dirname $pkgidxfile] Ignoring $thisline"}
+ set thisline {} ; continue
+ }
+ if {[regexp "if.*package.*vsatisfies.*package.*provide.*return" $thisline]} {
+ if {$trace} { puts "[file dirname $pkgidxfile] Ignoring $thisline" }
+ set thisline {} ; continue
+ }
+ if {![regexp "package.*ifneeded" $thisline]} {
+ # This package index contains arbitrary code
+ # source instead of trying to add it to the master
+ # package index
+ if {$trace} { puts "[file dirname $pkgidxfile] Arbitrary code $thisline" }
+ return {source [file join $dir pkgIndex.tcl]}
+ }
+ append buffer $thisline \n
+ set thisline {}
+ }
+ if {$trace} {puts [list [file dirname $pkgidxfile] $buffer]}
+ return $buffer
+}
+
+
+proc ::practcl::_pkgindex_path_subdir {path} {
+ set result {}
+ foreach subpath [glob -nocomplain [file join $path *]] {
+ if {[file isdirectory $subpath]} {
+ lappend result $subpath {*}[_pkgindex_path_subdir $subpath]
+ }
+ }
+ return $result
+}
+###
+# Index all paths given as though they will end up in the same
+# virtual file system
+###
+proc ::practcl::pkgindex_path args {
+ set stack {}
+ set buffer {
+lappend ::PATHSTACK $dir
+ }
+ foreach base $args {
+ set base [file normalize $base]
+ set paths [::practcl::_pkgindex_path_subdir $base]
+ set i [string length $base]
+ # Build a list of all of the paths
+ foreach path $paths {
+ if {$path eq $base} continue
+ set path_indexed($path) 0
+ }
+ set path_indexed($base) 1
+ set path_indexed([file join $base boot tcl]) 1
+ #set path_index([file join $base boot tk]) 1
+
+ foreach path $paths {
+ if {$path_indexed($path)} continue
+ set thisdir [file_relative $base $path]
+ #set thisdir [string range $path $i+1 end]
+ #append buffer "# DIR $thisdir" \n
+ set idxbuf [::practcl::_pkgindex_directory $path]
+ if {[string length $idxbuf]} {
+ incr path_indexed($path)
+ append buffer "set dir \[set PKGDIR \[file join \[lindex \$::PATHSTACK end\] $thisdir\]\]" \n
+ append buffer [string map {$dir $PKGDIR} [string trimright $idxbuf]] \n
+ }
+ }
+ }
+ append buffer {
+set dir [lindex $::PATHSTACK end]
+set ::PATHSTACK [lrange $::PATHSTACK 0 end-1]
+}
+ return $buffer
+}
+
+###
+# topic: 64319f4600fb63c82b2258d908f9d066
+# description: Script to build the VFS file system
+###
+proc ::practcl::installDir {d1 d2} {
+
+ puts [format {%*sCreating %s} [expr {4 * [info level]}] {} [file tail $d2]]
+ file delete -force -- $d2
+ file mkdir $d2
+
+ foreach ftail [glob -directory $d1 -nocomplain -tails *] {
+ set f [file join $d1 $ftail]
+ if {[file isdirectory $f] && [string compare CVS $ftail]} {
+ installDir $f [file join $d2 $ftail]
+ } elseif {[file isfile $f]} {
+ file copy -force $f [file join $d2 $ftail]
+ if {$::tcl_platform(platform) eq {unix}} {
+ file attributes [file join $d2 $ftail] -permissions 0644
+ } else {
+ file attributes [file join $d2 $ftail] -readonly 1
+ }
+ }
+ }
+
+ if {$::tcl_platform(platform) eq {unix}} {
+ file attributes $d2 -permissions 0755
+ } else {
+ file attributes $d2 -readonly 1
+ }
+}
+
+proc ::practcl::copyDir {d1 d2 {toplevel 1}} {
+ if {$toplevel} {
+ puts [list ::practcl::copyDir $d1 -> $d2]
+ }
+ #file delete -force -- $d2
+ file mkdir $d2
+
+ foreach ftail [glob -directory $d1 -nocomplain -tails *] {
+ set f [file join $d1 $ftail]
+ if {[file isdirectory $f] && [string compare CVS $ftail]} {
+ copyDir $f [file join $d2 $ftail] 0
+ } elseif {[file isfile $f]} {
+ file copy -force $f [file join $d2 $ftail]
+ }
+ }
+}
+
+::oo::class create ::practcl::metaclass {
+ superclass ::oo::object
+
+ method script script {
+ eval $script
+ }
+
+ method source filename {
+ source $filename
+ }
+
+ method initialize {} {}
+
+ method define {submethod args} {
+ my variable define
+ switch $submethod {
+ dump {
+ return [array get define]
+ }
+ add {
+ set field [lindex $args 0]
+ if {![info exists define($field)]} {
+ set define($field) {}
+ }
+ foreach arg [lrange $args 1 end] {
+ if {$arg ni $define($field)} {
+ lappend define($field) $arg
+ }
+ }
+ return $define($field)
+ }
+ remove {
+ set field [lindex $args 0]
+ if {![info exists define($field)]} {
+ return
+ }
+ set rlist [lrange $args 1 end]
+ set olist $define($field)
+ set nlist {}
+ foreach arg $olist {
+ if {$arg in $rlist} continue
+ lappend nlist $arg
+ }
+ set define($field) $nlist
+ return $nlist
+ }
+ exists {
+ set field [lindex $args 0]
+ return [info exists define($field)]
+ }
+ getnull -
+ get -
+ cget {
+ set field [lindex $args 0]
+ if {[info exists define($field)]} {
+ return $define($field)
+ }
+ return [lindex $args 1]
+ }
+ set {
+ if {[llength $args]==1} {
+ set arglist [lindex $args 0]
+ } else {
+ set arglist $args
+ }
+ array set define $arglist
+ if {[dict exists $arglist class]} {
+ my select
+ }
+ }
+ default {
+ array $submethod define {*}$args
+ }
+ }
+ }
+
+ method graft args {
+ my variable organs
+ if {[llength $args] == 1} {
+ error "Need two arguments"
+ }
+ set object {}
+ foreach {stub object} $args {
+ dict set organs $stub $object
+ oo::objdefine [self] forward <${stub}> $object
+ oo::objdefine [self] export <${stub}>
+ }
+ return $object
+ }
+
+ method organ {{stub all}} {
+ my variable organs
+ if {![info exists organs]} {
+ return {}
+ }
+ if { $stub eq "all" } {
+ return $organs
+ }
+ if {[dict exists $organs $stub]} {
+ return [dict get $organs $stub]
+ }
+ }
+
+ method link {command args} {
+ my variable links
+ switch $command {
+ object {
+ foreach obj $args {
+ foreach linktype [$obj linktype] {
+ my link add $linktype $obj
+ }
+ }
+ }
+ add {
+ ###
+ # Add a link to an object that was externally created
+ ###
+ if {[llength $args] ne 2} { error "Usage: link add LINKTYPE OBJECT"}
+ lassign $args linktype object
+ if {[info exists links($linktype)] && $object in $links($linktype)} {
+ return
+ }
+ lappend links($linktype) $object
+ }
+ remove {
+ set object [lindex $args 0]
+ if {[llength $args]==1} {
+ set ltype *
+ } else {
+ set ltype [lindex $args 1]
+ }
+ foreach {linktype elements} [array get links $ltype] {
+ if {$object in $elements} {
+ set nlist {}
+ foreach e $elements {
+ if { $object ne $e } { lappend nlist $e }
+ }
+ set links($linktype) $nlist
+ }
+ }
+ }
+ list {
+ if {[llength $args]==0} {
+ return [array get links]
+ }
+ if {[llength $args] != 1} { error "Usage: link list LINKTYPE"}
+ set linktype [lindex $args 0]
+ if {![info exists links($linktype)]} {
+ return {}
+ }
+ return $links($linktype)
+ }
+ dump {
+ return [array get links]
+ }
+ }
+ }
+
+ method select {} {
+ my variable define
+ set class {}
+ if {[info exists define(class)]} {
+ if {[info command $define(class)] ne {}} {
+ set class $define(class)
+ } elseif {[info command ::practcl::$define(class)] ne {}} {
+ set class ::practcl::$define(class)
+ } else {
+ switch $define(class) {
+ default {
+ set class ::practcl::object
+ }
+ }
+ }
+ }
+ if {$class ne {}} {
+ ::oo::objdefine [self] class $class
+ }
+ if {[::info exists define(oodefine)]} {
+ ::oo::objdefine [self] $define(oodefine)
+ unset define(oodefine)
+ }
+ }
+}
+
+proc ::practcl::trigger {args} {
+ foreach name $args {
+ if {[dict exists $::make_objects $name]} {
+ [dict get $::make_objects $name] triggers
+ }
+ }
+}
+
+proc ::practcl::depends {args} {
+ foreach name $args {
+ if {[dict exists $::make_objects $name]} {
+ [dict get $::make_objects $name] check
+ }
+ }
+}
+
+proc ::practcl::target {name info} {
+ set obj [::practcl::target_obj new $name $info]
+ dict set ::make_objects $name $obj
+ if {[dict exists $info aliases]} {
+ foreach item [dict get $info aliases] {
+ if {![dict exists $::make_objects $item]} {
+ dict set ::make_objects $item $obj
+ }
+ }
+ }
+ set ::make($name) 0
+ set ::trigger($name) 0
+ set filename [$obj define get filename]
+ if {$filename ne {}} {
+ set ::target($name) $filename
+ }
+}
+
+### Batch Tasks
+
+proc ::practcl::de_shell {data} {
+ set values {}
+ foreach flag {DEFS TCL_DEFS TK_DEFS} {
+ if {[dict exists $data $flag]} {
+ #set value {}
+ #foreach item [dict get $data $flag] {
+ # append value " " [string map {{ } {\ }} $item]
+ #}
+ dict set values $flag [dict get $data $flag]
+ }
+ }
+ set map {}
+ lappend map {${PKG_OBJECTS}} %LIBRARY_OBJECTS%
+ lappend map {$(PKG_OBJECTS)} %LIBRARY_OBJECTS%
+ lappend map {${PKG_STUB_OBJECTS}} %LIBRARY_STUB_OBJECTS%
+ lappend map {$(PKG_STUB_OBJECTS)} %LIBRARY_STUB_OBJECTS%
+
+ if {[dict exists $data name]} {
+ lappend map %LIBRARY_NAME% [dict get $data name]
+ lappend map %LIBRARY_VERSION% [dict get $data version]
+ lappend map %LIBRARY_VERSION_NODOTS% [string map {. {}} [dict get $data version]]
+ if {[dict exists $data libprefix]} {
+ lappend map %LIBRARY_PREFIX% [dict get $data libprefix]
+ } else {
+ lappend map %LIBRARY_PREFIX% [dict get $data prefix]
+ }
+ }
+ foreach flag [dict keys $data] {
+ if {$flag in {TCL_DEFS TK_DEFS DEFS}} continue
+ set value [string trim [dict get $data $flag] \"]
+ dict set map "\$\{${flag}\}" $value
+ dict set map "\$\(${flag}\)" $value
+ #dict set map "\$${flag}" $value
+ dict set map "%${flag}%" $value
+ dict set values $flag [dict get $data $flag]
+ #dict set map "\$\{${flag}\}" $proj($flag)
+ }
+ set changed 1
+ while {$changed} {
+ set changed 0
+ foreach {field value} $values {
+ if {$field in {TCL_DEFS TK_DEFS DEFS}} continue
+ dict with values {}
+ set newval [string map $map $value]
+ if {$newval eq $value} continue
+ set changed 1
+ dict set values $field $newval
+ }
+ }
+ return $values
+}
+
+###
+# Ancestor-less class intended to be a mixin
+# which defines a family of build related behaviors
+# that are modified when targetting either gcc or msvc
+###
+::oo::class create ::practcl::build {
+ ## method DEFS
+ # This method populates 4 variables:
+ # name - The name of the package
+ # version - The version of the package
+ # defs - C flags passed to the compiler
+ # includedir - A list of paths to feed to the compiler for finding headers
+ #
+ method build-cflags {PROJECT DEFS namevar versionvar defsvar} {
+ upvar 1 $namevar name $versionvar version NAME NAME $defsvar defs
+ set name [string tolower [${PROJECT} define get name [${PROJECT} define get pkg_name]]]
+ set NAME [string toupper $name]
+ set version [${PROJECT} define get version [${PROJECT} define get pkg_vers]]
+ if {$version eq {}} {
+ set version 0.1a
+ }
+ set defs $DEFS
+ foreach flag {
+ -DPACKAGE_NAME
+ -DPACKAGE_VERSION
+ -DPACKAGE_TARNAME
+ -DPACKAGE_STRING
+ } {
+ if {[set i [string first $flag $defs]] >= 0} {
+ set j [string first -D $flag [expr {$i+[string length $flag]}]]
+ set predef [string range $defs 0 [expr {$i-1}]]
+ set postdef [string range $defs $j end]
+ set defs "$predef $postdef"
+ }
+ }
+ append defs " -DPACKAGE_NAME=\"${name}\" -DPACKAGE_VERSION=\"${version}\""
+ append defs " -DPACKAGE_TARNAME=\"${name}\" -DPACKAGE_STRING=\"${name}\x5c\x20${version}\""
+ return $defs
+ }
+
+ method build-tclkit_main {PROJECT PKG_OBJS} {
+ ###
+ # Build static package list
+ ###
+ set statpkglist {}
+ foreach cobj [list {*}${PKG_OBJS} $PROJECT] {
+ foreach {pkg info} [$cobj static-packages] {
+ dict set statpkglist $pkg $info
+ }
+ }
+ foreach {ofile info} [${PROJECT} compile-products] {
+ if {![dict exists $info object]} continue
+ set cobj [dict get $info object]
+ foreach {pkg info} [$cobj static-packages] {
+ dict set statpkglist $pkg $info
+ }
+ }
+
+ set result {}
+ $PROJECT include {<tcl.h>}
+ $PROJECT include {"tclInt.h"}
+ $PROJECT include {"tclFileSystem.h"}
+ $PROJECT include {<assert.h>}
+ $PROJECT include {<stdio.h>}
+ $PROJECT include {<stdlib.h>}
+ $PROJECT include {<string.h>}
+ $PROJECT include {<math.h>}
+
+ $PROJECT code header {
+#ifndef MODULE_SCOPE
+# define MODULE_SCOPE extern
+#endif
+
+/*
+** Provide a dummy Tcl_InitStubs if we are using this as a static
+** library.
+*/
+#ifndef USE_TCL_STUBS
+# undef Tcl_InitStubs
+# define Tcl_InitStubs(a,b,c) TCL_VERSION
+#endif
+#define STATIC_BUILD 1
+#undef USE_TCL_STUBS
+
+/* Make sure the stubbed variants of those are never used. */
+#undef Tcl_ObjSetVar2
+#undef Tcl_NewStringObj
+#undef Tk_Init
+#undef Tk_MainEx
+#undef Tk_SafeInit
+}
+
+ # Build an area of the file for #define directives and
+ # function declarations
+ set define {}
+ set mainhook [$PROJECT define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook]
+ set mainfunc [$PROJECT define get TCL_LOCAL_APPINIT Tclkit_AppInit]
+ set mainscript [$PROJECT define get main.tcl main.tcl]
+ set vfsroot [$PROJECT define get vfsroot [file join [$PROJECT define get ZIPFS_VOLUME] app]]
+ set vfs_main "${vfsroot}/${mainscript}"
+ set vfs_tcl_library "${vfsroot}/boot/tcl"
+ set vfs_tk_library "${vfsroot}/boot/tk"
+
+ set map {}
+ foreach var {
+ vfsroot mainhook mainfunc vfs_main vfs_tcl_library vfs_tk_library
+ } {
+ dict set map %${var}% [set $var]
+ }
+ set preinitscript {
+set ::odie(boot_vfs) {%vfsroot%}
+set ::SRCDIR {%vfsroot%}
+if {[file exists {%vfs_tcl_library%}]} {
+ set ::tcl_library {%vfs_tcl_library%}
+ set ::auto_path {}
+}
+if {[file exists {%vfs_tk_library%}]} {
+ set ::tk_library {%vfs_tk_library%}
+}
+} ; # Preinitscript
+
+ set zvfsboot {
+/*
+ * %mainhook% --
+ * Performs the argument munging for the shell
+ */
+ }
+ ::practcl::cputs zvfsboot {
+ CONST char *archive;
+ Tcl_FindExecutable(*argv[0]);
+ archive=Tcl_GetNameOfExecutable();
+ }
+ # We have to initialize the virtual filesystem before calling
+ # Tcl_Init(). Otherwise, Tcl_Init() will not be able to find
+ # its startup script files.
+ if {[$PROJECT define get tip_430 0]} {
+ ::practcl::cputs zvfsboot " if(!TclZipfsMount(NULL, archive, \"%vfsroot%\", NULL)) \x7B "
+ } else {
+ $PROJECT include {"tclZipfs.h"}
+ ::practcl::cputs zvfsboot { Tclzipfs_Init(NULL);}
+ ::practcl::cputs zvfsboot " if(!Tclzipfs_Mount(NULL, archive, \"%vfsroot%\", NULL)) \x7B "
+ }
+ ::practcl::cputs zvfsboot {
+ Tcl_Obj *vfsinitscript;
+ vfsinitscript=Tcl_NewStringObj("%vfs_main%",-1);
+ Tcl_IncrRefCount(vfsinitscript);
+ if(Tcl_FSAccess(vfsinitscript,F_OK)==0) {
+ /* Startup script should be set before calling Tcl_AppInit */
+ Tcl_SetStartupScript(vfsinitscript,NULL);
+ }
+ }
+ ::practcl::cputs zvfsboot " TclSetPreInitScript([::practcl::tcl_to_c $preinitscript])\;"
+ ::practcl::cputs zvfsboot " \x7D else \x7B"
+ ::practcl::cputs zvfsboot " TclSetPreInitScript([::practcl::tcl_to_c {
+foreach path {
+ ../tcl
+} {
+ set p [file join $path library init.tcl]
+ if {[file exists [file join $path library init.tcl]]} {
+ set ::tcl_library [file normalize [file join $path library]]
+ break
+ }
+}
+foreach path {
+ ../tk
+} {
+ if {[file exists [file join $path library tk.tcl]]} {
+ set ::tk_library [file normalize [file join $path library]]
+ break
+ }
+}
+}])\;"
+
+ ::practcl::cputs zvfsboot " \x7D"
+ ::practcl::cputs zvfsboot " return TCL_OK;"
+
+ if {[$PROJECT define get TEACUP_OS] eq "windows"} {
+ set header {int %mainhook%(int *argc, TCHAR ***argv)}
+ } else {
+ set header {int %mainhook%(int *argc, char ***argv)}
+ }
+ $PROJECT c_function [string map $map $header] [string map $map $zvfsboot]
+
+ practcl::cputs appinit "int %mainfunc%(Tcl_Interp *interp) \x7B"
+
+ # Build AppInit()
+ set appinit {}
+ practcl::cputs appinit {
+ if ((Tcl_Init)(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+}
+ set main_init_script {}
+
+ foreach {statpkg info} $statpkglist {
+ set initfunc {}
+ if {[dict exists $info initfunc]} {
+ set initfunc [dict get $info initfunc]
+ }
+ if {$initfunc eq {}} {
+ set initfunc [string totitle ${statpkg}]_Init
+ }
+ if {![dict exists $info version]} {
+ error "$statpkg HAS NO VERSION"
+ }
+ # We employ a NULL to prevent the package system from thinking the
+ # package is actually loaded into the interpreter
+ $PROJECT code header "extern Tcl_PackageInitProc $initfunc\;\n"
+ set script [list package ifneeded $statpkg [dict get $info version] [list ::load {} $statpkg]]
+ append main_init_script \n [list set ::kitpkg(${statpkg}) $script]
+ if {[dict get $info autoload]} {
+ ::practcl::cputs appinit " if(${initfunc}(interp)) return TCL_ERROR\;"
+ ::practcl::cputs appinit " Tcl_StaticPackage(interp,\"$statpkg\",$initfunc,NULL)\;"
+ } else {
+ ::practcl::cputs appinit "\n Tcl_StaticPackage(NULL,\"$statpkg\",$initfunc,NULL)\;"
+ append main_init_script \n $script
+ }
+ }
+ append main_init_script \n {
+if {[file exists [file join $::SRCDIR packages.tcl]]} {
+ #In a wrapped exe, we don't go out to the environment
+ set dir $::SRCDIR
+ source [file join $::SRCDIR packages.tcl]
+}
+# Specify a user-specific startup file to invoke if the application
+# is run interactively. Typically the startup file is "~/.apprc"
+# where "app" is the name of the application. If this line is deleted
+# then no user-specific startup file will be run under any conditions.
+ }
+ append main_init_script \n [list set tcl_rcFileName [$PROJECT define get tcl_rcFileName ~/.tclshrc]]
+ practcl::cputs appinit " Tcl_Eval(interp,[::practcl::tcl_to_c $main_init_script]);"
+ practcl::cputs appinit { return TCL_OK;}
+ $PROJECT c_function [string map $map "int %mainfunc%(Tcl_Interp *interp)"] [string map $map $appinit]
+}
+
+}
+
+
+::oo::class create ::practcl::build.gcc {
+ superclass ::practcl::build
+
+ method build-compile-sources {PROJECT COMPILE {CPPCOMPILE {}}} {
+ set EXTERN_OBJS {}
+ set OBJECTS {}
+ set result {}
+ set builddir [$PROJECT define get builddir]
+ file mkdir [file join $builddir objs]
+ set debug [$PROJECT define get debug 0]
+ if {$CPPCOMPILE eq {}} {
+ set CPPCOMPILE $COMPILE
+ }
+ set task [${PROJECT} compile-products]
+ ###
+ # Compile the C sources
+ ###
+ foreach {ofile info} $task {
+ dict set task $ofile done 0
+ if {[dict exists $info external] && [dict get $info external]==1} {
+ dict set task $ofile external 1
+ } else {
+ dict set task $ofile external 0
+ }
+ if {[dict exists $info library]} {
+ dict set task $ofile done 1
+ continue
+ }
+ # Products with no cfile aren't compiled
+ if {![dict exists $info cfile] || [set cfile [dict get $info cfile]] eq {}} {
+ dict set task $ofile done 1
+ continue
+ }
+ set cfile [dict get $info cfile]
+ set ofilename [file join $builddir objs [file tail $ofile]]
+ if {$debug} {
+ set ofilename [file join $builddir objs [file rootname [file tail $ofile]].debug.o]
+ }
+ dict set task $ofile filename $ofilename
+ if {[file exists $ofilename] && [file mtime $ofilename]>[file mtime $cfile]} {
+ lappend result $ofilename
+ dict set task $ofile done 1
+ continue
+ }
+ if {![dict exist $info command]} {
+ if {[file extension $cfile] in {.c++ .cpp}} {
+ set cmd $CPPCOMPILE
+ } else {
+ set cmd $COMPILE
+ }
+ if {[dict exists $info extra]} {
+ append cmd " [dict get $info extra]"
+ }
+ append cmd " -c $cfile"
+ append cmd " -o $ofilename"
+ dict set task $ofile command $cmd
+ }
+ }
+ set completed 0
+ while {$completed==0} {
+ set completed 1
+ foreach {ofile info} $task {
+ set waiting {}
+ if {[dict exists $info done] && [dict get $info done]} continue
+ if {[dict exists $info depend]} {
+ foreach file [dict get $info depend] {
+ if {[dict exists $task $file command] && [dict exists $task $file done] && [dict get $task $file done] != 1} {
+ set waiting $file
+ break
+ }
+ }
+ }
+ if {$waiting ne {}} {
+ set completed 0
+ puts "$ofile waiting for $waiting"
+ continue
+ }
+ if {[dict exists $info command]} {
+ set cmd [dict get $info command]
+ puts "$cmd"
+ exec {*}$cmd >&@ stdout
+ }
+ lappend result [dict get $info filename]
+ dict set task $ofile done 1
+ }
+ }
+ return $result
+}
+
+method build-Makefile {path PROJECT} {
+ array set proj [$PROJECT define dump]
+ set path $proj(builddir)
+ cd $path
+ set includedir .
+ #lappend includedir [::practcl::file_relative $path $proj(TCL_INCLUDES)]
+ lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TCL_SRC_DIR) generic]]]
+ lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(srcdir) generic]]]
+ foreach include [$PROJECT generate-include-directory] {
+ set cpath [::practcl::file_relative $path [file normalize $include]]
+ if {$cpath ni $includedir} {
+ lappend includedir $cpath
+ }
+ }
+ set INCLUDES "-I[join $includedir " -I"]"
+ set NAME [string toupper $proj(name)]
+ set result {}
+ set products {}
+ set libraries {}
+ set thisline {}
+ ::practcl::cputs result "${NAME}_DEFS = $proj(DEFS)\n"
+ ::practcl::cputs result "${NAME}_INCLUDES = -I\"[join $includedir "\" -I\""]\"\n"
+ ::practcl::cputs result "${NAME}_COMPILE = \$(CC) \$(CFLAGS) \$(PKG_CFLAGS) \$(${NAME}_DEFS) \$(${NAME}_INCLUDES) \$(INCLUDES) \$(AM_CPPFLAGS) \$(CPPFLAGS) \$(AM_CFLAGS)"
+ ::practcl::cputs result "${NAME}_CPPCOMPILE = \$(CXX) \$(CFLAGS) \$(PKG_CFLAGS) \$(${NAME}_DEFS) \$(${NAME}_INCLUDES) \$(INCLUDES) \$(AM_CPPFLAGS) \$(CPPFLAGS) \$(AM_CFLAGS)"
+
+ foreach {ofile info} [$PROJECT compile-products] {
+ dict set products $ofile $info
+ if {[dict exists $info library]} {
+lappend libraries $ofile
+continue
+ }
+ if {[dict exists $info depend]} {
+ ::practcl::cputs result "\n${ofile}: [dict get $info depend]"
+ } else {
+ ::practcl::cputs result "\n${ofile}:"
+ }
+ set cfile [dict get $info cfile]
+ if {[file extension $cfile] in {.c++ .cpp}} {
+ set cmd "\t\$\(${NAME}_CPPCOMPILE\)"
+ } else {
+ set cmd "\t\$\(${NAME}_COMPILE\)"
+ }
+ if {[dict exists $info extra]} {
+ append cmd " [dict get $info extra]"
+ }
+ append cmd " -c [dict get $info cfile] -o \$@\n\t"
+ ::practcl::cputs result $cmd
+ }
+
+ set map {}
+ lappend map %LIBRARY_NAME% $proj(name)
+ lappend map %LIBRARY_VERSION% $proj(version)
+ lappend map %LIBRARY_VERSION_NODOTS% [string map {. {}} $proj(version)]
+ lappend map %LIBRARY_PREFIX% [$PROJECT define getnull libprefix]
+
+ if {[string is true [$PROJECT define get SHARED_BUILD]]} {
+ set outfile [$PROJECT define get libfile]
+ } else {
+ set outfile [$PROJECT shared_library]
+ }
+ $PROJECT define set shared_library $outfile
+ ::practcl::cputs result "
+${NAME}_SHLIB = $outfile
+${NAME}_OBJS = [dict keys $products]
+"
+
+ #lappend map %OUTFILE% {\[$]@}
+ lappend map %OUTFILE% $outfile
+ lappend map %LIBRARY_OBJECTS% "\$(${NAME}_OBJS)"
+ ::practcl::cputs result "$outfile: \$(${NAME}_OBJS)"
+ ::practcl::cputs result "\t[string map $map [$PROJECT define get PRACTCL_SHARED_LIB]]"
+ if {[$PROJECT define get PRACTCL_VC_MANIFEST_EMBED_DLL] ni {: {}}} {
+ ::practcl::cputs result "\t[string map $map [$PROJECT define get PRACTCL_VC_MANIFEST_EMBED_DLL]]"
+ }
+ ::practcl::cputs result {}
+ if {[string is true [$PROJECT define get SHARED_BUILD]]} {
+ #set outfile [$PROJECT static_library]
+ set outfile $proj(name).a
+ } else {
+ set outfile [$PROJECT define get libfile]
+ }
+ $PROJECT define set static_library $outfile
+ dict set map %OUTFILE% $outfile
+ ::practcl::cputs result "$outfile: \$(${NAME}_OBJS)"
+ ::practcl::cputs result "\t[string map $map [$PROJECT define get PRACTCL_STATIC_LIB]]"
+ ::practcl::cputs result {}
+ return $result
+}
+
+###
+# Produce a static or dynamic library
+###
+method build-library {outfile PROJECT} {
+ array set proj [$PROJECT define dump]
+ set path $proj(builddir)
+ cd $path
+ set includedir .
+ #lappend includedir [::practcl::file_relative $path $proj(TCL_INCLUDES)]
+ lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TCL_SRC_DIR) generic]]]
+ lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(srcdir) generic]]]
+ if {[$PROJECT define get tk 0]} {
+ lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) generic]]]
+ lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) ttk]]]
+ lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) xlib]]]
+ lappend includedir [::practcl::file_relative $path [file normalize $proj(TK_BIN_DIR)]]
+ }
+ foreach include [$PROJECT generate-include-directory] {
+ set cpath [::practcl::file_relative $path [file normalize $include]]
+ if {$cpath ni $includedir} {
+ lappend includedir $cpath
+ }
+ }
+ my build-cflags $PROJECT $proj(DEFS) name version defs
+ set NAME [string toupper $name]
+ set debug [$PROJECT define get debug 0]
+ set os [$PROJECT define get TEACUP_OS]
+
+ set INCLUDES "-I[join $includedir " -I"]"
+ if {$debug} {
+ set COMPILE "$proj(CC) $proj(CFLAGS_DEBUG) -ggdb \
+$proj(CFLAGS_WARNING) $INCLUDES $defs"
+
+ if {[info exists proc(CXX)]} {
+ set COMPILECPP "$proj(CXX) $defs $INCLUDES $proj(CFLAGS_DEBUG) -ggdb \
+ $defs $proj(CFLAGS_WARNING)"
+ } else {
+ set COMPILECPP $COMPILE
+ }
+ } else {
+ set COMPILE "$proj(CC) $proj(CFLAGS) $defs $INCLUDES "
+
+ if {[info exists proc(CXX)]} {
+ set COMPILECPP "$proj(CXX) $defs $INCLUDES $proj(CFLAGS) $defs"
+ } else {
+ set COMPILECPP $COMPILE
+ }
+ }
+
+ set products [my build-compile-sources $PROJECT $COMPILE $COMPILECPP]
+
+ set map {}
+ lappend map %LIBRARY_NAME% $proj(name)
+ lappend map %LIBRARY_VERSION% $proj(version)
+ lappend map %LIBRARY_VERSION_NODOTS% [string map {. {}} $proj(version)]
+ lappend map %OUTFILE% $outfile
+ lappend map %LIBRARY_OBJECTS% $products
+ lappend map {${CFLAGS}} "$proj(CFLAGS_DEFAULT) $proj(CFLAGS_WARNING)"
+
+ if {[string is true [$PROJECT define get SHARED_BUILD 1]]} {
+ set cmd [$PROJECT define get PRACTCL_SHARED_LIB]
+ append cmd " [$PROJECT define get PRACTCL_LIBS]"
+ set cmd [string map $map $cmd]
+ puts $cmd
+ exec {*}$cmd >&@ stdout
+ if {[$PROJECT define get PRACTCL_VC_MANIFEST_EMBED_DLL] ni {: {}}} {
+ set cmd [string map $map [$PROJECT define get PRACTCL_VC_MANIFEST_EMBED_DLL]]
+ puts $cmd
+ exec {*}$cmd >&@ stdout
+ }
+ } else {
+ set cmd [string map $map [$PROJECT define get PRACTCL_STATIC_LIB]]
+ puts $cmd
+ exec {*}$cmd >&@ stdout
+ }
+ set ranlib [$PROJECT define get RANLIB]
+ if {$ranlib ni {{} :}} {
+ catch {exec $ranlib $outfile}
+ }
+}
+
+###
+# Produce a static executable
+###
+method build-tclsh {outfile PROJECT} {
+ puts " BUILDING STATIC TCLSH "
+ set TCLOBJ [$PROJECT project TCLCORE]
+ set PKG_OBJS {}
+ foreach item [$PROJECT link list core.library] {
+ if {[string is true [$item define get static]]} {
+ lappend PKG_OBJS $item
+ }
+ }
+ foreach item [$PROJECT link list package] {
+ if {[string is true [$item define get static]]} {
+ lappend PKG_OBJS $item
+ }
+ }
+ array set TCL [$TCLOBJ config.sh]
+
+ set TKOBJ [$PROJECT project tk]
+ if {[info command $TKOBJ] eq {}} {
+ set TKOBJ ::noop
+ $PROJECT define set static_tk 0
+ } else {
+ array set TK [$TKOBJ config.sh]
+ $PROJECT define set static_tk [$TKOBJ define get static]
+ set TKSRCDIR [$TKOBJ define get srcdir]
+ }
+ set path [file dirname $outfile]
+ cd $path
+ ###
+ # For a static Tcl shell, we need to build all local sources
+ # with the same DEFS flags as the tcl core was compiled with.
+ # The DEFS produced by a TEA extension aren't intended to operate
+ # with the internals of a staticly linked Tcl
+ ###
+ my build-cflags $PROJECT $TCL(defs) name version defs
+ set debug [$PROJECT define get debug 0]
+ set NAME [string toupper $name]
+ set result {}
+ set libraries {}
+ set thisline {}
+ set OBJECTS {}
+ set EXTERN_OBJS {}
+ foreach obj $PKG_OBJS {
+ $obj compile
+ set config($obj) [$obj config.sh]
+ }
+ set os [$PROJECT define get TEACUP_OS]
+ set TCLSRCDIR [$TCLOBJ define get srcdir]
+
+ set includedir .
+ foreach include [$TCLOBJ generate-include-directory] {
+ set cpath [::practcl::file_relative $path [file normalize $include]]
+ if {$cpath ni $includedir} {
+ lappend includedir $cpath
+ }
+ }
+ lappend includedir [::practcl::file_relative $path [file normalize ../tcl/compat/zlib]]
+ foreach include [$PROJECT generate-include-directory] {
+ set cpath [::practcl::file_relative $path [file normalize $include]]
+ if {$cpath ni $includedir} {
+ lappend includedir $cpath
+ }
+ }
+
+ set INCLUDES "-I[join $includedir " -I"]"
+ if {$debug} {
+ set COMPILE "$TCL(cc) $TCL(shlib_cflags) $TCL(cflags_debug) -ggdb \
+$TCL(cflags_warning) $TCL(extra_cflags) $INCLUDES"
+ } else {
+ set COMPILE "$TCL(cc) $TCL(shlib_cflags) $TCL(cflags_optimize) \
+$TCL(cflags_warning) $TCL(extra_cflags) $INCLUDES"
+ }
+ append COMPILE " " $defs
+ lappend OBJECTS {*}[my build-compile-sources $PROJECT $COMPILE $COMPILE]
+
+ set TCLSRC [file normalize $TCLSRCDIR]
+
+ if {[${PROJECT} define get TEACUP_OS] eq "windows"} {
+ set windres [$PROJECT define get RC windres]
+ set RSOBJ [file join $path build tclkit.res.o]
+ set RCSRC [${PROJECT} define get kit_resource_file]
+ set cmd [list $windres -o $RSOBJ -DSTATIC_BUILD --include [::practcl::file_relative $path [file join $TCLSRC generic]]]
+ if {[$PROJECT define get static_tk]} {
+ if {$RCSRC eq {} || ![file exists $RCSRC]} {
+ set RCSRC [file join $TKSRCDIR win rc wish.rc]
+ }
+ set TKSRC [file normalize $TKSRCDIR]
+ lappend cmd --include [::practcl::file_relative $path [file join $TKSRC generic]] \
+ --include [::practcl::file_relative $path [file join $TKSRC win]] \
+ --include [::practcl::file_relative $path [file join $TKSRC win rc]]
+ } else {
+ if {$RCSRC eq {} || ![file exists $RCSRC]} {
+ set RCSRC [file join $TCLSRCDIR tclsh.rc]
+ }
+ }
+ foreach item [${PROJECT} define get resource_include] {
+ lappend cmd --include [::practcl::file_relative $path [file normalize $item]]
+ }
+ lappend cmd $RCSRC
+ ::practcl::doexec {*}$cmd
+ lappend OBJECTS $RSOBJ
+ set LDFLAGS_CONSOLE {-mconsole -pipe -static-libgcc}
+ set LDFLAGS_WINDOW {-mwindows -pipe -static-libgcc}
+ } else {
+ set LDFLAGS_CONSOLE {}
+ set LDFLAGS_WINDOW {}
+ }
+ puts "***"
+ if {$debug} {
+ set cmd "$TCL(cc) $TCL(shlib_cflags) $TCL(cflags_debug) \
+$TCL(cflags_warning) $TCL(extra_cflags) $INCLUDES"
+ } else {
+ set cmd "$TCL(cc) $TCL(shlib_cflags) $TCL(cflags_optimize) \
+$TCL(cflags_warning) $TCL(extra_cflags) $INCLUDES"
+ }
+ append cmd " $OBJECTS"
+ append cmd " $EXTERN_OBJS "
+ # On OSX it is impossibly to generate a completely static
+ # executable
+ if {[$PROJECT define get TEACUP_OS] ne "macosx"} {
+ append cmd " -static "
+ }
+ if {$debug} {
+ if {$os eq "windows"} {
+ append cmd " -L${TCL(src_dir)}/win -ltcl86g"
+ if {[$PROJECT define get static_tk]} {
+ append cmd " -L${TK(src_dir)}/win -ltk86g"
+ }
+ } else {
+ append cmd " -L${TCL(src_dir)}/unix -ltcl86g"
+ if {[$PROJECT define get static_tk]} {
+ append cmd " -L${TK(src_dir)}/unix -ltk86g"
+ }
+ }
+ } else {
+ append cmd " $TCL(build_lib_spec)"
+ if {[$PROJECT define get static_tk]} {
+ append cmd " $TK(build_lib_spec)"
+ }
+ }
+ foreach obj $PKG_OBJS {
+ append cmd " [$obj linker-products $config($obj)]"
+ }
+ append cmd " $TCL(libs) "
+ if {[$PROJECT define get static_tk]} {
+ append cmd " $TK(libs)"
+ }
+ foreach obj $PKG_OBJS {
+ append cmd " [$obj linker-external $config($obj)]"
+ }
+ if {$debug} {
+ if {$os eq "windows"} {
+ append cmd " -L${TCL(src_dir)}/win ${TCL(stub_lib_flag)}"
+ if {[$PROJECT define get static_tk]} {
+ append cmd " -L${TK(src_dir)}/win ${TK(stub_lib_flag)}"
+ }
+ } else {
+ append cmd " -L${TCL(src_dir)}/unix ${TCL(stub_lib_flag)}"
+ if {[$PROJECT define get static_tk]} {
+ append cmd " -L${TK(src_dir)}/unix ${TK(stub_lib_flag)}"
+ }
+ }
+ } else {
+ append cmd " $TCL(build_stub_lib_spec)"
+ if {[$PROJECT define get static_tk]} {
+ append cmd " $TK(build_stub_lib_spec)"
+ }
+ }
+ append cmd " -o $outfile $LDFLAGS_CONSOLE"
+ puts "LINK: $cmd"
+ exec {*}$cmd >&@ stdout
+}
+}
+
+
+::oo::class create ::practcl::build.msvc {
+ superclass ::practcl::build
+
+}
+
+::oo::class create ::practcl::target_obj {
+ superclass ::practcl::metaclass
+
+ constructor {name info} {
+ my variable define triggered domake
+ set triggered 0
+ set domake 0
+ set define(name) $name
+ set data [uplevel 2 [list subst $info]]
+ array set define $data
+ my select
+ my initialize
+ }
+
+ method do {} {
+ my variable domake
+ return $domake
+ }
+
+ method check {} {
+ my variable needs_make domake
+ if {$domake} {
+ return 1
+ }
+ if {[info exists needs_make]} {
+ return $needs_make
+ }
+ set needs_make 0
+ foreach item [my define get depends] {
+ if {![dict exists $::make_objects $item]} continue
+ set depobj [dict get $::make_objects $item]
+ if {$depobj eq [self]} {
+ puts "WARNING [self] depends on itself"
+ continue
+ }
+ if {[$depobj check]} {
+ set needs_make 1
+ }
+ }
+ if {!$needs_make} {
+ set filename [my define get filename]
+ if {$filename ne {} && ![file exists $filename]} {
+ set needs_make 1
+ }
+ }
+ return $needs_make
+ }
+
+ method triggers {} {
+ my variable triggered domake define
+ if {$triggered} {
+ return $domake
+ }
+ set triggered 1
+ foreach item [my define get depends] {
+ if {![dict exists $::make_objects $item]} continue
+ set depobj [dict get $::make_objects $item]
+ if {$depobj eq [self]} {
+ puts "WARNING [self] triggers itself"
+ continue
+ } else {
+ set r [$depobj check]
+ if {$r} {
+ $depobj triggers
+ }
+ }
+ }
+ if {[info exists ::make($define(name))] && $::make($define(name))} {
+ return
+ }
+ set ::make($define(name)) 1
+ ::practcl::trigger {*}[my define get triggers]
+ }
+}
+
+
+###
+# Define the metaclass
+###
+::oo::class create ::practcl::object {
+ superclass ::practcl::metaclass
+
+ constructor {parent args} {
+ my variable links define
+ set organs [$parent child organs]
+ my graft {*}$organs
+ array set define $organs
+ array set define [$parent child define]
+ array set links {}
+ if {[llength $args]==1 && [file exists [lindex $args 0]]} {
+ my InitializeSourceFile [lindex $args 0]
+ } elseif {[llength $args] == 1} {
+ set data [uplevel 1 [list subst [lindex $args 0]]]
+ array set define $data
+ my select
+ my initialize
+ } else {
+ array set define [uplevel 1 [list subst $args]]
+ my select
+ my initialize
+ }
+ }
+
+
+ method include_dir args {
+ my define add include_dir {*}$args
+ }
+
+ method include_directory args {
+ my define add include_dir {*}$args
+ }
+
+ method Collate_Source CWD {}
+
+
+ method child {method} {
+ return {}
+ }
+
+ method InitializeSourceFile filename {
+ my define set filename $filename
+ set class {}
+ switch [file extension $filename] {
+ .tcl {
+ set class ::practcl::dynamic
+ }
+ .h {
+ set class ::practcl::cheader
+ }
+ .c {
+ set class ::practcl::csource
+ }
+ .ini {
+ switch [file tail $filename] {
+ module.ini {
+ set class ::practcl::module
+ }
+ library.ini {
+ set class ::practcl::subproject
+ }
+ }
+ }
+ .so -
+ .dll -
+ .dylib -
+ .a {
+ set class ::practcl::clibrary
+ }
+ }
+ if {$class ne {}} {
+ oo::objdefine [self] class $class
+ my initialize
+ }
+ }
+
+ method add args {
+ my variable links
+ set object [::practcl::object new [self] {*}$args]
+ foreach linktype [$object linktype] {
+ lappend links($linktype) $object
+ }
+ return $object
+ }
+
+ method go {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable links
+ foreach {linktype objs} [array get links] {
+ foreach obj $objs {
+ $obj go
+ }
+ }
+ ::practcl::debug [list /[self] [self method] [self class]]
+ }
+
+ method code {section body} {
+ my variable code
+ ::practcl::cputs code($section) $body
+ }
+
+ method Ofile filename {
+ set lpath [my <module> define get localpath]
+ if {$lpath eq {}} {
+ set lpath [my <module> define get name]
+ }
+ return ${lpath}_[file rootname [file tail $filename]].o
+ }
+
+ method compile-products {} {
+ set filename [my define get filename]
+ set result {}
+ if {$filename ne {}} {
+ if {[my define exists ofile]} {
+ set ofile [my define get ofile]
+ } else {
+ set ofile [my Ofile $filename]
+ my define set ofile $ofile
+ }
+ lappend result $ofile [list cfile $filename extra [my define get extra] external [string is true -strict [my define get external]] object [self]]
+ }
+ foreach item [my link list subordinate] {
+ lappend result {*}[$item compile-products]
+ }
+ return $result
+ }
+
+ method generate-include-directory {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set result [my define get include_dir]
+ foreach obj [my link list product] {
+ foreach path [$obj generate-include-directory] {
+ lappend result $path
+ }
+ }
+ return $result
+ }
+
+ method generate-debug {{spaces {}}} {
+ set result {}
+ ::practcl::cputs result "$spaces[list [self] [list class [info object class [self]] filename [my define get filename]] links [my link list]]"
+ foreach item [my link list subordinate] {
+ practcl::cputs result [$item generate-debug "$spaces "]
+ }
+ return $result
+ }
+
+ # Empty template methods
+ method generate-cheader {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code cfunct cstruct methods tcltype tclprocs
+ set result {}
+ if {[info exists code(header)]} {
+ ::practcl::cputs result $code(header)
+ }
+ foreach obj [my link list product] {
+ # Exclude products that will generate their own C files
+ if {[$obj define get output_c] ne {}} continue
+ set dat [$obj generate-cheader]
+ if {[string length [string trim $dat]]} {
+ ::practcl::cputs result "/* BEGIN [$obj define get filename] generate-cheader */"
+ ::practcl::cputs result $dat
+ ::practcl::cputs result "/* END [$obj define get filename] generate-cheader */"
+ }
+ }
+ ::practcl::debug [list cfunct [info exists cfunct]]
+ if {[info exists cfunct]} {
+ foreach {funcname info} $cfunct {
+ if {[dict get $info public]} continue
+ ::practcl::cputs result "[dict get $info header]\;"
+ }
+ }
+ ::practcl::debug [list tclprocs [info exists tclprocs]]
+ if {[info exists tclprocs]} {
+ foreach {name info} $tclprocs {
+ if {[dict exists $info header]} {
+ ::practcl::cputs result "[dict get $info header]\;"
+ }
+ }
+ }
+ ::practcl::debug [list methods [info exists methods] [my define get cclass]]
+
+ if {[info exists methods]} {
+ set thisclass [my define get cclass]
+ foreach {name info} $methods {
+ if {[dict exists $info header]} {
+ ::practcl::cputs result "[dict get $info header]\;"
+ }
+ }
+ # Add the initializer wrapper for the class
+ ::practcl::cputs result "static int ${thisclass}_OO_Init(Tcl_Interp *interp)\;"
+ }
+ return $result
+ }
+
+ method generate-public-define {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code
+ set result {}
+ if {[info exists code(public-define)]} {
+ ::practcl::cputs result $code(public-define)
+ }
+ set result [::practcl::_tagblock $result c [my define get filename]]
+ foreach mod [my link list product] {
+ ::practcl::cputs result [$mod generate-public-define]
+ }
+ return $result
+ }
+
+ method generate-public-macro {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code
+ set result {}
+ if {[info exists code(public-macro)]} {
+ ::practcl::cputs result $code(public-macro)
+ }
+ set result [::practcl::_tagblock $result c [my define get filename]]
+ foreach mod [my link list product] {
+ ::practcl::cputs result [$mod generate-public-macro]
+ }
+ return $result
+ }
+
+ method generate-public-typedef {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code cstruct
+ set result {}
+ if {[info exists code(public-typedef)]} {
+ ::practcl::cputs result $code(public-typedef)
+ }
+ if {[info exists cstruct]} {
+ # Add defintion for native c data structures
+ foreach {name info} $cstruct {
+ if {[dict get $info public]==0} continue
+ ::practcl::cputs result "typedef struct $name ${name}\;"
+ if {[dict exists $info aliases]} {
+ foreach n [dict get $info aliases] {
+ ::practcl::cputs result "typedef struct $name ${n}\;"
+ }
+ }
+ }
+ }
+ set result [::practcl::_tagblock $result c [my define get filename]]
+ foreach mod [my link list product] {
+ ::practcl::cputs result [$mod generate-public-typedef]
+ }
+ return $result
+ }
+
+ method generate-private-typedef {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code cstruct
+ set result {}
+ if {[info exists code(private-typedef)]} {
+ ::practcl::cputs result $code(private-typedef)
+ }
+ if {[info exists cstruct]} {
+ # Add defintion for native c data structures
+ foreach {name info} $cstruct {
+ if {[dict get $info public]==1} continue
+ ::practcl::cputs result "typedef struct $name ${name}\;"
+ if {[dict exists $info aliases]} {
+ foreach n [dict get $info aliases] {
+ ::practcl::cputs result "typedef struct $name ${n}\;"
+ }
+ }
+ }
+ }
+ set result [::practcl::_tagblock $result c [my define get filename]]
+ foreach mod [my link list product] {
+ ::practcl::cputs result [$mod generate-private-typedef]
+ }
+ return $result
+ }
+
+ method generate-public-structure {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code cstruct
+ set result {}
+ if {[info exists code(public-structure)]} {
+ ::practcl::cputs result $code(public-structure)
+ }
+ if {[info exists cstruct]} {
+ foreach {name info} $cstruct {
+ if {[dict get $info public]==0} continue
+ if {[dict exists $info comment]} {
+ ::practcl::cputs result [dict get $info comment]
+ }
+ ::practcl::cputs result "struct $name \{[dict get $info body]\}\;"
+ }
+ }
+ set result [::practcl::_tagblock $result c [my define get filename]]
+ foreach mod [my link list product] {
+ ::practcl::cputs result [$mod generate-public-structure]
+ }
+ return $result
+ }
+
+
+ method generate-private-structure {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code cstruct
+ set result {}
+ if {[info exists code(private-structure)]} {
+ ::practcl::cputs result $code(private-structure)
+ }
+ if {[info exists cstruct]} {
+ foreach {name info} $cstruct {
+ if {[dict get $info public]==1} continue
+ if {[dict exists $info comment]} {
+ ::practcl::cputs result [dict get $info comment]
+ }
+ ::practcl::cputs result "struct $name \{[dict get $info body]\}\;"
+ }
+ }
+ set result [::practcl::_tagblock $result c [my define get filename]]
+ foreach mod [my link list product] {
+ ::practcl::cputs result [$mod generate-private-structure]
+ }
+ return $result
+ }
+
+ method generate-public-headers {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code tcltype
+ set result {}
+ if {[info exists code(public-header)]} {
+ ::practcl::cputs result $code(public-header)
+ }
+ if {[info exists tcltype]} {
+ foreach {type info} $tcltype {
+ if {![dict exists $info cname]} {
+ set cname [string tolower ${type}]_tclobjtype
+ dict set tcltype $type cname $cname
+ } else {
+ set cname [dict get $info cname]
+ }
+ ::practcl::cputs result "extern const Tcl_ObjType $cname\;"
+ }
+ }
+ if {[info exists code(public)]} {
+ ::practcl::cputs result $code(public)
+ }
+ set result [::practcl::_tagblock $result c [my define get filename]]
+ foreach mod [my link list product] {
+ ::practcl::cputs result [$mod generate-public-headers]
+ }
+ return $result
+ }
+
+ method generate-stub-function {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code cfunct tcltype
+ set result {}
+ foreach mod [my link list product] {
+ foreach {funct def} [$mod generate-stub-function] {
+ dict set result $funct $def
+ }
+ }
+ if {[info exists cfunct]} {
+ foreach {funcname info} $cfunct {
+ if {![dict get $info export]} continue
+ dict set result $funcname [dict get $info header]
+ }
+ }
+ return $result
+ }
+
+ method generate-public-function {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code cfunct tcltype
+ set result {}
+
+ if {[my define get initfunc] ne {}} {
+ ::practcl::cputs result "int [my define get initfunc](Tcl_Interp *interp);"
+ }
+ if {[info exists cfunct]} {
+ foreach {funcname info} $cfunct {
+ if {![dict get $info public]} continue
+ ::practcl::cputs result "[dict get $info header]\;"
+ }
+ }
+ set result [::practcl::_tagblock $result c [my define get filename]]
+ foreach mod [my link list product] {
+ ::practcl::cputs result [$mod generate-public-function]
+ }
+ return $result
+ }
+
+ method generate-public-includes {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set includes {}
+ foreach item [my define get public-include] {
+ if {$item ni $includes} {
+ lappend includes $item
+ }
+ }
+ foreach mod [my link list product] {
+ foreach item [$mod generate-public-includes] {
+ if {$item ni $includes} {
+ lappend includes $item
+ }
+ }
+ }
+ return $includes
+ }
+ method generate-public-verbatim {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set includes {}
+ foreach item [my define get public-verbatim] {
+ if {$item ni $includes} {
+ lappend includes $item
+ }
+ }
+ foreach mod [my link list subordinate] {
+ foreach item [$mod generate-public-verbatim] {
+ if {$item ni $includes} {
+ lappend includes $item
+ }
+ }
+ }
+ return $includes
+ }
+ ###
+ # This methods generates the contents of an amalgamated .h file
+ # which describes the public API of this module
+ ###
+ method generate-h {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set result {}
+ set includes [my generate-public-includes]
+ foreach inc $includes {
+ if {[string index $inc 0] ni {< \"}} {
+ ::practcl::cputs result "#include \"$inc\""
+ } else {
+ ::practcl::cputs result "#include $inc"
+ }
+ }
+
+ foreach method {
+ generate-public-define
+ generate-public-macro
+ generate-public-typedef
+ generate-public-structure
+ } {
+ ::practcl::cputs result "/* BEGIN SECTION $method */"
+ ::practcl::cputs result [my $method]
+ ::practcl::cputs result "/* END SECTION $method */"
+ }
+
+ foreach file [my generate-public-verbatim] {
+ ::practcl::cputs result "/* BEGIN $file */"
+ ::practcl::cputs result [::practcl::cat $file]
+ ::practcl::cputs result "/* END $file */"
+ }
+
+ foreach method {
+ generate-public-headers
+ generate-public-function
+ } {
+ ::practcl::cputs result "/* BEGIN SECTION $method */"
+ ::practcl::cputs result [my $method]
+ ::practcl::cputs result "/* END SECTION $method */"
+ }
+ return $result
+ }
+
+ method IncludeAdd {headervar args} {
+ upvar 1 $headervar headers
+ foreach inc $args {
+ if {[string index $inc 0] ni {< \"}} {
+ set inc "\"$inc\""
+ }
+ if {$inc ni $headers} {
+ lappend headers $inc
+ }
+ }
+ }
+
+ ###
+ # This methods generates the contents of an amalgamated .c file
+ # which implements the loader for a batch of tools
+ ###
+ method generate-c {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set result {
+/* This file was generated by practcl */
+ }
+ set includes {}
+
+ foreach mod [my link list product] {
+ # Signal modules to formulate final implementation
+ $mod go
+ }
+ set headers {}
+
+ my IncludeAdd headers <tcl.h> <tclOO.h>
+ if {[my define get tk 0]} {
+ my IncludeAdd headers <tk.h>
+ }
+ if {[my define get output_h] ne {}} {
+ my IncludeAdd headers [my define get output_h]
+ }
+ my IncludeAdd headers {*}[my define get include]
+
+ foreach mod [my link list dynamic] {
+ my IncludeAdd headers {*}[$mod define get include]
+ }
+ foreach inc $headers {
+ ::practcl::cputs result "#include $inc"
+ }
+ foreach {method} {
+ generate-cheader
+ generate-private-typedef
+ generate-private-structure
+ generate-cstruct
+ generate-constant
+ generate-cfunct
+ generate-cmethod
+ } {
+ set dat [my $method]
+ if {[string length [string trim $dat]]} {
+ ::practcl::cputs result "/* BEGIN $method [my define get filename] */"
+ ::practcl::cputs result $dat
+ ::practcl::cputs result "/* END $method [my define get filename] */"
+ }
+ }
+ ::practcl::debug [list /[self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ return $result
+ }
+
+
+ method generate-loader {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set result {}
+ if {[my define get initfunc] eq {}} return
+ ::practcl::cputs result "
+extern int DLLEXPORT [my define get initfunc]( Tcl_Interp *interp ) \{"
+ ::practcl::cputs result {
+ /* Initialise the stubs tables. */
+ #ifdef USE_TCL_STUBS
+ if (Tcl_InitStubs(interp, "8.6", 0)==NULL) return TCL_ERROR;
+ if (TclOOInitializeStubs(interp, "1.0") == NULL) return TCL_ERROR;
+}
+ if {[my define get tk 0]} {
+ ::practcl::cputs result { if (Tk_InitStubs(interp, "8.6", 0)==NULL) return TCL_ERROR;}
+ }
+ ::practcl::cputs result { #endif}
+ set TCLINIT [my generate-tcl-pre]
+ if {[string length $TCLINIT]} {
+ ::practcl::cputs result " if(Tcl_Eval(interp,[::practcl::tcl_to_c $TCLINIT])) return TCL_ERROR ;"
+ }
+ foreach item [my link list product] {
+ if {[$item define get output_c] ne {}} {
+ ::practcl::cputs result [$item generate-cinit-external]
+ } else {
+ ::practcl::cputs result [$item generate-cinit]
+ }
+ }
+ set TCLINIT [my generate-tcl-post]
+ if {[string length $TCLINIT]} {
+ ::practcl::cputs result " if(Tcl_Eval(interp,[::practcl::tcl_to_c $TCLINIT])) return TCL_ERROR ;"
+ }
+ if {[my define exists pkg_name]} {
+ ::practcl::cputs result " if (Tcl_PkgProvide(interp, \"[my define get pkg_name [my define get name]]\" , \"[my define get pkg_vers [my define get version]]\" )) return TCL_ERROR\;"
+ }
+ ::practcl::cputs result " return TCL_OK\;\n\}\n"
+ return $result
+ }
+
+ ###
+ # This methods generates any Tcl script file
+ # which is required to pre-initialize the C library
+ ###
+ method generate-tcl-pre {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set result {}
+ my variable code
+ if {[info exists code(tcl)]} {
+ set result [::practcl::_tagblock $code(tcl) tcl [my define get filename]]
+ }
+ if {[info exists code(tcl-pre)]} {
+ set result [::practcl::_tagblock $code(tcl) tcl [my define get filename]]
+ }
+ foreach mod [my link list product] {
+ ::practcl::cputs result [$mod generate-tcl-pre]
+ }
+ return $result
+ }
+
+ method generate-tcl-post {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set result {}
+ my variable code
+ if {[info exists code(tcl-post)]} {
+ set result [::practcl::_tagblock $code(tcl-post) tcl [my define get filename]]
+ }
+ foreach mod [my link list product] {
+ ::practcl::cputs result [$mod generate-tcl-post]
+ }
+ return $result
+ }
+
+ method static-packages {} {
+ set result [my define get static_packages]
+ set statpkg [my define get static_pkg]
+ set initfunc [my define get initfunc]
+ if {$initfunc ne {}} {
+ set pkg_name [my define get pkg_name]
+ if {$pkg_name ne {}} {
+ dict set result $pkg_name initfunc $initfunc
+ dict set result $pkg_name version [my define get version [my define get pkg_vers]]
+ dict set result $pkg_name autoload [my define get autoload 0]
+ }
+ }
+ foreach item [my link list subordinate] {
+ foreach {pkg info} [$item static-packages] {
+ dict set result $pkg $info
+ }
+ }
+ return $result
+ }
+
+ method target {method args} {
+ switch $method {
+ is_unix { return [expr {$::tcl_platform(platform) eq "unix"}] }
+ }
+ }
+
+}
+
+::oo::class create ::practcl::product {
+ superclass ::practcl::object
+
+ method linktype {} {
+ return {subordinate product}
+ }
+
+ method include header {
+ my define add include $header
+ }
+
+ method cstructure {name definition {argdat {}}} {
+ my variable cstruct
+ dict set cstruct $name body $definition
+ foreach {f v} $argdat {
+ dict set cstruct $name $f $v
+ }
+ if {![dict exists $cstruct $name public]} {
+ dict set cstruct $name public 1
+ }
+ }
+
+ method generate-cinit {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code
+ set result {}
+ if {[info exists code(cinit)]} {
+ ::practcl::cputs result $code(cinit)
+ }
+ if {[my define get initfunc] ne {}} {
+ ::practcl::cputs result " if([my define get initfunc](interp)!=TCL_OK) return TCL_ERROR\;"
+ }
+ set result [::practcl::_tagblock $result c [my define get filename]]
+ foreach obj [my link list product] {
+ ::practcl::cputs result [$obj generate-cinit]
+ }
+ return $result
+ }
+}
+
+###
+# Dynamic blocks do not generate their own .c files,
+# instead the contribute to the amalgamation
+# of the main library file
+###
+::oo::class create ::practcl::dynamic {
+ superclass ::practcl::product
+
+ # Retrieve any additional source files required
+
+ method compile-products {} {
+ set filename [my define get output_c]
+ set result {}
+ if {$filename ne {}} {
+ if {[my define exists ofile]} {
+ set ofile [my define get ofile]
+ } else {
+ set ofile [my Ofile $filename]
+ my define set ofile $ofile
+ }
+ lappend result $ofile [list cfile $filename extra [my define get extra] external [string is true -strict [my define get external]]]
+ } else {
+ set filename [my define get cfile]
+ if {$filename ne {}} {
+ if {[my define exists ofile]} {
+ set ofile [my define get ofile]
+ } else {
+ set ofile [my Ofile $filename]
+ my define set ofile $ofile
+ }
+ lappend result $ofile [list cfile $filename extra [my define get extra] external [string is true -strict [my define get external]]]
+ }
+ }
+ foreach item [my link list subordinate] {
+ lappend result {*}[$item compile-products]
+ }
+ return $result
+ }
+
+ method implement path {
+ my go
+ my Collate_Source $path
+ if {[my define get output_c] eq {}} return
+ set filename [file join $path [my define get output_c]]
+ my define set cfile $filename
+ set fout [open $filename w]
+ puts $fout [my generate-c]
+ if {[my define get initfunc] ne {}} {
+ puts $fout "extern int DLLEXPORT [my define get initfunc]( Tcl_Interp *interp ) \x7B"
+ puts $fout [my generate-cinit]
+ if {[my define get pkg_name] ne {}} {
+ puts $fout " Tcl_PkgProvide(interp, \"[my define get pkg_name]\", \"[my define get pkg_vers]\");"
+ }
+ puts $fout " return TCL_OK\;"
+ puts $fout "\x7D"
+ }
+ close $fout
+ }
+
+ method initialize {} {
+ set filename [my define get filename]
+ if {$filename eq {}} {
+ return
+ }
+ if {[my define get name] eq {}} {
+ my define set name [file tail [file rootname $filename]]
+ }
+ if {[my define get localpath] eq {}} {
+ my define set localpath [my <module> define get localpath]_[my define get name]
+ }
+ ::source $filename
+ }
+
+ method linktype {} {
+ return {subordinate product dynamic}
+ }
+
+ ###
+ # Populate const static data structures
+ ###
+ method generate-cstruct {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code cstruct methods tcltype
+ set result {}
+ if {[info exists code(struct)]} {
+ ::practcl::cputs result $code(struct)
+ }
+ foreach obj [my link list dynamic] {
+ # Exclude products that will generate their own C files
+ if {[$obj define get output_c] ne {}} continue
+ ::practcl::cputs result [$obj generate-cstruct]
+ }
+ return $result
+ }
+
+ method generate-constant {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set result {}
+ my variable code cstruct methods tcltype
+ if {[info exists code(constant)]} {
+ ::practcl::cputs result "/* [my define get filename] CONSTANT */"
+ ::practcl::cputs result $code(constant)
+ }
+ if {[info exists cstruct]} {
+ foreach {name info} $cstruct {
+ set map {}
+ lappend map @NAME@ $name
+ lappend map @MACRO@ GET[string toupper $name]
+
+ if {[dict exists $info deleteproc]} {
+ lappend map @DELETEPROC@ [dict get $info deleteproc]
+ } else {
+ lappend map @DELETEPROC@ NULL
+ }
+ if {[dict exists $info cloneproc]} {
+ lappend map @CLONEPROC@ [dict get $info cloneproc]
+ } else {
+ lappend map @CLONEPROC@ NULL
+ }
+ ::practcl::cputs result [string map $map {
+const static Tcl_ObjectMetadataType @NAME@DataType = {
+ TCL_OO_METADATA_VERSION_CURRENT,
+ "@NAME@",
+ @DELETEPROC@,
+ @CLONEPROC@
+};
+#define @MACRO@(OBJCONTEXT) (@NAME@ *) Tcl_ObjectGetMetadata(OBJCONTEXT,&@NAME@DataType)
+}]
+ }
+ }
+ if {[info exists tcltype]} {
+ foreach {type info} $tcltype {
+ dict with info {}
+ ::practcl::cputs result "const Tcl_ObjType $cname = \{\n .freeIntRepProc = &${freeproc},\n .dupIntRepProc = &${dupproc},\n .updateStringProc = &${updatestringproc},\n .setFromAnyProc = &${setfromanyproc}\n\}\;"
+ }
+ }
+
+ if {[info exists methods]} {
+ set mtypes {}
+ foreach {name info} $methods {
+ set callproc [dict get $info callproc]
+ set methodtype [dict get $info methodtype]
+ if {$methodtype in $mtypes} continue
+ lappend mtypes $methodtype
+ ###
+ # Build the data struct for this method
+ ###
+ ::practcl::cputs result "const static Tcl_MethodType $methodtype = \{"
+ ::practcl::cputs result " .version = TCL_OO_METADATA_VERSION_CURRENT,\n .name = \"$name\",\n .callProc = $callproc,"
+ if {[dict exists $info deleteproc]} {
+ set deleteproc [dict get $info deleteproc]
+ } else {
+ set deleteproc NULL
+ }
+ if {$deleteproc ni { {} NULL }} {
+ ::practcl::cputs result " .deleteProc = $deleteproc,"
+ } else {
+ ::practcl::cputs result " .deleteProc = NULL,"
+ }
+ if {[dict exists $info cloneproc]} {
+ set cloneproc [dict get $info cloneproc]
+ } else {
+ set cloneproc NULL
+ }
+ if {$cloneproc ni { {} NULL }} {
+ ::practcl::cputs result " .cloneProc = $cloneproc\n\}\;"
+ } else {
+ ::practcl::cputs result " .cloneProc = NULL\n\}\;"
+ }
+ dict set methods $name methodtype $methodtype
+ }
+ }
+ foreach obj [my link list dynamic] {
+ # Exclude products that will generate their own C files
+ if {[$obj define get output_c] ne {}} continue
+ ::practcl::cputs result [$obj generate-constant]
+ }
+ return $result
+ }
+
+ ###
+ # Generate code that provides subroutines called by
+ # Tcl API methods
+ ###
+ method generate-cfunct {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code cfunct
+ set result {}
+ if {[info exists code(funct)]} {
+ ::practcl::cputs result $code(funct)
+ }
+ if {[info exists cfunct]} {
+ foreach {funcname info} $cfunct {
+ ::practcl::cputs result "/* $funcname */"
+ ::practcl::cputs result "\n[dict get $info header]\{[dict get $info body]\}"
+ }
+ }
+ foreach obj [my link list dynamic] {
+ # Exclude products that will generate their own C files
+ if {[$obj define get output_c] ne {}} {
+ continue
+ }
+ ::practcl::cputs result [$obj generate-cfunct]
+ }
+ return $result
+ }
+
+ ###
+ # Generate code that provides implements Tcl API
+ # calls
+ ###
+ method generate-cmethod {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ my variable code methods tclprocs
+ set result {}
+ if {[info exists code(method)]} {
+ ::practcl::cputs result $code(method)
+ }
+
+ if {[info exists tclprocs]} {
+ foreach {name info} $tclprocs {
+ if {![dict exists $info body]} continue
+ set callproc [dict get $info callproc]
+ set header [dict get $info header]
+ set body [dict get $info body]
+ ::practcl::cputs result "/* Tcl Proc $name */"
+ ::practcl::cputs result "${header} \{${body}\}"
+ }
+ }
+
+
+ if {[info exists methods]} {
+ set thisclass [my define get cclass]
+ foreach {name info} $methods {
+ if {![dict exists $info body]} continue
+ set callproc [dict get $info callproc]
+ set header [dict get $info header]
+ set body [dict get $info body]
+ ::practcl::cputs result "/* OO Method $thisclass $name */"
+ ::practcl::cputs result "${header} \{${body}\}"
+ }
+ # Build the OO_Init function
+ ::practcl::cputs result "/* Loader for $thisclass */"
+ ::practcl::cputs result "static int ${thisclass}_OO_Init(Tcl_Interp *interp) \{"
+ ::practcl::cputs result [string map [list @CCLASS@ $thisclass @TCLCLASS@ [my define get class]] {
+ /*
+ ** Build the "@TCLCLASS@" class
+ */
+ Tcl_Obj* nameObj; /* Name of a class or method being looked up */
+ Tcl_Object curClassObject; /* Tcl_Object representing the current class */
+ Tcl_Class curClass; /* Tcl_Class representing the current class */
+
+ /*
+ * Find the "@TCLCLASS@" class, and attach an 'init' method to it.
+ */
+
+ nameObj = Tcl_NewStringObj("@TCLCLASS@", -1);
+ Tcl_IncrRefCount(nameObj);
+ if ((curClassObject = Tcl_GetObjectFromObj(interp, nameObj)) == NULL) {
+ Tcl_DecrRefCount(nameObj);
+ return TCL_ERROR;
+ }
+ Tcl_DecrRefCount(nameObj);
+ curClass = Tcl_GetObjectAsClass(curClassObject);
+}]
+ if {[dict exists $methods constructor]} {
+ set mtype [dict get $methods constructor methodtype]
+ ::practcl::cputs result [string map [list @MTYPE@ $mtype] {
+ /* Attach the constructor to the class */
+ Tcl_ClassSetConstructor(interp, curClass, Tcl_NewMethod(interp, curClass, NULL, 1, &@MTYPE@, NULL));
+ }]
+ }
+ foreach {name info} $methods {
+ dict with info {}
+ if {$name in {constructor destructor}} continue
+ ::practcl::cputs result [string map [list @NAME@ $name @MTYPE@ $methodtype] {
+ nameObj=Tcl_NewStringObj("@NAME@",-1);
+ Tcl_NewMethod(interp, curClass, nameObj, 1, &@MTYPE@, (ClientData) NULL);
+ Tcl_DecrRefCount(nameObj);
+}]
+ if {[dict exists $info aliases]} {
+ foreach alias [dict get $info aliases] {
+ if {[dict exists $methods $alias]} continue
+ ::practcl::cputs result [string map [list @NAME@ $alias @MTYPE@ $methodtype] {
+ nameObj=Tcl_NewStringObj("@NAME@",-1);
+ Tcl_NewMethod(interp, curClass, nameObj, 1, &@MTYPE@, (ClientData) NULL);
+ Tcl_DecrRefCount(nameObj);
+}]
+ }
+ }
+ }
+ ::practcl::cputs result " return TCL_OK\;\n\}\n"
+ }
+ foreach obj [my link list dynamic] {
+ # Exclude products that will generate their own C files
+ if {[$obj define get output_c] ne {}} continue
+ ::practcl::cputs result [$obj generate-cmethod]
+ }
+ return $result
+ }
+
+ method generate-cinit-external {} {
+ if {[my define get initfunc] eq {}} {
+ return "/* [my define get filename] declared not initfunc */"
+ }
+ return " if([my define get initfunc](interp)) return TCL_ERROR\;"
+ }
+
+ ###
+ # Generate code that runs when the package/module is
+ # initialized into the interpreter
+ ###
+ method generate-cinit {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set result {}
+ my variable code methods tclprocs
+ if {[info exists code(nspace)]} {
+ ::practcl::cputs result " \{\n Tcl_Namespace *modPtr;"
+ foreach nspace $code(nspace) {
+ ::practcl::cputs result [string map [list @NSPACE@ $nspace] {
+ modPtr=Tcl_FindNamespace(interp,"@NSPACE@",NULL,TCL_NAMESPACE_ONLY);
+ if(!modPtr) {
+ modPtr = Tcl_CreateNamespace(interp, "@NSPACE@", NULL, NULL);
+ }
+}]
+ }
+ ::practcl::cputs result " \}"
+ }
+ if {[info exists code(tclinit)]} {
+ ::practcl::cputs result $code(tclinit)
+ }
+ if {[info exists code(cinit)]} {
+ ::practcl::cputs result $code(cinit)
+ }
+ if {[info exists code(initfuncts)]} {
+ foreach func $code(initfuncts) {
+ ::practcl::cputs result " if (${func}(interp) != TCL_OK) return TCL_ERROR\;"
+ }
+ }
+ if {[info exists tclprocs]} {
+ foreach {name info} $tclprocs {
+ set map [list @NAME@ $name @CALLPROC@ [dict get $info callproc]]
+ ::practcl::cputs result [string map $map { Tcl_CreateObjCommand(interp,"@NAME@",(Tcl_ObjCmdProc *)@CALLPROC@,NULL,NULL);}]
+ if {[dict exists $info aliases]} {
+ foreach alias [dict get $info aliases] {
+ set map [list @NAME@ $alias @CALLPROC@ [dict get $info callproc]]
+ ::practcl::cputs result [string map $map { Tcl_CreateObjCommand(interp,"@NAME@",(Tcl_ObjCmdProc *)@CALLPROC@,NULL,NULL);}]
+ }
+ }
+ }
+ }
+
+ if {[info exists code(nspace)]} {
+ ::practcl::cputs result " \{\n Tcl_Namespace *modPtr;"
+ foreach nspace $code(nspace) {
+ ::practcl::cputs result [string map [list @NSPACE@ $nspace] {
+ modPtr=Tcl_FindNamespace(interp,"@NSPACE@",NULL,TCL_NAMESPACE_ONLY);
+ Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX);
+ Tcl_Export(interp, modPtr, "[a-z]*", 1);
+}]
+ }
+ ::practcl::cputs result " \}"
+ }
+ set result [::practcl::_tagblock $result c [my define get filename]]
+ foreach obj [my link list product] {
+ # Exclude products that will generate their own C files
+ if {[$obj define get output_c] ne {}} {
+ ::practcl::cputs result [$obj generate-cinit-external]
+ } else {
+ ::practcl::cputs result [$obj generate-cinit]
+ }
+ }
+ return $result
+ }
+
+ method c_header body {
+ my variable code
+ ::practcl::cputs code(header) $body
+ }
+
+ method c_code body {
+ my variable code
+ ::practcl::cputs code(funct) $body
+ }
+ method c_function {header body {info {}}} {
+ set header [string map "\t \ \n \ \ \ \ " $header]
+ my variable code cfunct
+ foreach regexp {
+ {(.*) ([a-zA-Z_][a-zA-Z0-9_]*) *\((.*)\)}
+ {(.*) (\x2a[a-zA-Z_][a-zA-Z0-9_]*) *\((.*)\)}
+ } {
+ if {[regexp $regexp $header all keywords funcname arglist]} {
+ dict set cfunct $funcname header $header
+ dict set cfunct $funcname body $body
+ dict set cfunct $funcname keywords $keywords
+ dict set cfunct $funcname arglist $arglist
+ dict set cfunct $funcname inline [expr {"inline" ni $keywords}]
+ dict set cfunct $funcname public [expr {"static" ni $keywords}]
+ dict set cfunct $funcname export [expr {"STUB_EXPORT" in $keywords}]
+ foreach {f v} $info {
+ dict set cfunct $f $v
+ }
+ return
+ }
+ }
+ foreach {f v} $info {
+ dict set cfunct $f $v
+ }
+ ::practcl::cputs code(header) "$header\;"
+ # Could not parse that block as a function
+ # append it verbatim to our c_implementation
+ ::practcl::cputs code(funct) "$header [list $body]"
+ }
+
+
+ method cmethod {name body {arginfo {}}} {
+ my variable methods code
+ foreach {f v} $arginfo {
+ dict set methods $name $f $v
+ }
+ dict set methods $name body "Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
+$body"
+ }
+
+ method c_tclproc_nspace nspace {
+ my variable code
+ if {![info exists code(nspace)]} {
+ set code(nspace) {}
+ }
+ if {$nspace ni $code(nspace)} {
+ lappend code(nspace) $nspace
+ }
+ }
+
+ method c_tclproc_raw {name body {arginfo {}}} {
+ my variable tclprocs code
+
+ foreach {f v} $arginfo {
+ dict set tclprocs $name $f $v
+ }
+ dict set tclprocs $name body $body
+ }
+
+ method go {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ next
+ my variable methods code cstruct tclprocs
+ if {[info exists methods]} {
+ ::practcl::debug [self] methods [my define get cclass]
+ set thisclass [my define get cclass]
+ foreach {name info} $methods {
+ # Provide a callproc
+ if {![dict exists $info callproc]} {
+ set callproc [string map {____ _ ___ _ __ _} [string map {{ } _ : _} OOMethod_${thisclass}_${name}]]
+ dict set methods $name callproc $callproc
+ } else {
+ set callproc [dict get $info callproc]
+ }
+ if {[dict exists $info body] && ![dict exists $info header]} {
+ dict set methods $name header "static int ${callproc}(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext ,int objc ,Tcl_Obj *const *objv)"
+ }
+ if {![dict exists $info methodtype]} {
+ set methodtype [string map {{ } _ : _} OOMethodType_${thisclass}_${name}]
+ dict set methods $name methodtype $methodtype
+ }
+ }
+ if {![info exists code(initfuncts)] || "${thisclass}_OO_Init" ni $code(initfuncts)} {
+ lappend code(initfuncts) "${thisclass}_OO_Init"
+ }
+ }
+ set thisnspace [my define get nspace]
+
+ if {[info exists tclprocs]} {
+ ::practcl::debug [self] tclprocs [dict keys $tclprocs]
+ foreach {name info} $tclprocs {
+ if {![dict exists $info callproc]} {
+ set callproc [string map {____ _ ___ _ __ _} [string map {{ } _ : _} TclCmd_${thisnspace}_${name}]]
+ dict set tclprocs $name callproc $callproc
+ } else {
+ set callproc [dict get $info callproc]
+ }
+ if {[dict exists $info body] && ![dict exists $info header]} {
+ dict set tclprocs $name header "static int ${callproc}(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv\[\])"
+ }
+ }
+ }
+ ::practcl::debug [list /[self] [self method] [self class]]
+ }
+
+ # Once an object marks itself as some
+ # flavor of dynamic, stop trying to morph
+ # it into something else
+ method select {} {}
+
+
+ method tcltype {name argdat} {
+ my variable tcltype
+ foreach {f v} $argdat {
+ dict set tcltype $name $f $v
+ }
+ if {![dict exists tcltype $name cname]} {
+ dict set tcltype $name cname [string tolower $name]_tclobjtype
+ }
+ lappend map @NAME@ $name
+ set info [dict get $tcltype $name]
+ foreach {f v} $info {
+ lappend map @[string toupper $f]@ $v
+ }
+ foreach {func fpat template} {
+ freeproc {@Name@Obj_freeIntRepProc} {void @FNAME@(Tcl_Obj *objPtr)}
+ dupproc {@Name@Obj_dupIntRepProc} {void @FNAME@(Tcl_Obj *srcPtr,Tcl_Obj *dupPtr)}
+ updatestringproc {@Name@Obj_updateStringRepProc} {void @FNAME@(Tcl_Obj *objPtr)}
+ setfromanyproc {@Name@Obj_setFromAnyProc} {int @FNAME@(Tcl_Interp *interp,Tcl_Obj *objPtr)}
+ } {
+ if {![dict exists $info $func]} {
+ error "$name does not define $func"
+ }
+ set body [dict get $info $func]
+ # We were given a function name to call
+ if {[llength $body] eq 1} continue
+ set fname [string map [list @Name@ [string totitle $name]] $fpat]
+ my c_function [string map [list @FNAME@ $fname] $template] [string map $map $body]
+ dict set tcltype $name $func $fname
+ }
+ }
+}
+
+::oo::class create ::practcl::cheader {
+ superclass ::practcl::product
+
+ method compile-products {} {}
+ method generate-cinit {} {}
+}
+
+::oo::class create ::practcl::csource {
+ superclass ::practcl::product
+}
+
+::oo::class create ::practcl::clibrary {
+ superclass ::practcl::product
+
+ method linker-products {configdict} {
+ return [my define get filename]
+ }
+
+}
+
+###
+# In the end, all C code must be loaded into a module
+# This will either be a dynamically loaded library implementing
+# a tcl extension, or a compiled in segment of a custom shell/app
+###
+::oo::class create ::practcl::module {
+ superclass ::practcl::dynamic
+
+ method child which {
+ switch $which {
+ organs {
+ return [list project [my define get project] module [self]]
+ }
+ }
+ }
+
+ method initialize {} {
+ set filename [my define get filename]
+ if {$filename eq {}} {
+ return
+ }
+ if {[my define get name] eq {}} {
+ my define set name [file tail [file dirname $filename]]
+ }
+ if {[my define get localpath] eq {}} {
+ my define set localpath [my <project> define get name]_[my define get name]
+ }
+ ::practcl::debug [self] SOURCE $filename
+ my source $filename
+ }
+
+ method implement path {
+ my go
+ my Collate_Source $path
+ foreach item [my link list dynamic] {
+ if {[catch {$item implement $path} err]} {
+ puts "Skipped $item: $err"
+ }
+ }
+ foreach item [my link list module] {
+ if {[catch {$item implement $path} err]} {
+ puts "Skipped $item: $err"
+ }
+ }
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set filename [my define get output_c]
+ if {$filename eq {}} {
+ ::practcl::debug [list /[self] [self method] [self class]]
+ return
+ }
+ set cout [open [file join $path [file rootname $filename].c] w]
+ puts $cout [subst {/*
+** This file is generated by the [info script] script
+** any changes will be overwritten the next time it is run
+*/}]
+ puts $cout [my generate-c]
+ puts $cout [my generate-loader]
+ close $cout
+ ::practcl::debug [list /[self] [self method] [self class]]
+ }
+
+ method linktype {} {
+ return {subordinate product dynamic module}
+ }
+}
+
+::oo::class create ::practcl::autoconf {
+
+ ###
+ # find or fake a key/value list describing this project
+ ###
+ method config.sh {} {
+ my variable conf_result
+ if {[info exists conf_result]} {
+ return $conf_result
+ }
+ set result {}
+ set name [my define get name]
+ set PWD $::CWD
+ set builddir [my define get builddir]
+ my unpack
+ set srcdir [my define get srcdir]
+ if {![file exists $builddir]} {
+ my Configure
+ }
+ set filename [file join $builddir config.tcl]
+ # Project uses the practcl template. Use the leavings from autoconf
+ if {[file exists $filename]} {
+ set dat [::practcl::config.tcl $builddir]
+ foreach {item value} [::practcl::sort_dict $dat] {
+ dict set result $item $value
+ }
+ set conf_result $result
+ return $result
+ }
+ set filename [file join $builddir ${name}Config.sh]
+ if {[file exists $filename]} {
+ set l [expr {[string length $name]+1}]
+ foreach {field dat} [::practcl::read_Config.sh $filename] {
+ set field [string tolower $field]
+ if {[string match ${name}_* $field]} {
+ set field [string range $field $l end]
+ }
+ dict set result $field $dat
+ }
+ set conf_result $result
+ return $result
+ }
+ ###
+ # Oh man... we have to guess
+ ###
+ set filename [file join $builddir Makefile]
+ if {![file exists $filename]} {
+ error "Could not locate any configuration data in $srcdir"
+ }
+ foreach {field dat} [::practcl::read_Makefile $filename] {
+ dict set result $field $dat
+ }
+ set conf_result $result
+ cd $PWD
+ return $result
+ }
+}
+
+
+::oo::class create ::practcl::project {
+ superclass ::practcl::module ::practcl::autoconf
+
+ constructor args {
+ my variable define
+ if {[llength $args] == 1} {
+ set rawcontents [lindex $args 0]
+ } else {
+ set rawcontents $args
+ }
+ if {[catch {uplevel 1 [list subst $rawcontents]} contents]} {
+ set contents $rawcontents
+ }
+ ###
+ # The first instance of ::practcl::project (or its descendents)
+ # registers itself as the ::practcl::MAIN. If a project other
+ # than ::practcl::LOCAL is created, odds are that was the one
+ # the developer intended to be the main project
+ ###
+ if {$::practcl::MAIN eq "::practcl::LOCAL"} {
+ set ::practcl::MAIN [self]
+ }
+ # DEFS fields need to be passed unchanged and unsubstituted
+ # as we need to preserve their escape characters
+ foreach field {TCL_DEFS DEFS TK_DEFS} {
+ if {[dict exists $rawcontents $field]} {
+ dict set contents $field [dict get $rawcontents $field]
+ }
+ }
+ array set define $contents
+ my select
+ my initialize
+ }
+
+ method add_project {pkg info {oodefine {}}} {
+ set os [my define get TEACUP_OS]
+ if {$os eq {}} {
+ set os [::practcl::os]
+ my define set os $os
+ }
+ set fossilinfo [list download [my define get download] tag trunk sandbox [my define get sandbox]]
+ if {[dict exists $info os] && ($os ni [dict get $info os])} return
+ # Select which tag to use here.
+ # For production builds: tag-release
+ set profile [my define get profile release]:
+ if {[dict exists $info profile $profile]} {
+ dict set info tag [dict get $info profile $profile]
+ }
+ if {[my define get USEMSVC 0]} {
+ dict set info USEMSVC 1
+ }
+ set obj [namespace current]::PROJECT.$pkg
+ if {[info command $obj] eq {}} {
+ set obj [::practcl::subproject create $obj [self] [dict merge $fossilinfo [list name $pkg pkg_name $pkg static 0 class subproject.binary] $info]]
+ }
+ my link object $obj
+ oo::objdefine $obj $oodefine
+ $obj define set masterpath $::CWD
+ $obj go
+ return $obj
+ }
+
+ method add_tool {pkg info {oodefine {}}} {
+ set info [dict merge [::practcl::local_os] $info]
+ set os [dict get $info TEACUP_OS]
+ set fossilinfo [list download [my define get download] tag trunk sandbox [my define get sandbox]]
+ if {[dict exists $info os] && ($os ni [dict get $info os])} return
+ # Select which tag to use here.
+ # For production builds: tag-release
+ set profile [my define get profile release]:
+ if {[dict exists $info profile $profile]} {
+ dict set info tag [dict get $info profile $profile]
+ }
+ set obj [namespace current]::TOOL.$pkg
+ if {[info command $obj] eq {}} {
+ set obj [::practcl::tool create $obj [self] [dict merge $fossilinfo [list name $pkg pkg_name $pkg static 0] $info]]
+ }
+ my link object $obj
+ oo::objdefine $obj $oodefine
+ $obj define set masterpath $::CWD
+ $obj go
+ return $obj
+ }
+
+ method child which {
+ switch $which {
+ organs {
+ # A library can be a project, it can be a module. Any
+ # subordinate modules will indicate their existance
+ return [list project [self] module [self]]
+ }
+ }
+ }
+
+ method linktype {} {
+ return project
+ }
+
+ # Exercise the methods of a sub-object
+ method project {pkg args} {
+ set obj [namespace current]::PROJECT.$pkg
+ if {[llength $args]==0} {
+ return $obj
+ }
+ ${obj} {*}$args
+ }
+
+ method select {} {
+ next
+ ###
+ # Select the toolset to use for this project
+ ###
+ my variable define
+ set class {}
+ if {[info exists define(toolset)]} {
+ if {[info command $define(toolset)] ne {}} {
+ set class $define(toolset)
+ } elseif {[info command ::practcl::$define(toolset)] ne {}} {
+ set class ::practcl::$define(toolset)
+ } else {
+ switch $define(toolset) {
+ default {
+ set class ::practcl::build.gcc
+ }
+ }
+ }
+ } else {
+ if {[info exists ::env(VisualStudioVersion)]} {
+ set class ::practcl::build.msvc
+ } else {
+ set class ::practcl::build.gcc
+ }
+ }
+ ::oo::objdefine [self] mixin $class
+ }
+
+ method tool {pkg args} {
+ set obj [namespace current]::TOOL.$pkg
+ if {[llength $args]==0} {
+ return $obj
+ }
+ ${obj} {*}$args
+ }
+}
+
+::oo::class create ::practcl::library {
+ superclass ::practcl::project
+
+ method compile-products {} {
+ set result {}
+ foreach item [my link list subordinate] {
+ lappend result {*}[$item compile-products]
+ }
+ set filename [my define get output_c]
+ if {$filename ne {}} {
+ set ofile [file rootname [file tail $filename]]_main.o
+ lappend result $ofile [list cfile $filename extra [my define get extra] external [string is true -strict [my define get external]]]
+ }
+ return $result
+ }
+
+ method generate-tcl-loader {} {
+ set result {}
+ set PKGINIT [my define get pkginit]
+ set PKG_NAME [my define get name [my define get pkg_name]]
+ set PKG_VERSION [my define get pkg_vers [my define get version]]
+ if {[string is true [my define get SHARED_BUILD 0]]} {
+ set LIBFILE [my define get libfile]
+ ::practcl::cputs result [string map \
+ [list @LIBFILE@ $LIBFILE @PKGINIT@ $PKGINIT @PKG_NAME@ $PKG_NAME @PKG_VERSION@ $PKG_VERSION] {
+# Shared Library Style
+load [file join [file dirname [file join [pwd] [info script]]] @LIBFILE@] @PKGINIT@
+package provide @PKG_NAME@ @PKG_VERSION@
+}]
+ } else {
+ ::practcl::cputs result [string map \
+ [list @PKGINIT@ $PKGINIT @PKG_NAME@ $PKG_NAME @PKG_VERSION@ $PKG_VERSION] {
+# Tclkit Style
+load {} @PKGINIT@
+package provide @PKG_NAME@ @PKG_VERSION@
+}]
+ }
+ return $result
+ }
+
+ method go {} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set name [my define getnull name]
+ if {$name eq {}} {
+ set name generic
+ my define name generic
+ }
+ if {[my define get tk] eq {@TEA_TK_EXTENSION@}} {
+ my define set tk 0
+ }
+ set output_c [my define getnull output_c]
+ if {$output_c eq {}} {
+ set output_c [file rootname $name].c
+ my define set output_c $output_c
+ }
+ set output_h [my define getnull output_h]
+ if {$output_h eq {}} {
+ set output_h [file rootname $output_c].h
+ my define set output_h $output_h
+ }
+ set output_tcl [my define getnull output_tcl]
+ #if {$output_tcl eq {}} {
+ # set output_tcl [file rootname $output_c].tcl
+ # my define set output_tcl $output_tcl
+ #}
+ #set output_mk [my define getnull output_mk]
+ #if {$output_mk eq {}} {
+ # set output_mk [file rootname $output_c].mk
+ # my define set output_mk $output_mk
+ #}
+ set initfunc [my define getnull initfunc]
+ if {$initfunc eq {}} {
+ set initfunc [string totitle $name]_Init
+ my define set initfunc $initfunc
+ }
+ set output_decls [my define getnull output_decls]
+ if {$output_decls eq {}} {
+ set output_decls [file rootname $output_c].decls
+ my define set output_decls $output_decls
+ }
+ my variable links
+ foreach {linktype objs} [array get links] {
+ foreach obj $objs {
+ $obj go
+ }
+ }
+ ::practcl::debug [list /[self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ }
+
+ method implement path {
+ my go
+ my Collate_Source $path
+ foreach item [my link list dynamic] {
+ if {[catch {$item implement $path} err]} {
+ puts "Skipped $item: $err"
+ }
+ }
+ foreach item [my link list module] {
+ if {[catch {$item implement $path} err]} {
+ puts "Skipped $item: $err"
+ }
+ }
+ set cout [open [file join $path [my define get output_c]] w]
+ puts $cout [subst {/*
+** This file is generated by the [info script] script
+** any changes will be overwritten the next time it is run
+*/}]
+ puts $cout [my generate-c]
+ puts $cout [my generate-loader]
+ close $cout
+
+ set macro HAVE_[string toupper [file rootname [my define get output_h]]]_H
+ set hout [open [file join $path [my define get output_h]] w]
+ puts $hout [subst {/*
+** This file is generated by the [info script] script
+** any changes will be overwritten the next time it is run
+*/}]
+ puts $hout "#ifndef ${macro}"
+ puts $hout "#define ${macro}"
+ puts $hout [my generate-h]
+ puts $hout "#endif"
+ close $hout
+
+ set output_tcl [my define get output_tcl]
+ if {$output_tcl ne {}} {
+ set tclout [open [file join $path [my define get output_tcl]] w]
+ puts $tclout "###
+# This file is generated by the [info script] script
+# any changes will be overwritten the next time it is run
+###"
+ puts $tclout [my generate-tcl-pre]
+ puts $tclout [my generate-tcl-loader]
+ puts $tclout [my generate-tcl-post]
+ close $tclout
+ }
+ }
+
+ method generate-decls {pkgname path} {
+ ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
+ set outfile [file join $path/$pkgname.decls]
+
+ ###
+ # Build the decls file
+ ###
+ set fout [open $outfile w]
+ puts $fout [subst {###
+ # $outfile
+ #
+ # This file was generated by [info script]
+ ###
+
+ library $pkgname
+ interface $pkgname
+ }]
+
+ ###
+ # Generate list of functions
+ ###
+ set stubfuncts [my generate-stub-function]
+ set thisline {}
+ set functcount 0
+ foreach {func header} $stubfuncts {
+ puts $fout [list declare [incr functcount] $header]
+ }
+ puts $fout [list export "int [my define get initfunc](Tcl_Inter *interp)"]
+ puts $fout [list export "char *[string totitle [my define get name]]_InitStubs(Tcl_Inter *interp, char *version, int exact)"]
+
+ close $fout
+
+ ###
+ # Build [package]Decls.h
+ ###
+ set hout [open [file join $path ${pkgname}Decls.h] w]
+
+ close $hout
+
+ set cout [open [file join $path ${pkgname}StubInit.c] w]
+puts $cout [string map [list %pkgname% $pkgname %PkgName% [string totitle $pkgname]] {
+#ifndef USE_TCL_STUBS
+#define USE_TCL_STUBS
+#endif
+#undef USE_TCL_STUB_PROCS
+
+#include "tcl.h"
+#include "%pkgname%.h"
+
+ /*
+ ** Ensure that Tdom_InitStubs is built as an exported symbol. The other stub
+ ** functions should be built as non-exported symbols.
+ */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+
+%PkgName%Stubs *%pkgname%StubsPtr;
+
+ /*
+ **----------------------------------------------------------------------
+ **
+ ** %PkgName%_InitStubs --
+ **
+ ** Checks that the correct version of %PkgName% is loaded and that it
+ ** supports stubs. It then initialises the stub table pointers.
+ **
+ ** Results:
+ ** The actual version of %PkgName% that satisfies the request, or
+ ** NULL to indicate that an error occurred.
+ **
+ ** Side effects:
+ ** Sets the stub table pointers.
+ **
+ **----------------------------------------------------------------------
+ */
+
+char *
+%PkgName%_InitStubs (Tcl_Interp *interp, char *version, int exact)
+{
+ char *actualVersion;
+ actualVersion = Tcl_PkgRequireEx(interp, "%pkgname%", version, exact,(ClientData *) &%pkgname%StubsPtr);
+ if (!actualVersion) {
+ return NULL;
+ }
+ if (!%pkgname%StubsPtr) {
+ Tcl_SetResult(interp,"This implementation of %PkgName% does not support stubs",TCL_STATIC);
+ return NULL;
+ }
+ return actualVersion;
+}
+}]
+ close $cout
+ }
+
+ # Backward compadible call
+ method generate-make path {
+ my build-Makefile $path [self]
+ }
+
+ method install-headers {} {
+ set result {}
+ return $result
+ }
+
+ method linktype {} {
+ return library
+ }
+
+ # Create a "package ifneeded"
+ # Args are a list of aliases for which this package will answer to
+ method package-ifneeded {args} {
+ set result {}
+ set name [my define get pkg_name [my define get name]]
+ set version [my define get pkg_vers [my define get version]]
+ if {$version eq {}} {
+ set version 0.1a
+ }
+ set output_tcl [my define get output_tcl]
+ if {$output_tcl ne {}} {
+ set script "\[list source \[file join \$dir $output_tcl\]\]"
+ } elseif {[string is true -strict [my define get SHARED_BUILD]]} {
+ set script "\[list load \[file join \$dir [my define get libfile]\] $name\]"
+ } else {
+ # Provide a null passthrough
+ set script "\[list package provide $name $version\]"
+ }
+ set result "package ifneeded [list $name] [list $version] $script"
+ foreach alias $args {
+ set script "package require $name $version \; package provide $alias $version"
+ append result \n\n [list package ifneeded $alias $version $script]
+ }
+ return $result
+ }
+
+
+ method shared_library {} {
+ set name [string tolower [my define get name [my define get pkg_name]]]
+ set NAME [string toupper $name]
+ set version [my define get version [my define get pkg_vers]]
+ set map {}
+ lappend map %LIBRARY_NAME% $name
+ lappend map %LIBRARY_VERSION% $version
+ lappend map %LIBRARY_VERSION_NODOTS% [string map {. {}} $version]
+ lappend map %LIBRARY_PREFIX% [my define getnull libprefix]
+ set outfile [string map $map [my define get PRACTCL_NAME_LIBRARY]][my define get SHLIB_SUFFIX]
+ return $outfile
+ }
+}
+
+::oo::class create ::practcl::tclkit {
+ superclass ::practcl::library
+
+ method Collate_Source CWD {
+ set name [my define get name]
+ # Assume a static shell
+ if {[my define exists SHARED_BUILD]} {
+ my define exists SHARED_BUILD 0
+ }
+ if {![my define exists TCL_LOCAL_APPINIT]} {
+ my define set TCL_LOCAL_APPINIT Tclkit_AppInit
+ }
+ if {![my define exists TCL_LOCAL_MAIN_HOOK]} {
+ my define set TCL_LOCAL_MAIN_HOOK Tclkit_MainHook
+ }
+ set PROJECT [self]
+ set os [$PROJECT define get TEACUP_OS]
+ if {[my define get SHARED_BUILD]} {
+ puts [list BUILDING TCLSH FOR OS $os]
+ } else {
+ puts [list BUILDING KIT FOR OS $os]
+ }
+ set TCLOBJ [$PROJECT project TCLCORE]
+ set TCLSRCDIR [$TCLOBJ define get srcdir]
+ set PKG_OBJS {}
+ foreach item [$PROJECT link list core.library] {
+ if {[string is true [$item define get static]]} {
+ lappend PKG_OBJS $item
+ }
+ }
+ foreach item [$PROJECT link list package] {
+ if {[string is true [$item define get static]]} {
+ lappend PKG_OBJS $item
+ }
+ }
+ # Arrange to build an main.c that utilizes TCL_LOCAL_APPINIT and TCL_LOCAL_MAIN_HOOK
+ if {$os eq "windows"} {
+ set PLATFORM_SRC_DIR win
+ if {[my define get SHARED_BUILD]} {
+ my add class csource filename [file join $TCLSRCDIR win tclWinReg.c] initfunc Registry_Init pkg_name registry pkg_vers 1.3.1 autoload 1
+ my add class csource filename [file join $TCLSRCDIR win tclWinDde.c] initfunc Dde_Init pkg_name dde pkg_vers 1.4.0 autoload 1
+ }
+ my add class csource ofile [my define get name]_appinit.o filename [file join $TCLSRCDIR win tclAppInit.c] extra [list -DTCL_LOCAL_MAIN_HOOK=[my define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook] -DTCL_LOCAL_APPINIT=[my define get TCL_LOCAL_APPINIT Tclkit_AppInit]]
+ } else {
+ set PLATFORM_SRC_DIR unix
+ my add class csource ofile [my define get name]_appinit.o filename [file join $TCLSRCDIR unix tclAppInit.c] extra [list -DTCL_LOCAL_MAIN_HOOK=[my define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook] -DTCL_LOCAL_APPINIT=[my define get TCL_LOCAL_APPINIT Tclkit_AppInit]]
+ }
+
+ if {[my define get SHARED_BUILD]} {
+ ###
+ # Add local static Zlib implementation
+ ###
+ set cdir [file join $TCLSRCDIR compat zlib]
+ foreach file {
+ adler32.c compress.c crc32.c
+ deflate.c infback.c inffast.c
+ inflate.c inftrees.c trees.c
+ uncompr.c zutil.c
+ } {
+ my add [file join $cdir $file]
+ }
+ }
+ ###
+ # Pre 8.7, Tcl doesn't include a Zipfs implementation
+ # in the core. Grab the one from odielib
+ ###
+ set zipfs [file join $TCLSRCDIR generic tclZipfs.c]
+ if {![$PROJECT define exists ZIPFS_VOLUME]} {
+ $PROJECT define set ZIPFS_VOLUME "//zipfs:/"
+ }
+ $PROJECT code header "#define ZIPFS_VOLUME \"[$PROJECT define get ZIPFS_VOLUME]\""
+ if {[file exists $zipfs]} {
+ $TCLOBJ define set tip_430 1
+ my define set tip_430 1
+ } else {
+ # The Tclconfig project maintains a mirror of the version
+ # released with the Tcl core
+ my define set tip_430 0
+ ::practcl::LOCAL tool odie load
+ set COMPATSRCROOT [::practcl::LOCAL tool odie define get srcdir]
+ set cdir [file join $COMPATSRCROOT compat zipfs]
+ my define add include_dir $cdir
+ set zipfs [file join $cdir tclZipfs.c]
+ my add class csource filename $zipfs initfunc Tclzipfs_Init pkg_name zipfs pkg_vers 1.1 autoload 1 extra "-DZIPFS_VOLUME=\"[$PROJECT define get ZIPFS_VOLUME]\""
+ }
+
+ my define add include_dir [file join $TCLSRCDIR generic]
+ my define add include_dir [file join $TCLSRCDIR $PLATFORM_SRC_DIR]
+ # This file will implement TCL_LOCAL_APPINIT and TCL_LOCAL_MAIN_HOOK
+ my build-tclkit_main $PROJECT $PKG_OBJS
+ }
+
+ ## Wrap an executable
+ #
+ method wrap {PWD exename vfspath args} {
+ cd $PWD
+ if {![file exists $vfspath]} {
+ file mkdir $vfspath
+ }
+ foreach item [my link list core.library] {
+ set name [$item define get name]
+ set libsrcdir [$item define get srcdir]
+ if {[file exists [file join $libsrcdir library]]} {
+ ::practcl::copyDir [file join $libsrcdir library] [file join $vfspath boot $name]
+ }
+ }
+ # Assume the user will populate the VFS path
+ #if {[my define get installdir] ne {}} {
+ # ::practcl::copyDir [file join [my define get installdir] [string trimleft [my define get prefix] /] lib] [file join $vfspath lib]
+ #}
+ foreach arg $args {
+ ::practcl::copyDir $arg $vfspath
+ }
+
+ set fout [open [file join $vfspath packages.tcl] w]
+ puts $fout {
+ set ::PKGIDXFILE [info script]
+ set dir [file dirname $::PKGIDXFILE]
+ }
+ #set BASEVFS [my define get BASEVFS]
+ set EXEEXT [my define get EXEEXT]
+
+ set tclkit_bare [my define get tclkit_bare]
+
+ set buffer [::practcl::pkgindex_path $vfspath]
+ puts $fout $buffer
+ puts $fout {
+ # Advertise statically linked packages
+ foreach {pkg script} [array get ::kitpkg] {
+ eval $script
+ }
+ }
+ close $fout
+ ::practcl::mkzip ${exename}${EXEEXT} $tclkit_bare $vfspath
+ if { [my define get TEACUP_OS] ne "windows" } {
+ file attributes ${exename}${EXEEXT} -permissions a+x
+ }
+ }
+}
+
+###
+# Standalone class to manage code distribution
+# This class is intended to be mixed into another class
+# (Thus the lack of ancestors)
+###
+oo::class create ::practcl::distribution {
+
+ method DistroMixIn {} {
+ my define set scm none
+ }
+
+ method Sandbox {} {
+ if {[my define exists sandbox]} {
+ return [my define get sandbox]
+ }
+ if {[my organ project] ni {::noop {}}} {
+ set sandbox [my <project> define get sandbox]
+ if {$sandbox ne {}} {
+ my define set sandbox $sandbox
+ return $sandbox
+ }
+ }
+ set sandbox [file normalize [file join $::CWD .. $pkg]]
+ my define set sandbox $sandbox
+ return $sandbox
+ }
+
+ method SrcDir {} {
+ set pkg [my define get name]
+ if {[my define exists srcdir]} {
+ return [my define get srcdir]
+ }
+ set sandbox [my Sandbox]
+ set srcdir [file join [my Sandbox] $pkg]
+ my define set srcdir $srcdir
+ return $srcdir
+ }
+
+ method ScmSelect {} {
+ if {[my define exists scm]} {
+ return [my define get scm]
+ }
+ set srcdir [my SrcDir]
+ set classprefix ::practcl::distribution.
+ if {[file exists $srcdir]} {
+ foreach class [::info commands ${classprefix}*] {
+ if {[$class claim_path $srcdir]} {
+ oo::objdefine [self] mixin $class
+ my define set scm [string range $class [string length ::practcl::distribution.] end]
+ }
+ }
+ }
+ foreach class [::info commands ${classprefix}*] {
+ if {[$class claim_object [self]]} {
+ oo::objdefine [self] mixin $class
+ my define set scm [string range $class [string length ::practcl::distribution.] end]
+ }
+ }
+ if {[my define get scm] eq {} && [my define exists file_url]} {
+ set class
+ }
+
+ if {[my define get scm] eq {}} {
+ error "No SCM selected"
+ }
+ return [my define get scm]
+ }
+
+ method ScmTag {} {}
+ method ScmClone {} {}
+ method ScmUnpack {} {}
+ method ScmUpdate {} {}
+
+ method unpack {} {
+ my ScmSelect
+ set srcdir [my SrcDir]
+ if {[file exists $srcdir]} {
+ return
+ }
+ set pkg [my define get name]
+ if {[my define exists download]} {
+ # Utilize a staged download
+ set download [my define get download]
+ if {[file exists [file join $download $pkg.zip]]} {
+ ::practcl::tcllib_require zipfile::decode
+ ::zipfile::decode::unzipfile [file join $download $pkg.zip] $srcdir
+ return
+ }
+ }
+ my ScmUnpack
+ }
+
+ method update {} {
+ my ScmSelect
+ my ScmUpdate
+ }
+}
+
+oo::objdefine ::practcl::distribution {
+ method claim_path path {
+ return false
+ }
+ method claim_object object {
+ return false
+ }
+}
+
+oo::class create ::practcl::distribution.snapshot {
+ superclass ::practcl::distribution
+ method ScmUnpack {} {
+ set srcdir [my SrcDir]
+ if {[file exists [file join $srcdir .download]]} {
+ return 0
+ }
+ set dpath [::practcl::LOCAL define get download]
+ set url [my define get file_url]
+ set fname [file tail $url]
+ set archive [file join $dpath $fname]
+ if {![file exists $archive]} {
+ ::http::wget $url $archive
+ }
+ set CWD [pwd]
+ switch [file extension $fname] {
+ .zip {
+ # Zipfile
+
+ }
+ .tar {
+ ::practcl::tcllib_require tar
+ }
+ .tgz -
+ .gz {
+ # Tarball
+ ::practcl::tcllib_require tcl::transform::zlib
+ ::practcl::tcllib_require tar
+ set fh [::open $archive]
+ fconfigure $fh -encoding binary -translation lf -eofchar {}
+ ::tcl::transform::zlib $fh
+ }
+ }
+ set fosdb [my ScmClone]
+ set tag [my ScmTag]
+ file mkdir $srcdir
+ ::practcl::fossil $srcdir open $fosdb $tag
+ return 1
+ }
+}
+
+oo::objdefine ::practcl::distribution.snapshot {
+ method claim_path path {
+ if {[file exists [file join $path .download]]} {
+ return true
+ }
+ return false
+ }
+ method claim_object object {
+ return false
+ }
+}
+
+
+oo::class create ::practcl::distribution.fossil {
+ superclass ::practcl::distribution
+
+ # Clone the source
+ method ScmClone {} {
+ set srcdir [my SrcDir]
+ if {[file exists [file join $srcdir .fslckout]]} {
+ return
+ }
+ if {[file exists [file join $srcdir _FOSSIL_]]} {
+ return
+ }
+ if {![::info exists ::practcl::fossil_dbs]} {
+ # Get a list of local fossil databases
+ set ::practcl::fossil_dbs [exec fossil all list]
+ }
+ set pkg [my define get name]
+ # Return an already downloaded fossil repo
+ foreach line [split $::practcl::fossil_dbs \n] {
+ set line [string trim $line]
+ if {[file rootname [file tail $line]] eq $pkg} {
+ return $line
+ }
+ }
+ set download [::practcl::LOCAL define get download]
+ set fosdb [file join $download $pkg.fos]
+ if {[file exists $fosdb]} {
+ return $fosdb
+ }
+
+ file mkdir [file join $download fossil]
+ set fosdb [file join $download fossil $pkg.fos]
+ if {[file exists $fosdb]} {
+ return $fosdb
+ }
+
+ set cloned 0
+ # Attempt to clone from a local network mirror
+ if {[::practcl::LOCAL define exists fossil_mirror]} {
+ set localmirror [::practcl::LOCAL define get fossil_mirror]
+ catch {
+ ::practcl::doexec fossil clone $localmirror/$pkg $fosdb
+ set cloned 1
+ }
+ if {$cloned} {
+ return $fosdb
+ }
+ }
+ # Attempt to clone from the canonical source
+ if {[my define get fossil_url] ne {}} {
+ catch {
+ ::practcl::doexec fossil clone [my define get fossil_url] $fosdb
+ set cloned 1
+ }
+ if {$cloned} {
+ return $fosdb
+ }
+ }
+ # Fall back to the fossil mirror on the island of misfit toys
+ ::practcl::doexec fossil clone http://fossil.etoyoc.com/fossil/$pkg $fosdb
+ return $fosdb
+ }
+
+ method ScmTag {} {
+ if {[my define exists scm_tag]} {
+ return [my define get scm_tag]
+ }
+ if {[my define exists tag]} {
+ set tag [my define get tag]
+ } else {
+ set tag trunk
+ }
+ my define set scm_tag $tag
+ return $tag
+ }
+
+ method ScmUnpack {} {
+ set srcdir [my SrcDir]
+ if {[file exists [file join $srcdir .fslckout]]} {
+ return 0
+ }
+ if {[file exists [file join $srcdir _FOSSIL_]]} {
+ return 0
+ }
+ set CWD [pwd]
+ set fosdb [my ScmClone]
+ set tag [my ScmTag]
+ file mkdir $srcdir
+ ::practcl::fossil $srcdir open $fosdb $tag
+ return 1
+ }
+
+ method ScmUpdate {} {
+ if {[my ScmUnpack]} {
+ return
+ }
+ set srcdir [my SrcDir]
+ set tag [my ScmTag]
+ ::practcl::fossil $srcdir update $tag
+ }
+}
+
+oo::objdefine ::practcl::distribution.fossil {
+
+ # Check for markers in the source root
+ method claim_path path {
+ if {[file exists [file join $path .fslckout]]} {
+ return true
+ }
+ if {[file exists [file join $path _FOSSIL_]]} {
+ return true
+ }
+ return false
+ }
+
+ # Check for markers in the metadata
+ method claim_object obj {
+ set path [$obj define get srcdir]
+ if {[my claim_path $path]} {
+ return true
+ }
+ if {[$obj define get fossil_url] ne {}} {
+ return true
+ }
+ return false
+ }
+}
+
+oo::class create ::practcl::distribution.git {
+
+ method ScmTag {} {
+ if {[my define exists scm_tag]} {
+ return [my define get scm_tag]
+ }
+ if {[my define exists tag]} {
+ set tag [my define get tag]
+ } else {
+ set tag master
+ }
+ my define set scm_tag $tag
+ return $tag
+ }
+
+ method ScmUnpack {} {
+ set srcdir [my SrcDir]
+ if {[file exists [file join $srcdir .git]]} {
+ return 0
+ }
+ set CWD [pwd]
+ set tag [my ScmTag]
+ set pkg [my define get name]
+ if {[my define exists git_url]} {
+ ::practcl::doexec git clone --branch $tag [my define get git_url] $srcdir
+ } else {
+ ::practcl::doexec git clone --branch $tag https://github.com/eviltwinskippy/$pkg $srcdir
+ }
+ return 1
+ }
+
+ method ScmUpdate {} {
+ if {[my ScmUnpack]} {
+ return
+ }
+ set srcdir [my SrcDir]
+ set tag [my ScmTag]
+ ::practcl::doexec_in $srcdir git pull $tag
+ cd $CWD
+ }
+
+}
+oo::objdefine ::practcl::distribution.git {
+ method claim_path path {
+ if {[file exists [file join $path .git]]} {
+ return true
+ }
+ return false
+ }
+ method claim_object obj {
+ set path [$obj define get srcdir]
+ if {[my claim_path $path]} {
+ return true
+ }
+ if {[$obj define get git_url] ne {}} {
+ return true
+ }
+ return false
+ }
+}
+
+###
+# Meta repository
+# The default is an inert source code block
+###
+oo::class create ::practcl::subproject {
+ superclass ::practcl::object ::practcl::distribution
+
+ method compile {} {}
+
+ method critcl args {
+ if {![info exists critcl]} {
+ ::pratcl::LOCAL tool critcl load
+ set critcl [file join [::pratcl::LOCAL tool critcl define get srcdir] main.tcl
+ }
+ set srcdir [my SourceRoot]
+ set PWD [pwd]
+ cd $srcdir
+ ::pratcl::dotclexec $critcl {*}$args
+ cd $PWD
+ }
+
+ method go {} {
+ set name [my define get name]
+ set srcdir [my SrcDir]
+ my define set localsrcdir $srcdir
+ my define add include_dir [file join $srcdir generic]
+ my sources
+ }
+
+ # Install project into the local build system
+ method install args {}
+
+ method linktype {} {
+ return {subordinate package}
+ }
+
+ method linker-products {configdict} {}
+
+ method linker-external {configdict} {
+ if {[dict exists $configdict PRACTCL_PKG_LIBS]} {
+ return [dict get $configdict PRACTCL_PKG_LIBS]
+ }
+ }
+
+ method sources {} {}
+}
+
+###
+# A project which the kit compiles and integrates
+# the source for itself
+###
+oo::class create ::practcl::subproject.source {
+ superclass ::practcl::subproject ::practcl::library
+
+ method linktype {} {
+ return {subordinate package source}
+ }
+
+}
+
+# a copy from the teapot
+oo::class create ::practcl::subproject.teapot {
+ superclass ::practcl::subproject
+
+ method install-local {} {
+ my install-vfs
+ }
+
+ method install DEST {
+ set pkg [my define get pkg_name [my define get name]]
+ set download [my <project> define get download]
+ my unpack
+ set prefix [string trimleft [my <project> define get prefix] /]
+ ::practcl::tcllib_require zipfile::decode
+ ::zipfile::decode::unzipfile [file join $download $pkg.zip] [file join $DEST $prefix lib $pkg]
+ }
+}
+
+oo::class create ::practcl::subproject.kettle {
+ superclass ::practcl::subproject
+
+ method install-local {} {
+ my install-vfs
+ }
+
+ method kettle {path args} {
+ my variable kettle
+ if {![info exists kettle]} {
+ ::pratcl::LOCAL tool kettle load
+ set kettle [file join [::pratcl::LOCAL tool kettle define get srcdir] kettle]
+ }
+ set srcdir [my SourceRoot]
+ ::pratcl::dotclexec $kettle -f [file join $srcdir build.tcl] {*}$args
+ }
+
+ method install DEST {
+ my kettle reinstall --prefix $DEST
+ }
+}
+
+oo::class create ::practcl::subproject.critcl {
+ superclass ::practcl::subproject
+
+ method install-local {} {
+ my install-vfs
+ }
+
+ method install DEST {
+ my critcl -pkg [my define get name]
+ set srcdir [my SourceRoot]
+ ::pratcl::copyDir [file join $srcdir [my define get name]] [file join $DEST lib [my define get name]]
+ }
+}
+
+
+oo::class create ::practcl::subproject.sak {
+ superclass ::practcl::subproject
+
+ method install-local {} {
+ my install-vfs
+ }
+
+ method install DEST {
+ ###
+ # Handle teapot installs
+ ###
+ set pkg [my define get pkg_name [my define get name]]
+ my unpack
+ set prefix [string trimleft [my <project> define get prefix] /]
+ set srcdir [my define get srcdir]
+ ::practcl::dotclexec [file join $srcdir installer.tcl] \
+ -pkg-path [file join $DEST $prefix lib $pkg] \
+ -no-examples -no-html -no-nroff \
+ -no-wait -no-gui -no-apps
+ }
+}
+
+###
+# A binary package
+###
+oo::class create ::practcl::subproject.binary {
+ superclass ::practcl::subproject ::practcl::autoconf
+
+ method compile-products {} {}
+
+ method ConfigureOpts {} {
+ set opts {}
+ set builddir [my define get builddir]
+ if {[my define get broken_destroot 0]} {
+ set PREFIX [my <project> define get prefix_broken_destdir]
+ } else {
+ set PREFIX [my <project> define get prefix]
+ }
+ if {[my <project> define get CONFIG_SITE] != {}} {
+ lappend opts --host=[my <project> define get HOST]
+ lappend opts --with-tclsh=[info nameofexecutable]
+ }
+ if {[my <project> define exists tclsrcdir]} {
+ ###
+ # On Windows we are probably running under MSYS, which doesn't deal with
+ # spaces in filename well
+ ###
+ set TCLSRCDIR [::practcl::file_relative [file normalize $builddir] [file normalize [file join $::CWD [my <project> define get tclsrcdir]]]]
+ set TCLGENERIC [::practcl::file_relative [file normalize $builddir] [file normalize [file join $::CWD [my <project> define get tclsrcdir] .. generic]]]
+ lappend opts --with-tcl=$TCLSRCDIR --with-tclinclude=$TCLGENERIC
+ }
+ if {[my <project> define exists tksrcdir]} {
+ set TKSRCDIR [::practcl::file_relative [file normalize $builddir] [file normalize [file join $::CWD [my <project> define get tksrcdir]]]]
+ set TKGENERIC [::practcl::file_relative [file normalize $builddir] [file normalize [file join $::CWD [my <project> define get tksrcdir] .. generic]]]
+ lappend opts --with-tk=$TKSRCDIR --with-tkinclude=$TKGENERIC
+ }
+ lappend opts {*}[my define get config_opts]
+ if {![regexp -- "--prefix" $opts]} {
+ lappend opts --prefix=$PREFIX
+ }
+ #--exec_prefix=$PREFIX
+ #if {$::tcl_platform(platform) eq "windows"} {
+ # lappend opts --disable-64bit
+ #}
+ if {[my define get static 1]} {
+ lappend opts --disable-shared --disable-stubs
+ #
+ } else {
+ lappend opts --enable-shared
+ }
+ return $opts
+ }
+
+ method ComputeInstall {} {
+ if {[my define exists install]} {
+ switch [my define get install] {
+ static {
+ my define set static 1
+ my define set autoload 0
+ }
+ static-autoload {
+ my define set static 1
+ my define set autoload 1
+ }
+ vfs {
+ my define set static 0
+ my define set autoload 0
+ my define set vfsinstall 1
+ }
+ null {
+ my define set static 0
+ my define set autoload 0
+ my define set vfsinstall 0
+ }
+ default {
+
+ }
+ }
+ }
+ }
+
+ method go {} {
+ next
+ my ComputeInstall
+ my define set builddir [my BuildDir [my define get masterpath]]
+ }
+
+ method linker-products {configdict} {
+ if {![my define get static 0]} {
+ return {}
+ }
+ set srcdir [my define get builddir]
+ if {[dict exists $configdict libfile]} {
+ return " [file join $srcdir [dict get $configdict libfile]]"
+ }
+ }
+
+ method static-packages {} {
+ if {![my define get static 0]} {
+ return {}
+ }
+ set result [my define get static_packages]
+ set statpkg [my define get static_pkg]
+ set initfunc [my define get initfunc]
+ if {$initfunc ne {}} {
+ set pkg_name [my define get pkg_name]
+ if {$pkg_name ne {}} {
+ dict set result $pkg_name initfunc $initfunc
+ set version [my define get version]
+ if {$version eq {}} {
+ set info [my config.sh]
+ set version [dict get $info version]
+ set pl {}
+ if {[dict exists $info patch_level]} {
+ set pl [dict get $info patch_level]
+ append version $pl
+ }
+ my define set version $version
+ }
+ dict set result $pkg_name version $version
+ dict set result $pkg_name autoload [my define get autoload 0]
+ }
+ }
+ foreach item [my link list subordinate] {
+ foreach {pkg info} [$item static-packages] {
+ dict set result $pkg $info
+ }
+ }
+ return $result
+ }
+
+ method BuildDir {PWD} {
+ set name [my define get name]
+ return [my define get builddir [file join $PWD pkg.$name]]
+ }
+
+ method compile {} {
+ set name [my define get name]
+ set PWD $::CWD
+ cd $PWD
+ my unpack
+ set srcdir [file normalize [my SrcDir]]
+ my Collate_Source $PWD
+
+ ###
+ # Build a starter VFS for both Tcl and wish
+ ###
+ set srcdir [my define get srcdir]
+ if {[my define get static 1]} {
+ puts "BUILDING Static $name $srcdir"
+ } else {
+ puts "BUILDING Dynamic $name $srcdir"
+ }
+ if {[my define get USEMSVC 0]} {
+ cd $srcdir
+ ::practcl::doexec nmake -f makefile.vc INSTALLDIR=[my <project> define get installdir] release
+ } else {
+ cd $::CWD
+ set builddir [file normalize [my define get builddir]]
+ file mkdir $builddir
+ if {![file exists [file join $builddir Makefile]]} {
+ my Configure
+ }
+ if {[file exists [file join $builddir make.tcl]]} {
+ ::practcl::domake.tcl $builddir library
+ } else {
+ ::practcl::domake $builddir all
+ }
+ }
+ cd $PWD
+ }
+
+ method Configure {} {
+ cd $::CWD
+ my unpack
+ set srcdir [file normalize [my define get srcdir]]
+ set builddir [file normalize [my define get builddir]]
+ file mkdir $builddir
+ if {[my define get USEMSVC 0]} {
+ return
+ }
+ if {[file exists [file join $builddir practcl.log]]} {
+ file delete [file join $builddir practcl.log]
+ }
+ if {![file exists [file join $srcdir configure]]} {
+ if {[file exists [file join $srcdir autogen.sh]]} {
+ cd $srcdir
+ catch {exec sh autogen.sh >>& [file join $builddir practcl.log]}
+ cd $::CWD
+ }
+ }
+ if {![file exists [file join $srcdir tclconfig install-sh]]} {
+ # ensure we have tclconfig with all of the trimmings
+ set teapath {}
+ if {[file exists [file join $srcdir .. tclconfig install-sh]]} {
+ set teapath [file join $srcdir .. tclconfig]
+ } else {
+ set tclConfigObj [::practcl::LOCAL tool tclconfig]
+ $tclConfigObj load
+ set teapath [$tclConfigObj define get srcdir]
+ }
+ set teapath [file normalize $teapath]
+ #file mkdir [file join $srcdir tclconfig]
+ if {[catch {file link -symbolic [file join $srcdir tclconfig] $teapath}]} {
+ ::practcl::copyDir [file join $teapath] [file join $srcdir tclconfig]
+ }
+ }
+
+ set opts [my ConfigureOpts]
+ puts [list PKG [my define get name] CONFIGURE {*}$opts]
+ cd $builddir
+ if {[my <project> define get CONFIG_SITE] ne {}} {
+ set ::env(CONFIG_SITE) [my <project> define get CONFIG_SITE]
+ }
+ catch {exec sh [file join $srcdir configure] {*}$opts >>& [file join $builddir practcl.log]}
+ cd $::CWD
+ }
+
+ method install DEST {
+ set PWD [pwd]
+ set PREFIX [my <project> define get prefix]
+ ###
+ # Handle teapot installs
+ ###
+ set pkg [my define get pkg_name [my define get name]]
+ if {[my <project> define get teapot] ne {}} {
+ set TEAPOT [my <project> define get teapot]
+ set found 0
+ foreach ver [my define get pkg_vers [my define get version]] {
+ set teapath [file join $TEAPOT $pkg$ver]
+ if {[file exists $teapath]} {
+ set dest [file join $DEST [string trimleft $PREFIX /] lib [file tail $teapath]]
+ ::practcl::copyDir $teapath $dest
+ return
+ }
+ }
+ }
+ my compile
+ if {[my define get USEMSVC 0]} {
+ set srcdir [my define get srcdir]
+ cd $srcdir
+ puts "[self] VFS INSTALL $DEST"
+ ::practcl::doexec nmake -f makefile.vc INSTALLDIR=$DEST install
+ } else {
+ set builddir [my define get builddir]
+ if {[file exists [file join $builddir make.tcl]]} {
+ # Practcl builds can inject right to where we need them
+ puts "[self] VFS INSTALL $DEST (Practcl)"
+ ::practcl::domake.tcl $builddir install-package $DEST
+ } elseif {[my define get broken_destroot 0] == 0} {
+ # Most modern TEA projects understand DESTROOT in the makefile
+ puts "[self] VFS INSTALL $DEST (TEA)"
+ ::practcl::domake $builddir install DESTDIR=$DEST
+ } else {
+ # But some require us to do an install into a fictitious filesystem
+ # and then extract the gooey parts within.
+ # (*cough*) TkImg
+ set PREFIX [my <project> define get prefix]
+ set BROKENROOT [::practcl::msys_to_tclpath [my <project> define get prefix_broken_destdir]]
+ file delete -force $BROKENROOT
+ file mkdir $BROKENROOT
+ ::practcl::domake $builddir $install
+ ::practcl::copyDir $BROKENROOT [file join $DEST [string trimleft $PREFIX /]]
+ file delete -force $BROKENROOT
+ }
+ }
+ cd $PWD
+ }
+
+ method Autoconf {} {
+ ###
+ # Re-run autoconf for this project
+ # Not a good idea in practice... but in the right hands it can be useful
+ ###
+ set pwd [pwd]
+ set srcdir [file normalize [my define get srcdir]]
+ cd $srcdir
+ foreach template {configure.ac configure.in} {
+ set input [file join $srcdir $template]
+ if {[file exists $input]} {
+ puts "autoconf -f $input > [file join $srcdir configure]"
+ exec autoconf -f $input > [file join $srcdir configure]
+ }
+ }
+ cd $pwd
+ }
+}
+
+# An external library
+oo::class create ::practcl::subproject.external {
+ superclass ::practcl::subproject.binary
+ method install DEST {
+ my compile
+ }
+}
+
+oo::class create ::practcl::subproject.core {
+ superclass ::practcl::subproject.binary
+
+ # On the windows platform MinGW must build
+ # from the platform directory in the source repo
+ method BuildDir {PWD} {
+ return [my define get localsrcdir]
+ }
+
+ method Configure {} {
+ if {[my define get USEMSVC 0]} {
+ return
+ }
+ set opts [my ConfigureOpts]
+ set builddir [file normalize [my define get builddir]]
+ set localsrcdir [file normalize [my define get localsrcdir]]
+ puts [list PKG [my define get name] CONFIGURE {*}$opts]
+ cd $localsrcdir
+ if {[my <project> define get CONFIG_SITE] ne {}} {
+ set ::env(CONFIG_SITE) [my <project> define get CONFIG_SITE]
+ }
+ catch {exec sh [file join $localsrcdir configure] {*}$opts >& [file join $builddir practcl.log]}
+ }
+
+ method ConfigureOpts {} {
+ set opts {}
+ set builddir [file normalize [my define get builddir]]
+ set PREFIX [my <project> define get prefix]
+ if {[my <project> define get CONFIG_SITE] != {}} {
+ lappend opts --host=[my <project> define get HOST]
+ lappend opts --with-tclsh=[info nameofexecutable]
+ }
+ lappend opts {*}[my define get config_opts]
+ if {![regexp -- "--prefix" $opts]} {
+ lappend opts --prefix=$PREFIX
+ }
+ #--exec_prefix=$PREFIX
+ lappend opts --disable-shared
+ return $opts
+ }
+
+ method go {} {
+ set name [my define get name]
+ set os [my <project> define get TEACUP_OS]
+ my ComputeInstall
+ set srcdir [my SrcDir]
+ my define add include_dir [file join $srcdir generic]
+ switch $os {
+ windows {
+ my define set localsrcdir [file join $srcdir win]
+ my define add include_dir [file join $srcdir win]
+ }
+ default {
+ my define set localsrcdir [file join $srcdir unix]
+ my define add include_dir [file join $srcdir $name unix]
+ }
+ }
+ my define set builddir [my BuildDir [my define get masterpath]]
+ }
+
+ method linktype {} {
+ return {subordinate core.library}
+ }
+}
+
+
+###
+# Classes to manage tools that needed in the local environment
+# to compile and/or installed other packages
+###
+oo::class create ::practcl::tool {
+ superclass ::practcl::object ::practcl::distribution
+
+ method critcl args {
+ if {![info exists critcl]} {
+ ::pratcl::LOCAL tool critcl load
+ set critcl [file join [::pratcl::LOCAL tool critcl define get srcdir] main.tcl
+ }
+ set srcdir [my SourceRoot]
+ set PWD [pwd]
+ cd $srcdir
+ ::pratcl::dotclexec $critcl {*}$args
+ cd $PWD
+ }
+
+ method SourceRoot {} {
+ set info [my define dump]
+ set result $info
+ if {![my define exists srcdir]} {
+ if {[dict exists $info srcdir]} {
+ set srcdir [dict get $info srcdir]
+ } elseif {[dict exists $info sandbox]} {
+ set srcdir [file join [dict get $info sandbox] $pkg]
+ } else {
+ set srcdir [file join $::CWD .. $pkg]
+ }
+ dict set result srcdir $srcdir
+ my define set srcdir $srcdir
+ }
+ return [my define get srcdir]
+ }
+
+ method linktype {} {
+ return tool
+ }
+
+ # Return boolean if present
+ method present {} {
+ return 1
+ }
+
+ # Procedure to install in the local environment
+ method install {} {
+ my unpack
+ }
+
+ # Procedure to load into the local interpreter
+ method load {} {
+ my variable loaded
+ if {[info exists loaded]} {
+ return 0
+ }
+ if {![my present]} {
+ my install
+ }
+ my LocalLoad
+ set loaded 1
+ }
+
+ method LocalLoad {} {}
+}
+
+oo::class create ::practcl::tool.source {
+ superclass ::practcl::tool
+
+ method present {} {
+ return [file exists [my define get srcdir]]
+ }
+
+ method toplevel_script {} {
+ my load
+ return [file join [my SourceRoot] [my define get toplevel_script]]
+ }
+
+ method LocalLoad {} {
+ set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
+ if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
+ set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
+ }
+ }
+}
+
+###
+# Create an object to represent the local environment
+###
+set ::practcl::MAIN ::practcl::LOCAL
+# Defer the creation of the ::pratcl::LOCAL object until it is called
+# in order to allow packages to
+set ::auto_index(::practcl::LOCAL) {
+ puts "Building LOCAL"
+ ::practcl::project create ::practcl::LOCAL
+ ::practcl::LOCAL define set [::practcl::local_os]
+ # Until something better comes along, use ::practcl::LOCAL
+ # as our main project
+ # Add tclconfig as a project of record
+ ::practcl::LOCAL add_tool tclconfig {
+ tag trunk class tool.source fossil_url http://core.tcl.tk/tclconfig
+ }
+ # Add tcllib as a project of record
+ ::practcl::LOCAL add_tool tcllib {
+ tag trunk class tool.source fossil_url http://core.tcl.tk/tcllib
+ }
+ ::practcl::LOCAL add_tool kettle {
+ tag trunk class tool.source fossil_url http://fossil.etoyoc.com/fossil/kettle
+ }
+ ::practcl::LOCAL add_tool critcl {
+ tag trunk class tool.source
+ git_url http://github.com/andreas-kupries/critcl
+ }
+ ::practcl::LOCAL add_tool odie {
+ tag trunk class tool.source
+ fossil_url http://fossil.etoyoc.com/fossil/odie
+ }
+}
+package provide practcl 0.8a1
diff --git a/tclconfig/tcl.m4 b/tclconfig/tcl.m4
index 8bc9c83..b07ec54 100644
--- a/tclconfig/tcl.m4
+++ b/tclconfig/tcl.m4
@@ -13,12 +13,17 @@ AC_PREREQ(2.57)
dnl TEA extensions pass us the version of TEA they think they
dnl are compatible with (must be set in TEA_INIT below)
-dnl TEA_VERSION="3.9"
+dnl TEA_VERSION="3.10"
# Possible values for key variables defined:
#
# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem')
+# PRACTCL_WINDOWINGSYSTEM - windows cocoa hitheme x11 sdl
# TEA_PLATFORM - windows unix
+# TEA_TK_EXTENSION - True if this is a Tk extension
+# TEACUP_OS - windows macosx linux generic
+# TEACUP_TOOLSET - Toolset in use (gcc,mingw,msvc,llvm)
+# TEACUP_PROFILE - win32
#
#------------------------------------------------------------------------
@@ -134,10 +139,13 @@ AC_DEFUN([TEA_PATH_TCLCONFIG], [
for i in `ls -d ${libdir} 2>/dev/null` \
`ls -d ${exec_prefix}/lib 2>/dev/null` \
`ls -d ${prefix}/lib 2>/dev/null` \
- `ls -d /usr/local/lib 2>/dev/null` \
`ls -d /usr/contrib/lib 2>/dev/null` \
+ `ls -d /usr/local/lib 2>/dev/null` \
+ `ls -d /usr/pkg/lib 2>/dev/null` \
`ls -d /usr/lib 2>/dev/null` \
`ls -d /usr/lib64 2>/dev/null` \
+ `ls -d /usr/lib/tcl8.6 2>/dev/null` \
+ `ls -d /usr/lib/tcl8.5 2>/dev/null` \
; do
if test -f "$i/tclConfig.sh" ; then
ac_cv_c_tclconfig="`(cd $i; pwd)`"
@@ -205,6 +213,7 @@ AC_DEFUN([TEA_PATH_TKCONFIG], [
if test x"${no_tk}" = x ; then
# we reset no_tk in case something fails here
no_tk=true
+ TEA_TK_EXTENSION=0
AC_ARG_WITH(tk,
AC_HELP_STRING([--with-tk],
[directory containing tk configuration (tkConfig.sh)]),
@@ -324,6 +333,7 @@ AC_DEFUN([TEA_PATH_TKCONFIG], [
AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh])
else
no_tk=
+ TEA_TK_EXTENSION=1
TK_BIN_DIR="${ac_cv_c_tkconfig}"
AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh])
fi
@@ -420,8 +430,12 @@ AC_DEFUN([TEA_LOAD_TCLCONFIG], [
#ifdef _WIN32
#error win32
#endif
- ], TEA_PLATFORM="unix",
+ ], [
+ TEA_PLATFORM="unix"
+ CYGPATH=echo
+ ], [
TEA_PLATFORM="windows"
+ AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo) ]
)
CC=$hold_cc
AC_MSG_RESULT($TEA_PLATFORM)
@@ -515,18 +529,42 @@ AC_DEFUN([TEA_LOAD_TKCONFIG], [
eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\""
# TEA specific: Ensure windowingsystem is defined
- if test "${TEA_PLATFORM}" = "unix" ; then
+ case ${TK_DEFS} in
+ *PLATFORM_SDL*)
+ TEA_WINDOWINGSYSTEM="x11"
+ PRACTCL_WINDOWINGSYSTEM="sdl"
+ TEA_USE_SDL=yes
+ ;;
+ esac
+ if test "${TEA_USE_SDL}" = "yes" ; then
+ true
+ elif test "${TEA_PLATFORM}" = "unix" ; then
case ${TK_DEFS} in
*MAC_OSX_TK*)
- AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?])
+ AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X Cocoa?])
TEA_WINDOWINGSYSTEM="aqua"
+ PRACTCL_WINDOWINGSYSTEM="cocoa"
+ TEA_USE_HITHEME=no;
+ if test "${TK_VERSION}" = "8.5" ; then
+ if test "${TK_PATCH_LEVEL}" > ".17" ; then
+ TEA_USE_HITHEME=yes;
+ fi
+ elif test "${TK_VERSION}" = "8.6" ; then
+ if test "${TK_PATCH_LEVEL}" > ".3" ; then
+ TEA_USE_HITHEME=yes;
+ fi
+ elif test "${TK_VERSION}" > "8.6" ; then
+ TEA_USE_HITHEME=yes;
+ fi
;;
*)
TEA_WINDOWINGSYSTEM="x11"
+ PRACTCL_WINDOWINGSYSTEM="x11"
;;
esac
elif test "${TEA_PLATFORM}" = "windows" ; then
TEA_WINDOWINGSYSTEM="win32"
+ PRACTCL_WINDOWINGSYSTEM="windows"
fi
AC_SUBST(TK_VERSION)
@@ -544,6 +582,8 @@ AC_DEFUN([TEA_LOAD_TKCONFIG], [
# TEA specific:
AC_SUBST(TK_LIBS)
AC_SUBST(TK_XINCLUDES)
+ # Practcl
+ AC_SUBST(PRACTCL_WINDOWINGSYSTEM)
])
#------------------------------------------------------------------------
@@ -567,14 +607,41 @@ AC_DEFUN([TEA_LOAD_TKCONFIG], [
AC_DEFUN([TEA_PROG_TCLSH], [
AC_MSG_CHECKING([for tclsh])
- if test -f "${TCL_BIN_DIR}/Makefile" ; then
+
+ AC_ARG_WITH(tclsh, [ --with-tclsh Specify a local tcl shell to use for dynamic code], with_tclsh=${withval})
+ # Use the value from --with-tclsh, if it was given
+ TCLSH_PROG=0
+ if test x"${with_tclsh}" != x ; then
+ if test -f "${with_tclsh}" ; then
+ TCLSH_PROG=${with_tclsh}
+ else
+ if test -f "${with_tclsh}/tcl8.6" ; then
+ TCLSH_PROG="${with_tclsh}/tcl8.6"
+ else
+ if test -f "${with_tclsh}/tclsh86.exe" ; then
+ TCLSH_PROG="${with_tclsh}/tclsh86.exe"
+ else
+ AC_MSG_ERROR([${with_tclsh} does not point to a valid Tcl executable])
+ fi
+ fi
+ fi
+ else
+ if test -f "${TCL_BIN_DIR}/Makefile" ; then
# tclConfig.sh is in Tcl build directory
if test "${TEA_PLATFORM}" = "windows"; then
+ if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" ; then
TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
+ elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}s${EXEEXT}" ; then
+ TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}s${EXEEXT}"
+ elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}t${EXEEXT}" ; then
+ TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}t${EXEEXT}"
+ elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}st${EXEEXT}" ; then
+ TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}st${EXEEXT}"
+ fi
else
TCLSH_PROG="${TCL_BIN_DIR}/tclsh"
fi
- else
+ else
# tclConfig.sh is in install location
if test "${TEA_PLATFORM}" = "windows"; then
TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
@@ -591,7 +658,8 @@ AC_DEFUN([TEA_PROG_TCLSH], [
fi
done
TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}"
- fi
+ fi
+ fi
AC_MSG_RESULT([${TCLSH_PROG}])
AC_SUBST(TCLSH_PROG)
])
@@ -620,9 +688,17 @@ AC_DEFUN([TEA_PROG_WISH], [
if test -f "${TK_BIN_DIR}/Makefile" ; then
# tkConfig.sh is in Tk build directory
if test "${TEA_PLATFORM}" = "windows"; then
+ if test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" ; then
WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
+ elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}s${EXEEXT}" ; then
+ WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}$s{EXEEXT}"
+ elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}t${EXEEXT}" ; then
+ WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}t${EXEEXT}"
+ elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}st${EXEEXT}" ; then
+ WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}st${EXEEXT}"
+ fi
else
- WISH_PROG="${TK_BIN_DIR}/wish"
+ WISH_PROG="${TK_BIN_DIR}/wish"
fi
else
# tkConfig.sh is in install location
@@ -658,6 +734,7 @@ AC_DEFUN([TEA_PROG_WISH], [
#
# Adds the following arguments to configure:
# --enable-shared=yes|no
+# --enable-stubs=yes|no
#
# Defines the following vars:
# STATIC_BUILD Used for building import/export libraries
@@ -665,31 +742,63 @@ AC_DEFUN([TEA_PROG_WISH], [
#
# Sets the following vars:
# SHARED_BUILD Value of 1 or 0
+# STUBS_BUILD Value if 1 or 0
+# USE_TCL_STUBS Value true: if SHARED_BUILD or --enable-stubs
+# USE_TCLOO_STUBS Value true: if SHARED_BUILD or --enable-stubs
+# USE_TK_STUBS Value true: if SHARED_BUILD or --enable-stubs
+# AND TEA_WINDOWING_SYSTEM != ""
#------------------------------------------------------------------------
-
AC_DEFUN([TEA_ENABLE_SHARED], [
AC_MSG_CHECKING([how to build libraries])
AC_ARG_ENABLE(shared,
AC_HELP_STRING([--enable-shared],
[build and link with shared libraries (default: on)]),
- [tcl_ok=$enableval], [tcl_ok=yes])
+ [shared_ok=$enableval], [shared_ok=yes])
if test "${enable_shared+set}" = set; then
enableval="$enable_shared"
- tcl_ok=$enableval
+ shared_ok=$enableval
else
- tcl_ok=yes
+ shared_ok=yes
+ fi
+
+ AC_ARG_ENABLE(stubs,
+ AC_HELP_STRING([--enable-stubs],
+ [build and link with stub libraries. Always true for shared builds (default: on)]),
+ [stubs_ok=$enableval], [stubs_ok=yes])
+
+ if test "${enable_stubs+set}" = set; then
+ enableval="$enable_stubs"
+ stubs_ok=$enableval
+ else
+ stubs_ok=yes
fi
- if test "$tcl_ok" = "yes" ; then
+ # Stubs are always enabled for shared builds
+ if test "$shared_ok" = "yes" ; then
AC_MSG_RESULT([shared])
SHARED_BUILD=1
+ STUBS_BUILD=1
else
AC_MSG_RESULT([static])
SHARED_BUILD=0
- AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
+ AC_DEFINE(STATIC_BUILD, 1, [This a static build])
+ if test "$stubs_ok" = "yes" ; then
+ STUBS_BUILD=1
+ else
+ STUBS_BUILD=0
+ fi
fi
+ if test "${STUBS_BUILD}" = "1" ; then
+ AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
+ AC_DEFINE(USE_TCLOO_STUBS, 1, [Use TclOO stubs])
+ if test "${TEA_WINDOWINGSYSTEM}" != ""; then
+ AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])
+ fi
+ fi
+
AC_SUBST(SHARED_BUILD)
+ AC_SUBST(STUBS_BUILD)
])
#------------------------------------------------------------------------
@@ -1131,7 +1240,7 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
AC_CHECK_TOOL(AR, ar)
STLIB_LD='${AR} cr'
LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
- AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION="1.0"])
+ AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION=""],[SHLIB_VERSION=".$SHLIB_VERSION"])
case $system in
# TEA specific:
windows)
@@ -1232,13 +1341,21 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
else
runtime=-MD
fi
+ case "x`echo \${VisualStudioVersion}`" in
+ x1[[4-9]]*)
+ lflags="${lflags} -nodefaultlib:libucrt.lib"
+ TEA_ADD_LIBS([ucrt.lib])
+ ;;
+ *)
+ ;;
+ esac
if test "$do64bit" != "no" ; then
# All this magic is necessary for the Win64 SDK RC1 - hobbs
CC="\"${PATH64}/cl.exe\""
CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\""
RC="\"${MSSDK}/bin/rc.exe\""
- lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
+ lflags="${lflags} -nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
LINKBIN="\"${PATH64}/link.exe\""
CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d"
CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
@@ -1268,13 +1385,13 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
CFLAGS_DEBUG="-nologo -Zi -Od"
CFLAGS_OPTIMIZE="-nologo -Ox"
lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
- lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
+ lflags="${lflags} -MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
LINKBIN="\"${CEBINROOT}/link.exe\""
AC_SUBST(CELIB_DIR)
else
RC="rc"
- lflags="-nologo"
- LINKBIN="link"
+ lflags="${lflags} -nologo"
+ LINKBIN="link"
CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d"
CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
fi
@@ -1287,13 +1404,15 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
SHLIB_LD='${CC} -shared'
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ PRACTCL_UNSHARED_LIB_SUFFIX='.a'
+
LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}"
LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}"
AC_CACHE_CHECK(for cross-compile version of gcc,
ac_cv_cross,
AC_TRY_COMPILE([
- #ifdef __WIN32__
+ #ifdef _WIN32
#error cross-compiler
#endif
], [],
@@ -1424,8 +1543,10 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
CYGWIN_*)
SHLIB_CFLAGS=""
SHLIB_LD='${CC} -shared'
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a"
SHLIB_SUFFIX=".dll"
EXEEXT=".exe"
+ do64bit_ok=yes
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
@@ -1589,13 +1710,20 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
LDFLAGS=""
;;
*)
- SHLIB_CFLAGS="-fPIC"
+ case "$arch" in
+ alpha|sparc64)
+ SHLIB_CFLAGS="-fPIC"
+ ;;
+ *)
+ SHLIB_CFLAGS="-fpic"
+ ;;
+ esac
SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
SHLIB_SUFFIX=".so"
AS_IF([test $doRpath = yes], [
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}'
LDFLAGS="-Wl,-export-dynamic"
;;
esac
@@ -1637,7 +1765,7 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
# This configuration from FreeBSD Ports.
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="${CC} -shared"
- TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]"
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]"
SHLIB_SUFFIX=".so"
LDFLAGS=""
AS_IF([test $doRpath = yes], [
@@ -1648,11 +1776,15 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
LIBS=`echo $LIBS | sed s/-pthread//`
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
- # Version numbers are dot-stripped by system policy.
- TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .`
- UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
- SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1'
- TCL_LIB_VERSIONS_OK=nodots
+ case $system in
+ FreeBSD-3.*)
+ # Version numbers are dot-stripped by system policy.
+ TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .`
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ esac
;;
Darwin-*)
CFLAGS_OPTIMIZE="-Os"
@@ -1823,8 +1955,8 @@ AC_DEFUN([TEA_CONFIG_CFLAGS], [
SHLIB_CFLAGS="-fPIC -melf"
LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
], [
- SHLIB_CFLAGS="-Kpic -belf"
- LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
+ SHLIB_CFLAGS="-Kpic -belf"
+ LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
])
SHLIB_LD="ld -G"
SHLIB_LD_LIBS=""
@@ -2005,10 +2137,12 @@ dnl # preprocessing tests use only CPPFLAGS.
AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
# TEA specific: use PACKAGE_VERSION instead of VERSION
- SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}'])
+ SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}'
+ ])
AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
# TEA specific: use PACKAGE_VERSION instead of VERSION
- UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'])
+ UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'
+ ])
if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then
AC_CACHE_CHECK(for SEH support in compiler,
@@ -2111,6 +2245,7 @@ dnl # preprocessing tests use only CPPFLAGS.
AC_SUBST(STLIB_LD)
AC_SUBST(SHLIB_LD)
+ AC_SUBST(SHLIB_SUFFIX)
AC_SUBST(SHLIB_LD_LIBS)
AC_SUBST(SHLIB_CFLAGS)
@@ -2356,7 +2491,7 @@ closedir(d);
#--------------------------------------------------------------------
AC_DEFUN([TEA_PATH_X], [
- if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then
+ if test "${PRACTCL_WINDOWINGSYSTEM}" = "x11" ; then
TEA_PATH_UNIX_X
fi
])
@@ -2834,12 +2969,11 @@ AC_DEFUN([TEA_TCL_64BIT_FLAGS], [
AC_DEFUN([TEA_INIT], [
# TEA extensions pass this us the version of TEA they think they
# are compatible with.
- TEA_VERSION="3.9"
-
+ TEA_VERSION="3.10"
AC_MSG_CHECKING([for correct TEA configuration])
if test x"${PACKAGE_NAME}" = x ; then
AC_MSG_ERROR([
-The PACKAGE_NAME variable must be defined by your TEA configure.in])
+The PACKAGE_NAME variable must be defined by your TEA configure.ac])
fi
if test x"$1" = x ; then
AC_MSG_ERROR([
@@ -2855,17 +2989,17 @@ TEA version not specified.])
if test "${CFLAGS+set}" != "set" ; then
CFLAGS=""
fi
-
+ TEA_TK_EXTENSION=0
+ AC_SUBST(TEA_TK_EXTENSION)
case "`uname -s`" in
*win32*|*WIN32*|*MINGW32_*)
- AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)
+ AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo)
EXEEXT=".exe"
TEA_PLATFORM="windows"
;;
*CYGWIN_*)
- CYGPATH=echo
EXEEXT=".exe"
- # TEA_PLATFORM is determined later in LOAD_TCLCONFIG
+ # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG
;;
*)
CYGPATH=echo
@@ -3102,8 +3236,12 @@ AC_DEFUN([TEA_ADD_LIBS], [
vars="$@"
for i in $vars; do
if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then
- # Convert foo.lib to -lfoo for GCC. No-op if not *.lib
- i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'`
+ case $i in
+ *.lib)
+ # Convert foo.lib to -lfoo for GCC
+ i=-l`echo "$i" | sed -e 's/\.[[^.]]*$//' -e 's/\.lib.*//'`
+ ;;
+ esac
fi
PKG_LIBS="$PKG_LIBS $i"
done
@@ -3186,7 +3324,7 @@ AC_DEFUN([TEA_PREFIX], [
# TEA_SETUP_COMPILER_CC --
#
# Do compiler checks the way we want. This is just a replacement
-# for AC_PROG_CC in TEA configure.in files to make them cleaner.
+# for AC_PROG_CC in TEA configure.ac files to make them cleaner.
#
# Arguments:
# none
@@ -3202,8 +3340,19 @@ AC_DEFUN([TEA_SETUP_COMPILER_CC], [
AC_PROG_CC
AC_PROG_CPP
- INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c"
+ INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c'
+ INSTALL_DATA_DIR='${INSTALL} -d -m 755'
+ INSTALL_DATA='${INSTALL} -m 644'
+ INSTALL_PROGRAM='${INSTALL}'
+ INSTALL_SCRIPT='${INSTALL}'
+ INSTALL_LIBRARY='${INSTALL_DATA}'
+
AC_SUBST(INSTALL)
+ AC_SUBST(INSTALL_DATA_DIR)
+ AC_SUBST(INSTALL_DATA)
+ AC_SUBST(INSTALL_PROGRAM)
+ AC_SUBST(INSTALL_SCRIPT)
+ AC_SUBST(INSTALL_LIBRARY)
#--------------------------------------------------------------------
# Checks to see if the make program sets the $MAKE variable.
@@ -3296,92 +3445,131 @@ AC_DEFUN([TEA_SETUP_COMPILER], [
# MAKE_STUB_LIB Makefile rule for building a stub library
# VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL
# VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE
+#
+# PRACTCL_TOOLSET What toolset is in use (gcc or msvc)
+# PRACTCL_SHARED_LIB Template rule for building a shared library
+# PRACTCL_STATIC_LIB Template rule for building a static library
+# PRACTCL_STUB_LIB Template rule for building a stub library
+# PRACTCL_VC_MANIFEST_EMBED_DLL Template rule for embedded VC manifest in DLL
+# PRACTCL_VC_MANIFEST_EMBED_EXE Template rule for embedded VC manifest in EXE
+# PRACTCL_NAME_LIBRARY Template rule for naming libraries
+#
#------------------------------------------------------------------------
AC_DEFUN([TEA_MAKE_LIB], [
- if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then
- MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)"
- MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)"
- AC_EGREP_CPP([manifest needed], [
+ PRACTCL_TOOLSET="gcc"
+ PRACTCL_VC_MANIFEST_EMBED_DLL=:
+ PRACTCL_VC_MANIFEST_EMBED_EXE=:
+ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then
+ PRACTCL_TOOLSET="msvc"
+ PRACTCL_STATIC_LIB="%STLIB_LD% -out:%OUTFILE% %LIBRARY_OBJECTS%"
+ PRACTCL_SHARED_LIB="%SHLIB_LD% %SHLIB_LD_LIBS% %LDFLAGS_DEFAULT% -out:%OUTFILE% %LIBRARY_OBJECTS%"
+ MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)"
+ MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)"
+ AC_EGREP_CPP([manifest needed], [
#if defined(_MSC_VER) && _MSC_VER >= 1400
print("manifest needed")
#endif
- ], [
- # Could do a CHECK_PROG for mt, but should always be with MSVC8+
- VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi"
- VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi"
- MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}"
- TEA_ADD_CLEANFILES([*.manifest])
- ])
- MAKE_STUB_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_STUB_OBJECTS)"
- else
- MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)"
- MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
- MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)"
- fi
-
- if test "${SHARED_BUILD}" = "1" ; then
- MAKE_LIB="${MAKE_SHARED_LIB} "
- else
- MAKE_LIB="${MAKE_STATIC_LIB} "
- fi
-
- #--------------------------------------------------------------------
- # Shared libraries and static libraries have different names.
- # Use the double eval to make sure any variables in the suffix is
- # substituted. (@@@ Might not be necessary anymore)
- #--------------------------------------------------------------------
-
- if test "${TEA_PLATFORM}" = "windows" ; then
- if test "${SHARED_BUILD}" = "1" ; then
+ ], [
+ # Could do a CHECK_PROG for mt, but should always be with MSVC8+
+ PRACTCL_VC_MANIFEST_EMBED_DLL="mt.exe -nologo -manifest %OUTFILE%.manifest -outputresource:%OUTFILE%\;2"
+ PRACTCL_VC_MANIFEST_EMBED_EXE="mt.exe -nologo -manifest %OUTFILE%.manifest -outputresource:%OUTFILE%\;1"
+ VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi"
+ VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi"
+ MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}"
+ TEA_ADD_CLEANFILES([*.manifest])
+ ])
+ PRACTCL_STUB_LIB="%STLIB_LD% -nodefaultlib -out:%OUTFILE% %LIBRARY_OBJECTS%"
+ MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@ \$(PKG_STUB_OBJECTS)"
+ else
+ MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)"
+ MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
+ MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)"
+
+ PRACTCL_STATIC_LIB="%STLIB_LD% %OUTFILE% %LIBRARY_OBJECTS%"
+ PRACTCL_SHARED_LIB="%SHLIB_LD% -o %OUTFILE% %LIBRARY_OBJECTS% %SHLIB_LD_LIBS%"
+ PRACTCL_STUB_LIB="%STLIB_LD% %OUTFILE% %LIBRARY_OBJECTS%"
+ fi
+
+ if test "${SHARED_BUILD}" = "1" ; then
+ MAKE_LIB="${MAKE_SHARED_LIB} "
+ else
+ MAKE_LIB="${MAKE_STATIC_LIB} "
+ fi
+
+ #--------------------------------------------------------------------
+ # Shared libraries and static libraries have different names.
+ # Use the double eval to make sure any variables in the suffix is
+ # substituted. (@@@ Might not be necessary anymore)
+ #--------------------------------------------------------------------
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ PRACTCL_NAME_LIBRARY="%LIBRARY_PREFIX%%LIBRARY_NAME%%LIBRARY_VERSION_NODOTS%"
+ if test "${SHARED_BUILD}" = "1" ; then
# We force the unresolved linking of symbols that are really in
# the private libraries of Tcl and Tk.
- SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\""
if test x"${TK_BIN_DIR}" != x ; then
- SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\""
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\""
fi
- eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
- else
- eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
- fi
- # Some packages build their own stubs libraries
- eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
- if test "$GCC" = "yes"; then
- PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE}
- fi
- # These aren't needed on Windows (either MSVC or gcc)
- RANLIB=:
- RANLIB_STUB=:
- else
- RANLIB_STUB="${RANLIB}"
- if test "${SHARED_BUILD}" = "1" ; then
- SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}"
- if test x"${TK_BIN_DIR}" != x ; then
- SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}"
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\""
+ if test "$GCC" = "yes"; then
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc"
fi
- eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
- RANLIB=:
- else
- eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
- fi
- # Some packages build their own stubs libraries
- eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
+ eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
+ else
+ eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
+ if test "$GCC" = "yes"; then
+ PKG_LIB_FILE=lib${PKG_LIB_FILE}
+ fi
+ fi
+ # Some packages build their own stubs libraries
+ eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
+ if test "$GCC" = "yes"; then
+ PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE}
fi
-
- # These are escaped so that only CFLAGS is picked up at configure time.
- # The other values will be substituted at make time.
- CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}"
- if test "${SHARED_BUILD}" = "1" ; then
- CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}"
+ # These aren't needed on Windows (either MSVC or gcc)
+ RANLIB=:
+ RANLIB_STUB=:
+ else
+ PRACTCL_NAME_LIBRARY="lib%LIBRARY_PREFIX%%LIBRARY_NAME%%LIBRARY_VERSION%"
+ RANLIB_STUB="${RANLIB}"
+ if test "${SHARED_BUILD}" = "1" ; then
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}"
+ if test x"${TK_BIN_DIR}" != x ; then
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}"
+ fi
+ eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
+ RANLIB=:
+ else
+ eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
fi
-
- AC_SUBST(MAKE_LIB)
- AC_SUBST(MAKE_SHARED_LIB)
- AC_SUBST(MAKE_STATIC_LIB)
- AC_SUBST(MAKE_STUB_LIB)
- AC_SUBST(RANLIB_STUB)
- AC_SUBST(VC_MANIFEST_EMBED_DLL)
- AC_SUBST(VC_MANIFEST_EMBED_EXE)
+ # Some packages build their own stubs libraries
+ eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
+ fi
+
+ # Store the raw CFLAGS before we add the trimmings
+ PRACTCL_CFLAGS=${CFLAGS}
+ # These are escaped so that only CFLAGS is picked up at configure time.
+ # The other values will be substituted at make time.
+ CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}"
+ if test "${SHARED_BUILD}" = "1" ; then
+ CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}"
+ fi
+
+ AC_SUBST(MAKE_LIB)
+ AC_SUBST(MAKE_SHARED_LIB)
+ AC_SUBST(MAKE_STATIC_LIB)
+ AC_SUBST(MAKE_STUB_LIB)
+ AC_SUBST(RANLIB_STUB)
+ AC_SUBST(VC_MANIFEST_EMBED_DLL)
+ AC_SUBST(VC_MANIFEST_EMBED_EXE)
+ AC_SUBST(PRACTCL_CFLAGS)
+ AC_SUBST(PRACTCL_TOOLSET)
+ AC_SUBST(PRACTCL_SHARED_LIB)
+ AC_SUBST(PRACTCL_STATIC_LIB)
+ AC_SUBST(PRACTCL_STUB_LIB)
+ AC_SUBST(PRACTCL_VC_MANIFEST_EMBED_DLL)
+ AC_SUBST(PRACTCL_VC_MANIFEST_EMBED_EXE)
+ AC_SUBST(PRACTCL_NAME_LIBRARY)
])
#------------------------------------------------------------------------
@@ -3676,12 +3864,24 @@ AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [
if test -d "${TK_SRC_DIR}/generic/ttk"; then
TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\""
fi
- if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then
+ case ${PRACTCL_WINDOWINGSYSTEM} in
+ cocoa)
TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\""
- fi
- if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then
TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\""
- fi
+ ;;
+ hitheme)
+ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\""
+ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\""
+ ;;
+ sdl)
+ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\""
+ ;;
+ x11)
+ ;;
+ *)
+ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\""
+ ;;
+ esac
if test "`uname -s`" = "Darwin"; then
# If Tk was built as a framework, attempt to use
# the framework's Headers and PrivateHeaders directories
@@ -3806,7 +4006,7 @@ AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [
AC_SUBST(TK_INCLUDES)
- if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then
+ if test "${PRACTCL_WINDOWINGSYSTEM}" != "x11"; then
# On Windows and Aqua, we need the X compat headers
AC_MSG_CHECKING([for X11 header files])
if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then
@@ -4057,12 +4257,12 @@ AC_DEFUN([TEA_EXPORT_CONFIG], [
eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
fi
- $1_BUILD_LIB_SPEC="-L`pwd` ${$1_LIB_FLAG}"
- $1_LIB_SPEC="-L${pkglibdir} ${$1_LIB_FLAG}"
- $1_BUILD_STUB_LIB_SPEC="-L`pwd` [$]{$1_STUB_LIB_FLAG}"
- $1_STUB_LIB_SPEC="-L${pkglibdir} [$]{$1_STUB_LIB_FLAG}"
- $1_BUILD_STUB_LIB_PATH="`pwd`/[$]{PKG_STUB_LIB_FILE}"
- $1_STUB_LIB_PATH="${pkglibdir}/[$]{PKG_STUB_LIB_FILE}"
+ $1_BUILD_LIB_SPEC="-L`$CYGPATH $(pwd)` ${$1_LIB_FLAG}"
+ $1_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` ${$1_LIB_FLAG}"
+ $1_BUILD_STUB_LIB_SPEC="-L`$CYGPATH $(pwd)` [$]{$1_STUB_LIB_FLAG}"
+ $1_STUB_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` [$]{$1_STUB_LIB_FLAG}"
+ $1_BUILD_STUB_LIB_PATH="`$CYGPATH $(pwd)`/[$]{PKG_STUB_LIB_FILE}"
+ $1_STUB_LIB_PATH="`$CYGPATH ${pkglibdir}`/[$]{PKG_STUB_LIB_FILE}"
AC_SUBST($1_BUILD_LIB_SPEC)
AC_SUBST($1_LIB_SPEC)
@@ -4144,6 +4344,112 @@ AC_DEFUN([TEA_PATH_CELIB], [
fi
])
+#--------------------------------------------------------------------
+# TEA_CONFIG_TEAPOT
+#
+# Try to determine the canonical name for this package's binary
+# target
+#
+# Arguments:
+# none
+AC_DEFUN([TEA_CONFIG_TEAPOT], [
+ AC_REQUIRE([TEA_INIT])
+ AC_REQUIRE([TEA_CONFIG_SYSTEM])
+ TEACUP_OS=$system
+ TEACUP_ARCH="unknown"
+ TEACUP_TOOLSET="gcc"
+ TEACUP_PROFILE="unknown"
+ arch="unknown"
+ case ${host_alias} in
+ *mingw32*)
+ arch="ix86"
+ TEACUP_PROFILE="win32-ix86"
+ ;;
+ *mingw64*)
+ arch="x86_64"
+ TEACUP_PROFILE="win32-x86_64"
+ ;;
+ esac
+ if test "${arch}" = "unknown" ; then
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ if test "$GCC" = "yes" ; then
+ TEACUP_TOOLSET="gcc"
+ else
+ TEACUP_TOOLSET="msvc"
+ fi
+ if test "$do64bit" != "no" ; then
+ case "$do64bit" in
+ amd64|x64|yes)
+ arch="x86_64"
+ TEACUP_PROFILE="win32-x86_64"
+ ;;
+ ia64)
+ arch="ia64"
+ TEACUP_PROFILE="win32-ia64"
+ ;;
+ esac
+ else
+ arch="ix86"
+ TEACUP_PROFILE="win32-ix86"
+ fi
+ else
+ case $system in
+ Linux*)
+ TEACUP_OS="linux"
+ arch=`uname -m`
+ TEACUP_PROFILE="linux-glibc2.3-$arch"
+ ;;
+ GNU*)
+ TEACUP_OS="gnu"
+ arch=`uname -m`
+ ;;
+ NetBSD-Debian)
+ TEACUP_OS="netbsd-debian"
+ arch=`uname -m`
+ ;;
+ OpenBSD-*)
+ TEACUP_OS="openbsd"
+ arch=`arch -s`
+ ;;
+ Darwin*)
+ TEACUP_OS="macosx"
+ TEACUP_PROFILE="macosx-universal"
+ arch=`uname -m`
+ if test $arch = "x86_64"; then
+ TEACUP_PROFILE="macosx10.5-i386-x86_84"
+ fi
+ ;;
+ OpenBSD*)
+ TEACUP_OS="openbsd"
+ arch=`arch -s`
+ ;;
+ esac
+ fi
+ fi
+ TEACUP_ARCH=$arch
+ if test "$TEACUP_PROFILE" = "unknown"; then
+ if test $arch = "unknown"; then
+ arch=`uname -m`
+ fi
+ case $arch in
+ i*86)
+ arch="ix86"
+ ;;
+ amd64)
+ arch="x86_64"
+ ;;
+ esac
+ TEACUP_PROFILE="$TEACUP_OS-$arch"
+ fi
+ TEA_SYSTEM=$system
+ AC_SUBST(TEA_SYSTEM)
+ AC_SUBST(TEA_PLATFORM)
+ AC_SUBST(TEA_WINDOWINGSYSTEM)
+ AC_SUBST(TEACUP_OS)
+ AC_SUBST(TEACUP_ARCH)
+ AC_SUBST(TEACUP_TOOLSET)
+ AC_SUBST(TEACUP_PROFILE)
+])
# Local Variables:
# mode: autoconf