问题
Thanks to the comments, better understand the problem a bit. The variables:
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ echo 'puts $auto_path' | tclsh
/usr/share/tcltk/tcl8.6 /usr/share/tcltk /usr/lib /usr/local/lib/tcltk /usr/local/share/tcltk /usr/lib/tcltk/x86_64-linux-gnu /usr/lib/tcltk /usr/lib/tcltk/tcl8.6
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ echo 'puts $tcl_pkgPath' | tclsh
/usr/local/lib/tcltk /usr/local/share/tcltk /usr/lib/tcltk/x86_64-linux-gnu /usr/lib/tcltk /usr/share/tcltk /usr/lib/tcltk/tcl8.6 /usr/lib
thufir@dur:~/tcl/packages$
code:
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ ll
total 16
drwxrwxr-x 2 thufir thufir 4096 May 4 02:22 ./
drwxrwxr-x 6 thufir thufir 4096 May 4 02:22 ../
-rw-rw-r-- 1 thufir thufir 215 May 4 02:21 foo.tcl
-rw-rw-r-- 1 thufir thufir 1207 May 4 02:20 tutstack.tcl
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ cat foo.tcl
package require tutstack 1.0
set stack [tutstack::create]
foreach num {1 2 3 4 5} { tutstack::push $stack $num }
while { ![tutstack::empty $stack] } {
puts "[tutstack::pop $stack]"
}
tutstack::destroy $stack
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ cat tutstack.tcl
# Register the package
package provide tutstack 1.0
package require Tcl 8.5
# Create the namespace
namespace eval ::tutstack {
# Export commands
namespace export create destroy push pop peek empty
# Set up state
variable stack
variable id 0
}
# Create a new stack
proc ::tutstack::create {} {
variable stack
variable id
set token "stack[incr id]"
set stack($token) [list]
return $token
}
# Destroy a stack
proc ::tutstack::destroy {token} {
variable stack
unset stack($token)
}
# Push an element onto a stack
proc ::tutstack::push {token elem} {
variable stack
lappend stack($token) $elem
}
# Check if stack is empty
proc ::tutstack::empty {token} {
variable stack
set num [llength $stack($token)]
return [expr {$num == 0}]
}
# See what is on top of the stack without removing it
proc ::tutstack::peek {token} {
variable stack
if {[empty $token]} {
error "stack empty"
}
return [lindex $stack($token) end]
}
# Remove an element from the top of the stack
proc ::tutstack::pop {token} {
variable stack
set ret [peek $token]
set stack($token) [lrange $stack($token) 0 end-1]
return $ret
}
thufir@dur:~/tcl/packages$
thufir@dur:~/tcl/packages$ tclsh foo.tcl
can't find package tutstack 1.0
while executing
"package require tutstack 1.0"
(file "foo.tcl" line 1)
thufir@dur:~/tcl/packages$
to my understanding, I need to compile a list or map of where packages are.
回答1:
The problem is that Tcl is not finding the index file (which should be called pkgIndex.tcl
) for your package. If you had implemented the weather 1.0
package as a file weather.tcl
, then you'd probably be looking to have an index file something like this in the same directory:
package ifneeded weather 1.0 [list source [file join $dir weather.tcl]]
That says “to load version 1.0
of the weather
package, run this script” where the script is generated at runtime and binds $dir
in (which is a variable always defined in the context where package index loader runs package ifneeded
).
Once that's there, you need to allow Tcl to find the index file. This can be done by putting that directory or its immediate parent on the Tcl global auto_path
list; either do that inside your script before you load any packages (very useful for applications that have internal packages) or you can initialise that from outside of Tcl too by setting the TCLLIBPATH
environment variable. Note that the value of that variable is a Tcl list of directories, not a system path like env(PATH)
. This matters if you have backslashes or spaces in directory names, or if you want to have multiple elements on the list. Fortunately, you can usually avoid all of these issues in the case of adding a single directory as an environment variable, even on Windows, by using /
instead of \
and by following usual installation practice and not putting a space in names. When adding a path during application launch it's easier: you just use lappend
, perhaps like this (very early in your main script):
lappend auto_path [file join [file dirname [info script]] my_app_pacakges]
# If the script is in foo/bar.tcl then packages are in or below foo/my_app_packages
回答2:
result which runs:
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ tree
.
├── api
│ ├── pkgIndex.tcl
│ └── tutstack.tcl
└── main.tcl
1 directory, 3 files
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ cat main.tcl
lappend auto_path /home/thufir/tcl/foo/api
package require tutstack 1.0
set stack [tutstack::create]
foreach num {1 2 3 4 5} { tutstack::push $stack $num }
while { ![tutstack::empty $stack] } {
puts "[tutstack::pop $stack]"
}
tutstack::destroy $stack
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ cat api/pkgIndex.tcl
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script. It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands. When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.
package ifneeded tutstack 1.0 [list source [file join $dir tutstack.tcl]]
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ cat api/tutstack.tcl
# Register the package
package provide tutstack 1.0
package require Tcl 8.5
# Create the namespace
namespace eval ::tutstack {
# Export commands
namespace export create destroy push pop peek empty
# Set up state
variable stack
variable id 0
}
# Create a new stack
proc ::tutstack::create {} {
variable stack
variable id
set token "stack[incr id]"
set stack($token) [list]
return $token
}
# Destroy a stack
proc ::tutstack::destroy {token} {
variable stack
unset stack($token)
}
# Push an element onto a stack
proc ::tutstack::push {token elem} {
variable stack
lappend stack($token) $elem
}
# Check if stack is empty
proc ::tutstack::empty {token} {
variable stack
set num [llength $stack($token)]
return [expr {$num == 0}]
}
# See what is on top of the stack without removing it
proc ::tutstack::peek {token} {
variable stack
if {[empty $token]} {
error "stack empty"
}
return [lindex $stack($token) end]
}
# Remove an element from the top of the stack
proc ::tutstack::pop {token} {
variable stack
set ret [peek $token]
set stack($token) [lrange $stack($token) 0 end-1]
return $ret
}
thufir@dur:~/tcl/foo$
thufir@dur:~/tcl/foo$ tclsh main.tcl
5
4
3
2
1
thufir@dur:~/tcl/foo$
generating the config file:
thufir@dur:~/tcl/foo/api$
thufir@dur:~/tcl/foo/api$ tclsh
%
%
% pkg_mkIndex . *.tcl
%
% exit
thufir@dur:~/tcl/foo/api$
来源:https://stackoverflow.com/questions/61587687/cant-find-package-from-application-written-in-tcl