[Starkit] filleting tcllib

Schofield, Bryan (GE Trans) Bryan.Schofield at trans.ge.com
Wed May 4 10:31:07 CEST 2005


> -----Original Message-----
> From: starkit-bounces at equi4.com [mailto:starkit-bounces at equi4.com]On
> Behalf Of Steve Blinkhorn
> Sent: Wednesday, May 04, 2005 7:13 AM
> To: starkit at equi4.com
> Subject: [Starkit] filleting tcllib
> 
> 
> Tcllib is now quite big (4.5MB+), and individual packages often have
> significant dependencies.  Including the whole of tcllib in a starkit
> that is going to be downloaded by many users for a single usage
> introduces a significant download penalty, particularly for dialup
> users, but is unlikely to be of concern to those who are downloading
> and installing a conventional Tcl/Tk installation. 
> 
> Has anyone given any thought to a method for filleting tcllib, i.e.
> specifying a list of packages known to be required, and ensuring that
> those packages plus all dependencies are extracted and placed
> appropriately in a .vfs tree?   Doing it by hand is moderately
> painful, and I wonder if some clever use of [package ifneeded],
> perhaps grabbing all the pkgIndex.tcl files and programmatically
> rewriting them to replace the "source [file join...." element with a
> "[file copy..." or two might be a way forward.
> 
> -- 
> Steve Blinkhorn <steve at prd.co.uk>
> _____________________________________________
> Starkit mailing list  -  Starkit at equi4.com
> http://www.equi4.com/mailman/listinfo/starkit
> 



Below is simple tcl package that I use to find a package and it's dependancies and collect them all as one big hunk of code. For example, if you needed package foo, you could do the following to collect foo and everything else it needs

cd $myVfsLibDir
set c [open myfoo.tcl w]
puts $c [flatpkg::script foo]
close $c
pkg_mkIndex . myfoo.tcl


One thing to note, I don't think my "flatpkg" thing will work if the package if the package source files try to read variables in the global scope. It's implemented using slave interps with one command, "unknown". But, a proper package shouldn't be doing things in the global namespace anyhow, and from what I can tell, it works just fine with tcllib.

As a real-world example, flatpkg::script "struct", returns one the concatenation of the following files in the order specified below.

cmdline/typedCmdline.tcl
cmdline/cmdline.tcl
struct/list.tcl
struct/graph.tcl
struct/queue.tcl
struct/stack.tcl
struct/tree.tcl
struct/matrix.tcl
struct/pool.tcl
struct/record.tcl
struct/sets.tcl
struct/prioqueue.tcl
struct/skiplist.tcl
struct/struct.tcl







----
package provide flatpkg 1.0
namespace eval ::flatpkg {
    variable script ""
}

proc ::flatpkg::script {pkg {version ""}} {
    variable script
    set script ""
    set interp [CreateSourcingInterp]
    foreach f [FindSourceFiles $pkg $version] {
        set chan [open $f r]
        set data [read $chan]
        close $chan
        $interp eval $data
    }
    return $script
}

proc ::flatpkg::AppendToScript {args} {
    variable script
    append script $args "\n"
}

proc ::flatpkg::CreateSourcingInterp {} {
    set interp [interp create]
    foreach c [$interp eval {info commands}] {
        if {$c eq "rename"} {continue}
        $interp eval [list rename $c ""]
    }
    $interp eval {rename rename ""}
    interp alias $interp unknown {} ::flatpkg::AppendToScript
    return $interp
}

proc ::flatpkg::FindSourceFiles {package {version ""}} {
    set interp [interp create]
    $interp eval {
        namespace eval ::findsource {
            variable files {}
        }
        proc ::findsource::ignore {f} {
            if {[file tail $f] eq "pkgIndex.tcl"} { return 1}
            if {[string match $::tcl_library* $f]} { return 1 }
            if {[info exists ::tk_library] && [string match $::tk_library* $f]} {
                return 1
            }
            return 0
        }
        proc ::findsource::process {cmd code result op} {
            variable files
            set f [lindex [split $cmd] 1]
            if {![ignore $f]} {
                lappend files [file normalize $f]
            }
        }
        trace add execution source leave ::findsource::process
    }
    $interp eval [list set auto_path $::auto_path]
    $interp eval "package forget $package $version"
    $interp eval "package require $package $version"
    set files [$interp eval "set ::findsource::files"]
    interp delete $interp
    return $files
}


More information about the Starkit mailing list