pkgmake – make a Solaris SVR4 package


pkgmake [options] filesdir [destdir]


pkgmake is a simple utility for making Solaris SVR4 packages. It takes a directory structure containing the files you want to include in the package and produces a Solaris SVR4 package from it, resulting in a .pkg file suitable for distribution and installation.

filesdir must contain the files to install, in their final hierarchy, with their final permissions. This is typically a temporary directory created by "make DESTDIR=... install".

In addition to the files, a pkginfo file must be present in filesdir. This file specifies the package's name, version and so on (see example below).

There may also optionally be a depend file listing other packages which are required dependencies (see example), a compver file listing versions of the package which this version may replace while maintaining compatibility (see example), and a copyright file displayed during installation.

Finally, there may be scripts named request, checkinstall, preinstall, postinstall, preremove and postremove. The meaning of the scripts should be self-evident from their names, except for request which is used to ask the user for information during installation, and thus is rarely used in practice (because any form of interaction interferes with automated installations).

A prototype file is not required, but may be provided if you wish. Normally the files in filesdir are used to generate a prototype file automatically. You should only need to provide one if you're doing something very unusual.

Each of these files may have a filename extension if you wish (.sh for the scripts, .txt for the rest).


-l | --long-name
Generate a package file using the full, long package name, eg: ACMEcooltool-1.2.3-solaris-sparc.pkg. The default is to generate a shortened filename which does not include the company prefix, eg: cooltool-1.2.3-solaris-sparc.pkg. The actual package name remains in its full form either way, this only affects the filename.
-o | --owners
Keep the ownership of the files and directories exactly as is. Normally, pkgmake produces a package where files are installed owned by root and system directories such as /usr and /var have their ownership left unchanged. That's the desired behavior for the vast majority of packages. Use this option if you need to have special ownership for your package's files once installed.
-v | --verbose
Be verbose, display the output of underlying commands.
-V | --version
Print the version number of pkgmake.


A typical use from a shell is...

$ make DESTDIR=installtemp install
$ cp pkginfo installtemp
$ pkgmake installtemp
$ rm -rf installtemp

Another typical use is in a Makefile, allowing package creation to be part of the build process via "make package"...

INSTALLTEMP = installtemp

package: all
    - rm -rf $(INSTALLTEMP)
    cp pkginfo $(INSTALLTEMP)
    pkgmake $(INSTALLTEMP)
    rm -rf $(INSTALLTEMP)

A typical pkginfo file looks like...

NAME="Cool Tool"
DESC="Program to make you really cool."

Most of the fields in pkginfo are self-explanatory. Values for ARCH are the outputs of uname -p (eg: sparc, i386), or the word native which will be replaced by the output of uname -p, or the word all for hardware-independent packages, such as scripts and documentation.

A typical depend file looks like...

P   SUNWpng     Portable Network Graphics library
P   SUNWzlib    Zip compression library

Be careful if you add version information to your depend file (see depend(4)), because not all packages have accurate backward-compatibility information (compver files). You might end up with problems in the future because you depend on an older version of a library when a newer, perfectly compatible version is installed but doesn't list itself as being backwardly compatible with the older version number. This is especially true for 3rd-party packages. It's also not necessary to list any essential parts of the operating system, such as SUNWcsr and SUNWcsu, since they must be installed to be running Solaris in the first place.

A typical compver file looks like...


Normally a compver file will be generated automatically using the industry-standard 1.2.3 style of version numbering, including 1 and 1.2 style shortenings. You don't need to provide one unless either your package's version numbering scheme is unusual (eg: uses numbers over 99.99.99, uses dates/letters other than the standard 1.2b3 or 1.2.3b4 style for alpha/beta versions), or your package does not offer backward compatibility with all previous versions.


Scripts such as postinstall should use the BASEDIR env var to refer to files and directories, because the package may be being installed into a different root directory structure from the one the pkgadd command is being run in. In other words, BASEDIR is the root of the target filesystem, which may not necessarily be /. In fact, during JumpStart or Live Upgrade operations it definitely won't be.


Package upgrades are handled in a very inelegant fashion on Solaris. Rather than simply upgrading a package to a newer version in-place as most people would expect, on Solaris there are two approaches, both somewhat less than ideal...

pkgadd then pkgrm
The natural approach for most people is to simply install the new version of the package using pkgadd(1M). Because this will write the new files over the originals, it causes pkgadd(1M) to request confirmation, saying that there are "conflicting" files, which is ugly but acceptable.
After installation of the new version, however, there will now actually be two instances of the package installed on the system (the old and the new), at least as far as the package database is concerned. I kid you not – there really will be two instances of the package installed, even though in terms of files on the system the new versions will have completely replaced the old ones. The new package will be under the package name followed by a dot and an instance number (2, 3 etc). This is quite unexpected for most people, who would sensibly assume the new version had replaced the old one. Not so.
The old package should now actually be removed with pkgrm(1M), which will leave the new files in place because they belong to the new package.
pkgrm then pkgadd
The "better" approach is to first remove the existing package with pkgrm(1M), then install the new version with pkgadd(1M). Unfortunately, this will break any dependencies (temporarily), causing warnings to be issued during the pkgrm(1M), which is not a good installation experience. Nevertheless, this is actually the recommended approach.

Exactly why Solaris hasn't added the "feature" of being able to upgrade to a new version of a package in one step is a mystery which remains unsolved. Solaris could learn a lot from Linux in this area.


pkgmake is not intended to cover every possibility, and does not expose every last ounce of the package format's capabilities. It's intended to provide a simple utility suitable for producing the 90% of packages which are just a bunch of files and optionally some pre/post-install scripts. For complete access to all of the SVR4 package format's capabilities, use the lower-level pkgmk(1) and prototype(4) facilities directly.


pkginfo(4), depend(4), compver(4), pkgadd(1M), pkgrm(1M), pkginfo(1M), pkgchk(1M), pkgmk(1), prototype(4)



Copyright © 2003-2018 Lighterra – Open Source (MPL & LGPL)


Jason Robert Carey Patterson <>