Version 8 of pkg_mkIndex pitfalls

Updated 2002-08-22 20:31:55

Some things to beware of when using pkg_mkIndex:

If a script in the library directory fails for any reason when it is sourced, then any subsequent package provide statements in that script will not be reflected in the pkgIndex.tcl file. Probably the most common cause for failure is that a script calls package require for a dependant package which cannot be loaded. For example, package scripts which package require Tk will fail (on Unix) if the $DISPLAY is not set.

A more subtle problem: package scripts which package require other packages defined by scripts in the same directory will fail the first time you run pkg_mkIndex, but may succeed the second time. If there are many package interdependencies, it may be necessary to "iterate until convergence" before a working pkgIndex.tcl comes out.


DGP interrupts Can you provide an example? Goodness knows I've been a vocal critic of pkg_mkIndex, but it should not suffer from the problem as described above. It takes care to stub out any package requires for just that reason.


JE replies What I wrote earlier is of course utterly wrong. DGP is right: pkg_mkIndex does stub out package requires, so those won't cause the autoindexer to fail.

What does cause it to fail is if the required package defines namespaces or procedures which the file being indexed later uses at top-level. For example: if foo.tcl contains:

    namespace eval foo { ... }
    proc defineFoo {name args} { ... }
    package provide foo 1.0

and bar.tcl contains:

    package require foo 1.0
    defineFoo barFoo ...
    package provide bar 1.0

then the call to defineFoo will fail and the autoindexer will abort. If bar.tcl tries to use the namespace foo at top-level it will also fail.


To avoid this problem, you should call package provide before doing anything else.


DGP rebuts Just my opinion, but I think your package file should serve the package user first, and consider the indexer's needs less important. The user wants to know that when package provide foo returns a version number, that that version has been fully loaded. That implies that package provide foo $version should come last.


JE replies Good point. I still like to put it at the beginning so that the relevant interface data -- what package is provided, what packages are required -- comes first.


It is a very good idea for package authors to include prebuilt pkgIndex.tcl files in the distribution instead of having end-users run pkg_mkIndex as part of the installation process. There are too many things that can go wrong. The canonical TEA build structure (as of May 2002) uses pkg_mkIndex to build the package index as part of the installation process. Don't do that.

More often than not, pkg_mkIndex is overkill anyway: for simple packages it's just as easy to create a pkgIndex.tcl (or pkgIndex.tcl.in) by hand.

The biggest problem with "doing it by hand" is maintenance of a version number--and this is a serious practical nuisance. Several interesting proposals for automation are floating around. As of the weeks leading up to the 2002 Conference, though, packaging guru DGP says, "If you want to follow my example instead of advice, place a comment where the version number is defined reminding you of the other places that must be kept in sync."