[ Team LiB ] Previous Section Next Section

Using Packages

Each script file in a library declares what package it implements with the package provide command:

package provide name version

The name identifies the package, and the version has a major.minor format. The convention is that the minor version number can change and the package implementation will still be compatible. If the package changes in an incompatible way, then the major version number should change. For example, Chapter 17 defines several procedures that use the HTTP network protocol. These include http::geturl, http::wait, and http::cleanup. The file that contains the procedures starts with this command:

package provide http 2.4

Case is significant in package names. In particular, the package that comes with Tcl is named http — all lowercase.

More than one file can contribute to the same package simply by specifying the same name and version. In addition, different versions of the same package can be kept in the same directory but in different files.

An application specifies the packages it needs with the package require command:

package require name ?version? ?-exact?

If the version is left off, then the highest available version is loaded. Otherwise the highest version with the same major number is loaded. For example, if the client requires version 1.1, version 1.2 could be loaded if it exists, but versions 1.0 and 2.0 would not be loaded. You can restrict the package to a specific version with the -exact flag. If no matching version can be found, then the package require command raises an error.

Loading Packages Automatically

The package require command depends on an index to record which files implement which packages. The index must be maintained by you, your project librarian, or your system administrator when packages change. The index is created by the pkg_mkIndex command, which puts the index into a pkgIndex.tcl file in each library directory. The pkg_mkIndex command takes the name of a directory and one or more glob patterns that specify files within that directory. File name patterns are described on page 122. The syntax is:

pkg_mkIndex ?options? directory pattern ?pattern ...?

For example:

pkg_mkIndex /usr/local/lib/welchbook *.tcl
pkg_mkIndex -lazy /usr/local/lib/Sybtcl *.so

The pkg_mkIndex command sources or loads all the files matched by the pattern, detects what packages they provide, and computes the index. You should be aware of this behavior because it works well only for libraries. If the pkg_mkIndex command hangs or starts random applications, it is because it sourced an application file instead of a library file.

The package index, pkgIndex.tcl, is sourced in response to a package require command. The index instructs the package loading mechanism how to define the package. By default, source or load commands are specified so that packages are defined immediately as a side effect of package require. This is called direct loading. However, the original package index system used a deferred loading scheme layered on the auto_load mechanism and the unknown command hook, which is described on page 178. If you want deferred loading, use the -lazy option to pkg_mkIndex. The default behavior of pkg_mkIndex switched from -lazy to -direct in Tcl 8.3. The pkg_mkIndex options are summarized in Table 12-1.

Table 12-1. Options to the pkg_mkIndex command

-direct

Generates an index with source and load commands in it. This results in packages being loaded directly as a result of package require. This is the default starting with Tcl 8.3.

-lazy

Generates an index that populates the auto_index array for deferred loading of commands. This behavior was the default prior to Tcl 8.3.

-load pattern

Dynamically loads packages that match pattern into the slave interpreter used to compute the index. A common reason to need this is with the tcbload package needed to load .tbc files compiled with TclPro Compiler.

-verbose

Displays the name of each file processed and any errors that occur.

Packages Implemented in C Code

The files in a library can be either script files that define Tcl procedures or binary files in shared library format that define Tcl commands in compiled code (i.e., a Dynamic Link Library (DLL)). Chapter 47 describes how to implement Tcl commands in C. There is a C API to the package facility that you use to declare the package name for your commands. This is shown in Example 47-1 on page 698. Chapter 37 also describes the Tcl load command that is used instead of source to link in shared libraries. The pkg_mkIndex command also handles shared libraries:

pkg_mkIndex directory *.tcl *.so *.shlib *.dll

In this example, .so, .shlib, and .dll are file suffixes for shared libraries on UNIX, Macintosh, and Windows systems, respectively. You can have packages that have some of their commands implemented in C, and some implemented as Tcl procedures. The script files and the shared library must simply declare that they implement the same package. The pkg_mkIndex procedure will detect this and set up the auto_index, so some commands are defined by sourcing scripts, and some are defined by loading shared libraries.

If your file servers support more than one machine architecture, such as Solaris and Linux systems, you probably keep the shared library files in machine-specific directories. In this case the auto_path should also list the machine-specific directory so that the shared libraries there can be loaded automatically. If your system administrator configured the Tcl installation properly, this should already be set up. If not, or you have your shared libraries in a nonstandard place, you must append the location to the auto_path variable.

    [ Team LiB ] Previous Section Next Section