Updated 2009-05-04 13:33:27 by Cameron

20040617 CMcC: Here's a parser for tclConfig.sh - useful for introspection in things like critcl. tclConfig.sh is emitted as part of the build, capturing useful data about the build.

Update: jenglish has pointed out that this information is definitely either not portable between build machine and installation machine (if they differ, as they often will) or is derivable from info or tcl::pkgconfig. Details follow the parser.
    #! /usr/bin/env tclsh

    # Some code to parse the tclConfig.sh file into namespace vars
    # in ::tclConfig.  Merely sourcing this file will do all the work

    namespace eval tclConfig {
        namespace eval v {
        variable top ::tclConfig
        variable sect_re "\[\\\[\]\[ \t\]*(\[A-Za-z0-9_\]+)\[ \t\]*\[\\\]\]"
        variable comment_re {^(.*)#.*$}
        variable comment_match {#*}
        variable def_re {[ \t]*([A-Za-z0-9_]+)[ \t]*=[ \t]*(.*)(#.*)?$}
        }

        variable VERSION $::tcl_version
    }

    proc tclConfig::unparse {} {
        set result ""
        foreach var [info vars ::tclConfig::*] {
        append result "[namespace tail $var] = \"[set $var]\"" " "
        }
        return $result
    }

    proc tclConfig::parse {dir} {
        set fd [open [file join $dir tclConfig.sh]]
        namespace eval $v::top {}
        set section ""
        foreach line [split [read $fd] \n] {
        set line [string trim $line " \t"]
        regexp $v::comment_re $line x line
        if {[string match $v::comment_match $line] || ($line eq "")} {
            # comment
            continue
        } elseif {[regexp $v::def_re $line x var val]} {
            # definition
            set val [string trim $val " \t"]
            regsub -all {[$]ENV::([A-Za-z0-9_]+)} $val {$::env(\1)} val
            set val [string trim $val ']
            if {[catch {namespace eval $v::top "set $var \"$val\""}]} {
                set vars($var) $val
            } elseif {$var eq "TCL_DBGX"} {
                namespace eval $v::top set DBGX "$val"
            }
        } else {
            error "Can't parse '$line'"
        }
        }

        set change 1
        while {$change && [array size vars]} {
        set change 0
        foreach {var val} [array get vars] {
            if {![catch {
                namespace eval $v::top "set $var \"$val\""
            } result]} {
                set change 1
                unset vars($var)
            }
        }
        }
        foreach {var val} [array get vars] {
        namespace eval $v::top set $var [list $val]
        }
    }

    tclConfig::parse $::tcl_library

    if {[info exists argv0] && ([info script] == $argv0)} {
        puts [tclConfig::unparse]
    }

Details of tclConfig's uselessness to scripts
    Colin: Can you tell me what's not useful?
    jenglish: There is -- have I mentioned this -- a *lot* of useless gunk in there.
    jenglish: OK:
    Colin: Which bits aren't useful?
    jenglish: Starting from the top:
    jenglish: TCL_VERSION, TCL_MAJOR_VERSION, minor version, patch level :  already available via other mechanisms ([info patchlevel], etc)
    Colin: Agreed, redundant.
    jenglish: TCL_CC:  Possibly useful, but probably not.  Consider binary distributions on commercial Unices: TCL_CC is probably an expensive native compiler (like IRIX's, which costs >$7K), and an extension builder might very well want to use 'gcc' instead.
    jenglish: TCL_DEFS: absolutely not useful.  Contains a truckload of -D flags that are only relevant to the core, not extensions, a handful that _used_ to be relevant to building the core years ago but are still in there just 'cause nobody ever bothered to take them out, and a bunch of autoconf gunk (-DPACKAGE_NAME, etc) that actually *conflicts* with what you need to build an extension.
    jenglish: Repeat: TCL_DEFS: absolutely not useful.
    jenglish: TCL_DBGX:  This must die.
    jenglish: TCL_{CFLAGS/LDFLAGS}_{DEBUG/OPTIMIZE}:  Possibly useful, but probably not; see TCL_CC, above.
    Colin: Ok, deleted _DEFS. You don't like DBGX?  It does make for some sticky naming issues.
    jenglish: Plus, the DEBUG/OPTIMIZE TEA stuff is a hairball to begin with.
    jenglish: TCL_SHARED_BUILD: Not useful.
    jenglish: TCL_LIB_FILE:  This one actually is useful.
    Colin: It's also present elsewhere, I think.
    jenglish: TCL_NEEDS_EXP_FILE:  can determine this from $tcl_platform(platform).
    jenglish: TCL_EXPORT_FILE_SUFFIX: Might have been useful in ages past; I don't think any modern Unices use export files anymore.
    jenglish: TCL_LIBS: Not useful for extensions.
    Colin: Ok, elided.
    jenglish: TCL_PREFIX: Useful, but already available via the TIP 59 stuff that's already in there.
    dgp: TCL_LIBS is useful for embedders.
    jenglish: Ditto TCL_EXEC_PREFIX.
    jenglish: TCL_SHLIB_CFLAGS, TCL_CFLAGS_WARNING: Possibly useful, but probably not; see TCL_CC, above.
    dgp: hmmm... or is that superceded by something else now?
    dgp: some TCL_BLAH_BLAH_LIB_SPEC ?
    jenglish: Ditto TCL_SHLIB_LD, STLIB_LD, etc:
    jenglish: TCL_SHLIB_SUFFIX: already available in [info sharedlibextension]
    jenglish: TCL_DL_LIBS, TCL_LD_FLAGS: See TCL_LIBS above  (dgp is right, this might be useful for embedders)
    jenglish: TCL_{CC/LD}_SEARCH_FLAGS: Don't think these are useful; I've never needed 'em anyway.
    jenglish: TCL_COMPAT_OBJS: Definitely not useful.
    jenglish: TCL_RANLIB: See TCL_CC, above.  Possibly useful, but probably not.
    jenglish: TCL_BUILD_LIB_SPEC:  almost certainly not useful;
    Colin: RANLIB not, because it only pertains to making .a file.s
    jenglish: TCL_LIB_SPEC:  This one might be useful for embedders.  Not for extensions.
    jenglish: TCL_INCLUDE_SPEC: Useful, but already available in the current TIP #59 database.
    jenglish: TCL_LIB_VERSIONS_OK: Don't know if this is useful or not.  It's part of a large and unnecessary hairball; better to avoid the hairball.
jenglish: TCL_SHARED_LIB_SUFFIX
the important part of this is in [info sharedlibext], the other part is the remainder of the hairball mentioned above.
    jenglish: Not useful.
    jenglish: Ditto TCL_UNSHARED_LIB_SUFFIX.
    jenglish: TCL_SRC_DIR: almost certainly not useful.  (Think binary distributions of the core).
    jenglish: TCL_PACKAGE_PATH: This one is useful.  It will also be superceded (hopefully!)  by the search path cleanup that others are working on now.
    jenglish: (so, not useful for long, one hopes).
    jenglish: TCL_SUPPORTS_STUBS:  Not useful.  Can be assumed constant ("true").
    jenglish: TCL_STUB_LIB_SPEC: This one is useful.  TCL_STUB_LIB_FILE, TCL_STUB_LIB_FLAG, TCL_STUB_LIB_PATH, TCL_BUILD_STUB_LIB_PATH, on the other hand,  are redundant and not useful, not needed, and redundant.  Plus redundant.
    jenglish: TCL_THREADS: this one is useful.  Also available via $::tcl_platform, so redundant.
    jenglish: So, is there anything left?
    Colin: That's the lot.  I'll plug those into the TIP, thanks.
    jenglish: Wait, wouldn't it be easier to list the stuff that *is* useful?  It's a much shorter list.
    Colin: However, your point about binary distributions being compiled on different hosts, and the values being inapplicable is a good one.
    jenglish: ... unless I've miscounted, the only thing that's actually useful for extensions is TCL_STUB_LIB_SPEC .
    dkf: for a bit
    Colin: jenglish, we can just about assume a compiler which understands -l -L -I and file names :)
    jenglish: Sorry, and TCL_INCLUDE_SPEC.
    jenglish: Take that back, you can derive TCL_INCLUDE_SPEC from the pkgconfig database.
    Colin: jenglish, the inclu.. yes.
    jenglish: Come to think of it, you can derive TCL_STUB_LIB_SPEC from that as well (though the computation is a bit more difficult due to TCL_DBGX and the TCL_LIB_VERSIONS_OK hairball)
    Colin: So that which is useful is not universally applicable, and that which is (etc)

rdt I wish you guys would _stop_ promoting the use of /usr/bin/env. Its going back to the same old "not working" style. You might as well use /usr/bin/wish or whatever. The program env is _not_ always located in /usr/bin. Go back to the exec magic & stop this.

SEH At work I run Tcl scripts on a half-dozen versions of Unix across many different OS versions. The only common denominator I've found among all the computers I must use is /usr/bin/env. Not even /bin/sh or /usr/bin/sh are as reliably there. What versions of Unix have you found that don't have /usr/bin/env?

rdt Well, I have several versions which have env located in /bin and one in which /usr/bin/env is a link pointing to the actual file in /usr/bin. Whats wrong with exec magic at [1] ? The "standard" _is_ /bin/sh, if your system doesn't have an sh compatible shell there it isn't UNIX compliant!

To help introduce tclConfig.sh, consider this top fragment from a typical one:
    # tclConfig.sh --
 .   #
    # This shell script (for sh) is generated automatically by Tcl's
    # configure script.  It will create shell variables for most of
    # the configuration options discovered by the configure script.
    # This script is intended to be included by the configure scripts
    # for Tcl extensions so that they don't have to figure this all
    # out for themselves.
    #
    # The information in this file is specific to a single platform.
    #
    # RCS: @(#) $Id: tclConfig.sh.in,v 1.17 2002/07/28 03:15:11 mdejong Exp $

    # Tcl's version number.
    TCL_VERSION='8.4'
    TCL_MAJOR_VERSION='8'
    TCL_MINOR_VERSION='4'
    TCL_PATCH_LEVEL='.4'

    # C compiler to use for compilation.
    TCL_CC='gcc -pipe'
        ....

[Explain salient characteristics.]

See also TEA, finding out tclconfig.sh

Category Package Category Porting