A package can contain other packages which makes it possible to organise them into hierarchies. The hierarchies can be arbitrarily deep and wide. The minimum number of hierarchy levels in any software project is two: one for the releases and another for the packages they contain. More levels can be added according to the needs of the project. A large project would typically subdivide the software into domains or categories, and it is quite natural for the package hierarchy to follow this structuring.
The release tools do however restrict the structuring only to an organisational aid: the identity of a package is defined by its name, not by its location in the hierarchy. While the path leading to a package is important and cannot be changed arbitrarily, it nevertheless is not used in determining the package's identity. In particular, packages mostly refer to each other solely by name; only the use directives in the PACKAGE files should refer to the location in the hierarchy.
We recall here that a package corresponds to subdirectory with certain special files in it. A nested package is simply an immediate subdirectory of the containing package and a hierarchy of packages is a normal directory tree.[1] The restrictions the release tools impose on the tree structure should not limit the development process much at all. Moreover, developers can deal with only parts of the tree at a time without replicating the entire structure in their working areas. This model also complies very nicely with CVS, as the directories the developers deal with are the same ones seen by CVS and the CVS commands operate on them the same they would on any other other directory tree.
Packages can be classified into two flavours, leafs that contain no other packages and composites that do. A leaf package can also be an indepedent package that stands completely on its own; a dependent package uses other packages and cannot be built without them. Another way of classifying packages is to call them organisational packages that have no purpose beyond that of containing other packages, and source code packages that are responsible for the products such as libraries and executables. In practise, it is best to map these one-to-one to composites and leafs, respectively--a package that contains source code seldomly should contain other packages and vice versa.
The reason for separating source and organisational packages from each other is rather practical. Suppose there was a mixed package. A developer that wanted to modify only the source part would have difficulty in checking only those parts out with CVS--not because it could not be done, but because it would be inconvenient. The task would probably require three or four checkout and update commands instead of just one. On the other hand, were the source part of the package to build a library, what would it mean for another (possibly nested!) package to depend on the providing package? That is, how would one separate dependency on the library from the dependency on the nested packages? For these reasons there are only few occasions where mixed packages are of any practical use. It is better to not use them, and the design rarely suffers from avoiding them.[2]
Figure 11-1, ``Example Package Tree'' presents an imaginary tree of five packages: offline, Graphics, Aravis, HBookTuple (details not shown), and EventDisplay (details not shown). Graphics is a subpackage of offline while the rest are subpackages of Graphics. The subdirectories Aravis and src inside Aravis are simple subdirectories.
Finally, there is one exception to the rule that a directory name always reflects the package name: official release directories are usually named after the release version, not by the name of the release package. This is convenient not only because it allows several releases to be made available concurrently in one directory, but also because the release package may not be in $CVSROOT; it could be for instance $CVSROOT/software/offline.
| [1] | It is not possible to have, for instance, a package directory P containing a normal subdirectory D that contains a package subdirectory Q--either the latter ought to be a direct subdirectory of P or D ought to be made a package. |
| [2] | There is one quite good use for the mixed packages: examples. If your development culture calls for examples to be kept within the packages and not in a separate ``examples area,'' it is probably convenient to make the example programs nested packages. Developers who want only the examples can check them out without the containing packages while developers would normally want the examples anyway to make sure they work correctly after the package has been changed. |
| [1] | These instructions do not apply to creating the release package. That process is described in Section 22.1, ``Creating The First Release''. |
| [2] | As a matter of the fact, you can execute configure and make immediately after the first lot of commands. Not much will happen, though. |
| [1] | Even if you check out only selected subdirectories, you may end up getting the directories later against your will. In particular, this will happen if you use the -d option with the CVS update command (see Section 7.3, ``Customising CVS''). This makes it harder to check out and update vertical slices of the hierarchy. Thus, you may want to stay alert to which CVS commands you execute where and with what options when working with such partial structures. |
| [1] | make calls them ``phony'' targets. |
| [2] | Subdirectory targets always take precedence over package targets: defining a subdirectory target hides all information about packages with the same name. |