2.2. Basic Package Usage

Having learned how to get started with ComPact, you are ready to proceed with one of its core functionality, the management of the building and shipment of libraries and programs on the basis of software packages, build management for short. The following example, though small, teaches you most of the principles of that. First of all the creation of package collections and packages is described. Then the structure of a newly created package is considered. The command pkgm -build, which is used to initiate the compilation of a library or program, is introduced afterward. Further still, the command pkgm -ship, which is used to install libraries and programs, is introduced. An impression of how one imports installed libraries into other packages is given at the end of this section.

Package Description  : A pervading theme of this section, the next one, and indeed of Chapter 3-Chapter 7 is the role of package description files. These package elements declare package imports, header and source code files, libraries and programs to be generated, C/C++ defines, and what is exported of that. Their format is given by a simple-to-learn language, which is appropriately called the package description language, or PDL. Large parts of its syntax and semantics are described in Chapter 4. The picture is completed by specific additions that can be found in Chapter 5-Chapter 7.



2.2.1. Creating Collections and Packages

Package collections, collections for short, facilitate the handling of large numbers of packages. There is, in fact, never any package that does not belong to a collection. So you must get hold of a collection before you can create a package. There are two possibilities of doing that:

  1. Checking out an existing one from the version control repository.

  2. Creating a new one.

We postpone taking account of the first option to the beginning of Chapter 7, where the entire version control mechanism is described in detail. As for the second option, there is creation command, which has the format ( -newcollection | -newcol | -newc ) <collection_name> We suggest you use it to create a new, empty collection. The name does not matter unless ComPact informs you that it is already in use. Moreover, the version control system will ask you for a log message, possibly by invoking an editor. Once this process is finished, you should see the following confirmation:
   !!! warning: undefined package: no package root
   new collection <collection name> created and put under
   version control
The collection, then, should appear as a sub-directory, and its being under version control should reveal itself by the presence of a sub-sub-directory. This directory's name should be the same as that of the version control system your installation works with. The system known as CVS is currently the only supported one.

Note: Never touch any directory that has been created by the version control system.

Version Control: Having mentioned version control a few times, we would like to point out that you can use ComPact almost without taking notice of this part of its functionality. That what is mentioned in this section is everything you need to be aware of. The situation is not much different if you employ the version control repository for storage purposes. Just make sure that you leave untouched each directory the version control system has created; the directory name is always as explained above.



We continue with the command used for creating new packages. Its format is ( -newpackage | -newpkg | -newp ) <package_name> and it must be given so that the current working directory is a collection directory. The new member of that collection, then, appears as a new sub-directory. We suggest you add a package to the collection from the preceding step. You might want to choose the name MessageUtil, since it fits one of the two packages making up the example to be considered in the remainder of this section.

2.2.2. Package Structure

The directory structure of the newly created package is shown below, as is the purpose of each individual package element. Obviously, it is assumed that CVS is the underlying version control system. You might also note that the package description file is always called PkgDesc. Further still, the sub-directories inc and src are to contain header and source code files, and the sub-directory doc is the place where documentation is to be kept. The top-level is called the package root directory.

Table 2-3.

MessageUtil / CVS / version control directory
  / PkgDesc package description file
  / doc / documentation directory
  / inc / header directory
  / src / source code directory


A package comprises everything that is needed to build one or more libraries and/or programs with the exception of any imported libraries, header files, and defines. Moreover, it contains the libraries and/or programs itself once they have been built. As for the package MessageUtil, this one is intended to export a library messageutil, which contains a simple procedure that can be used to print simple text messages. C/C++ necessitates a header and a source code file for such purposes. So you may create a messageutil.h and a messageutil.c according to the scheme below.



It remains to edit the package description file so that ComPact is able to recognize what is in the package and, at the same time, what is to be built. In this case the scheme is



