Forum OpenACS Q&A: New twist on age old 'package require' problems

Request notifications

I want to use TclCurl from AOLserver 3.3+ad13 and OpenACS 4.6.3. Naturally, this runs into the age-old AOLserver 3.x package require problems.

That old thread has useful advice, but it seems incomplete. I tried this:

global tcl_version tcl_pkgPath tcl_library tcl_platform auto_path 
set tcl_pkgPath {/usr/lib} 
set tcl_library [file join $tcl_pkgPath "tcl${tcl_version}"] 
set tcl_platform(platform) {unix} 
set auto_path [list /usr/lib/tcl /usr/lib] 
source [file join $tcl_library init.tcl] 
source [file join $tcl_library package.tcl] 

package require TclCurl 
And got the expected error:
variable "errorInfo" already exists
    while executing
"global errorInfo errorCode"
    (procedure "template::adp_parse" line 36)
    invoked from within
"template::adp_parse [file root [ad_conn file]] {}"
    (procedure "adp_parse_ad_conn_file" line 7)
    invoked from within
(Note it makes no difference which Tcl package I require, 'package require http' or 'package require oratcl' all fail in exactly the same way.)

I still don't understand this part, but I commented out the offending lines in /usr/lib/tcl8.3/init.tcl as Dave B. suggested:

# TODO:  --atp@piskorski.com, 2003/10/07 09:00 EDT 
#set errorCode "" 
#set errorInfo "" 
But the 'package require' then still gives this error:
invalid command name "tclPkgUnknown"
    while executing
"tclPkgUnknown TclCurl {}"
    ("package unknown" script)
    invoked from within
"package require TclCurl"
    invoked from within
What gives? Does anyone understand this?

Collapse
Posted by Andrew Piskorski on
Does it matter that TclCurl needs to load a C module as well as Tcl code?

I also tried to create a genuine "nscurl" AOLserver module based on TclCurl, but since I couldn't get TclCurl to build at all that didn't get very far.

Note that TclCurl ships with a file doc/aolserver.txt which purports to explain how to use TclCurl with AOLserver 3.x, but it is cryptic and doesn't seem to make sense. Specifically, it mentions a file "modules\tcl\am\packages.init.tcl", but AFAICT no such file nor any simiar file exists in AOLserver 3.3+ad13.

Here are those TclCurl doc/aolserver.txt instructions:

There are a number of issues with namespaces in AOLserver 3.x, which I believe
are fixed in 4.0, which should be released within a few months. But in the
meantime this is what we've had to do for AOLserver 3.2 on Windows 2000.

Alex Khassin


1.  Under [ns_library shared] directory, create a directory called
    packages.

2.  Register this directory as a Tcl module in nsd.tcl:
        ns_section "ns/server/${servername}/modules"
        ns_param   packages Tcl

3.  Place each package into a subdirectory of the same name as the
    package name (i.e. [ns_library shared]/packages/TclCurl)

4.  Copy S:\NaviSoft\Server\modules\tcl\am\packages.init.tcl to the
    [ns_library shared]/packages directory and rename to just init.tcl

5.  Under AOLserver 4.x (and hopefully in 3.5.x) add to the bottom
    of this file appropriate commands to register each package:
        _am_pregister shared <packageName>

6.  In your code, when you need to use a particular package, instead
    of 'package require <packageName>', execute 'am_pinit <packageName>'

7.  This will use the existing package registration under AOLserver
    4.x and, under AOLserver 3.2, it will first register the package
    in this interpreter and then use it.

8.  This is necessary because in AOLserver 3.2, namespaces aren't
    properly imported into child interpreters.

    Currently dnscrub.com is set up like this for TclCurl and it works.

    Example usage:

        am_pinit TclCurl
        curl::transfer -url http://am.net/index.htm -file d:/test.htm

FYI, the code for am_pinit and _am_pregister procs:

        proc am_pinit {package} {
        # AOLserver 3.2 package/namespace-handling is broken
        # (namespace/packages don't get imported into child interpreters)
        # so use this workaround proc instead of 'package require' to
        # load the package into the current interpreter
        # (this is obviously slower than copying from master interpeter)
        # Package names are case-sensitive!
        # Returns the version of the loaded package
            set library shared
            if {[lsearch -exact [package names] $package] == -1} {
                ns_log Notice "packages: registering $library/$package"
                _am_pregister $library $package
            }
            package require $package
        }
         
        proc _am_pregister {library package} {
        # Registers the package. library is 'shared' or 'private'
            set dir [ns_library $library]/packages/$package
            source $dir/pkgIndex.tcl
        }
Collapse
Posted by Dave Bauer on
Andy,

I have done something similar and it should work.

Find your shared tcl library. For OpenACS its /web/opeancs/tcl

Under that create the packages subdirectory etc.

Under the modules section of your confile file setup a tcl module called packages like it says in the isntructions.

AOLserver should load anything under packages.

If you can, upgrade to 4.0 :) Its alot easier.