Front End vs. Back End  : As the PkgDesc should be self-explanatory, suffice it to stress its straightforward, purely declarative format. Knowledgeable readers might compare this simplicity with the complexity that may be involved in makefiles, even if the situation is as simple as in our example. The reason for this difference is that ComPact has both a front end and a back end. The former is made up mainly of the command interface and the package concept; the latter has actually already been mentioned because it hides all TPC-dependencies that are not package-specific (cf. Section 2.1). Makefiles mix up these aspects so that they become indivisible.

Note: Contrary to makefiles, ComPact has both a front end and a back end.



2.2.3. Building

You might instantly proceed with typing pkgm -build which is the command to compile and link a target, that is, a library or program. Like many other commands, it determines the package in question from the current working directory.

The ensuing directory structure should have the appearance shown below. It exhibits three automatically generated objects, namely the files PkgDep and PkgImp, and the directory whose name is that of the current TPC. For the moment, only the directory is of immediate interest because it contains the target.

Table 2-4.

MessageUtil / CVS /  
  / PkgDep dependency information
  / PkgDesc  
  / PkgImp package imports
  / doc /  
  / <TPC_name> / derived files (object files,
    libraries, programs, and others)
  / inc /  
  / src /  


Source Files vs. Derived Files  : It is indeed very helpful to keep in mind the distinction between source files -- C/C++ source code and header files, files that contain documentation etc. -- and derived files -- the PkgDep, the PkgImp, libraries, programs, and everything else contained in automatically generated, TPC-dependent directories. Source files are, of course, always created by the user; derived files are created by ComPact either directly or indirectly by invoking compilers, linkers etc. A central part of ComPact's functionality, then, consists of dependency computation on the basis of C/C++ include directives. The result is stored in the PkgDep, and is mainly used for speeding up the process of compilation and linkage: Whenever a derived file is to be (re-)created, then the dependency graph is traversed to spare as many compilations as possible. Applied to large packages with many components, this (well-known) technique yields one considerably gains in productivity.



2.2.4. Shipping

Pools  : Once the message utility library is built, it must be shipped to a standardized location so that it is accessible elsewhere. ComPact uses pool directories for this purpose, namely local pools, project pools, and global pools. The idea is that these storages spaces are respectively associated with individual developers, projects, and departments or companies. They are declared in a ~/.compactrc or ~/compact/compactrc, and ComPact searches them in the following order:

local pool -> project pool -> global pool

The pragmatics of the pool concept is as follows:
  • There is a unique global pool. Its role consists of storing libraries to be shared throughout all development activities of a department or company. For example, standard data types such as linked lists could be made accessible in this way.

  • Predictably, the role of project pools consists of storing project-specific libraries.

  • Each developer maintains one or more local pools within his or her own work space. (S)he uses these repositories for working on libraries until they are ready for release on a project-wide or even global scale.

Finally, the search order allows projects and developers to work on libraries without disturbing the use of earlier versions by other projects or developers. All what needs to be done is to maintain development and stable versions on different levels.



We suggest you create a local pool in your work space and declare it in a personal ~/.compactrc or ~compact/compactrc (cf. Section 2.1.2). Afterward, you could proceed with typing pkgm -ship local which is the command to ship a target to the local pool. It must be given in the same fashion as pkgm -build. ComPact will then ask whether you want the shipment be tagged as d0.0.0, the current development version. The version control system actually demands a version, so the easiest thing to do is answering with typing yes.

2.2.5. Importing

We conclude this section with a second package, which imports MessageUtil. You may add it to the same collection, choosing the name MessageUtilTest since it contains a test program. The scheme for filling it in is

the program messageutiltest is built as soon as you type pkgm -build, and can then be found in the automatically created sub-directory whose name is the same as that of the current TPC. Note that one must state the version of the library messageutil that is to be imported. Moreover, we would like to point out that a test program does not normally deserve its own package. It would have been more in line with standard practice if we had suggested that messageutiltest.c be made part of MessageUtil. This approach would have meant that the package has more than one target, namely the library and the program. Yet, multiple targets are supported by ComPact. We have suggested a two-package approach because of didactical reasons.