Table of Contents

  1. Solaris package creation walkthroughs
  2. Mechanics of Solaris/SysV pkg creation
    1. The prototype file
    2. Package control files
      1. pkginfo definitions
      2. depend definitions
      3. copyright file
    3. Boot scripts
    4. Install/Remove scripts
      1. preinstall/postinstall scripts
      2. preinstall/postinstall scripts, and ZONES/jumpstart
    5. How to create the package file
    6. How to create the package file without root access
      1. "direct from build tree" method
      2. fakeroot method
    7. Resources
      1. Template archive
      2. Signing up

Solaris package creation walkthroughs

The impatient will probably just want to dive into a direct "walk-through" of how to create packages for opencsw. We aim to please, with two alternative walkthrough guides: However, you should still read the rest of this page to better understand what is going on under the covers.

Mechanics of Solaris/SysV pkg creation

The prototype file

SysV(Solaris) packages are controlled by a 'prototype' file, that defines which control files, datafiles, and directories will be contained in the package. A sample prototype file will look like
i pkginfo
i depend
i copyright
d none /opt/csw/bin
f none /opt/csw/bin/links
The "i" is a funny way of saying "this is a control file". Other entries are for "normal" files and directories. Note that the standard ownership for all files and directories, is:
owner=root, group=bin
There is a SysV pkg convention, that says you can default the definitions with use of "? ? ?", to accept whatever permissions on a file or directory are there already.
This convention should only be used for directories that are expected to exist already, and are outside of both /opt/csw and /etc/opt/csw, such as "/etc/init.d". For all directories under a "csw" tree, the standard of "0755 root bin" should be used.

Exceptions to this are if there is a specific need to have other ownership/group settings, or if the directory is guaranteed to already be created by another package it depends on (such as CSWcommon). In which case, the line for the directory in the prototype file may be omitted altogether.

Package control files

pkginfo definitions

At minimum, your pkginfo file should contain the following information:
PKG=CSWxxxx
NAME=shortname - Long name after dash
ARCH=("sparc", "i386", or "all")
CATEGORY=("application" or "system")
VERSION=x.y.z
VENDOR=url://where.you.got.source packaged for CSW by Your Name
HOTLINE=http://www.opencsw.org/bugtrack/
EMAIL=yourlogin@opencsw.org
DESC=[Optional extra info about software. Omit this line if you wish]
 
These fields are used by scripts to generate catalogs and things, so it is VERY IMPORTANT that you stick to the above format. Please note that "shortname" should be a single lowercase word. Also be sure that what you pick for PKG is going to last forever, because changing it is a very messy thing.

Note that you do not have to set ARCH in the pkginfo file itself: You can set it on the command line when you create the package, with "pkgmk -a". [or, the "createpkg" utility will do it automatically for you]. See the examples lower down for details.

Please note that whatever you put in the DESC field, will be exactly how the package is listed in the packages listing. If you do not wish to provide a customized value, it will fall back to whatever you have as the "long name" in the NAME field.

Final note: Please do not use any apostrophe in the fields. (It makes putting the info in a database trickier). Especially do not use "GNU's xyz". Typical usage; "GNU emacs", not "GNU's emacs".

depend definitions

If your package depends on certain shared libraries being installed, it should have a 'depend' file specified. "man depend" for format of the file. You will almost always need a depend file. Generally speaking, it will have entries like the following:
  P      CSWgtk  GTK - The GIMP Toolkit
  P      CSWglib GLIB - Library of useful routines for C programming
If any packages in the depend file do not begin with "CSW", or "SUNW", go and read the "Build standards" section of this document.

EVERY SINGLE DYNAMICALLY LINKED LIBRARY used by your package, must have an appropriate entry in your depend file.

Generally speaking, it is best to use Solaris standard libraries and utilities. Unless there is an overriding reason, use the Sun ones. For example, unless there is a real benefit to using ncurses over curses, use the system standard curses library.

Many GNU programs use GNU gettext, and refuse to use Solaris standard gettext. Therefore, you should probably install CSWggettext, and declare a dependancy on it, for many programs, due to linkage of /opt/csw/lib/libintl.so.2

Declaring a conflict in the depend file

In very very very VERY rare circumstances, a package will declare a 'conflict' with another package. This is only done in circumstances where it is neccessary to automatically "clean up" an old, obsolete, "bad" package, that has a obsolete PKGname that is not 'upgrade'able. There should never be conflicts between two "current" packages.
Unlike the traditional pkgadd/pkgrm usage, (where a conflict may mean that you should decide whether you want one, or the other of the two packages), a conflict definition from a opencsw package, means that the older "conflicted" package should always be removed.

Because of this, pkg-get will, when installing a new package, automatically attempt to remove any other package that the new package has declared a conflict with.

copyright file

Every package should have a basic copyright file detailing the author's intents.

Boot scripts

Some packages need boot scripts (auto-start scripts in /etc/rc*.d/ ). Some may only sometimes need boot scripts. It it up to the packager to decide whether the software is important enough to merit always starting it at boot-time or not. You should carefully consider which one is correct for your package.

Two opposite examples, are apache and rsync. Apache's sole purpose in life is to be a webserver. It makes no sense to install it, if you do not want it running as a demon. rsync, on the other hand, is commonly run manually, and only in certain cases is it desirable to run it as a demon. Correspondingly, CSWapache directly installs scripts in /etc/*, whereas CSWrsync does not.

If you choose to not to always start a demon at boot time, you should probably provide a sample boot-time script, in either the /opt/csw/share/progname/, or the /opt/csw/share/doc/progname/ directory.

If you do want to always start a demon, you will most likely want to create boot-time scripts the same way, whether you decide to create a relocatable package, or an absolute path package (see lower down for details). Here is an example of how you would do that, taken from CSWapache.

The following assumes that you have a 'pkgs' directory tree in your home directory where you keep pkginfo files, and other files relating to each package.

f none /etc/init.d/cswapache=/export/home/phil/pkgs/apache/cswapache 0744 root sys
s none /etc/rc3.d/S50cswapache=../init.d/cswapache
s none /etc/rc0.d/K16cswapache=../init.d/cswapache
s none /etc/rc1.d/K16cswapache=../init.d/cswapache
s none /etc/rc2.d/K16cswapache=../init.d/cswapache
s none /etc/rcS.d/K16cswapache=../init.d/cswapache

Note that there are links for both 'S' and 'K' names, which means the script must handle both 'start' and 'stop' arguments.

Nice start scripts will check for the presence of a config file, and not start the demon if it is not present.

Install/Remove scripts

Packages that need scripts to run when pkgadd or pkgrm are called, are the most complex to put together. They are also a potential security risk. Some people feel uncomfortable about pkgadding third party stuff that requires an anonymous script running as root. So if possible, it is best to avoid install scripts, if you can still stick with the "deliver a fully functional package" motto.

When they are required, however, very strict guidelines need to be followed.

For example, scripts should be written to be paranoid about the state of config files. A package may be in a partially installed state ; your script may be running for the second time on the same machine.

Additionally, when packaging demons, be aware of the fact that the demon may STILL BE RUNNING. Do not do anything that could potentially break services.

preinstall/postinstall scripts

Custom preinstall/postinstall scripts (and any other pkg scripts!) should be aware of altered root locations. There are two reasons why the "root" directory may have been changed:
  1. You have made a relocatable package, and the BASEDIR has been changed by the installer
  2. The package is being installed with "pkgadd -R /somepath" (most commonly as part of jumpstart, or possibly a "live upgrade")
Sometimes, both can be in effect.
For the "-R /somepath" case, you only need to prefix all your file access with $PKG_INSTALL_ROOT. Example:
 grep username /etc/passwd
# becomes
 grep username $PKG_INSTALL_ROOT/etc/passwd
 #  (except you should probably use "getent passwd username" instead! )
If you have a relocatable package (one that has relative paths, without a leading '/', in your prototype file), then you should instead use the $BASEDIR variable. Interestingly, this variable gets automatically adjusted for use of -R. Thus, if the normal "base" for your package files is /opt/csw, but the user is installing in a jumpstart environment, AND they've decided to override the base to be /opt/csw-altdir, you dont have to worry about the -R usage. You can just use the normal BASEDIR style handling, and it will be taken care of either way, as follows:
# command-line, but inappropriate usage:
# cp /opt/csw/etc/yourprog.CSW  /opt/csw/etc/global.conf.file
# jumpstart-clean usage:
 cp $BASEDIR/etc/yourprog.CSW  $BASEDIR/etc/global.conf.file

preinstall/postinstall scripts, and ZONES/jumpstart

Sometimes, the package will be added with the equivalent of "pkgadd -R /somepath". This can happen both for jumpstart type installs, and also with zones.

For zones, packages will most commonly get added "normally", if the zone happens to be active(running). However, if the zone is NOT running, it will be automatically started up in "administrative state". This means that no demons will be running, and its filesystems will be mounted under /a, rather than / . Thus, proper use of $PKG_INSTALL_ROOT or $BASEDIR, is important for zones as well as jumpstart installs.

This can also be a good way to test out if your package works cleanly for jumpstarts, even if you dont have a jumpstart server! Create a zone, make sure it runs properly, then "zoneadm -z zone halt", and try to pkgadd it to the global zone. The system should automatically do its special magic and add it to the other zone as well, via booting the zone in "administrative mode"


How to create the package file

AFTER you have created pkginfo, depend, and copyright files, you have to generate the "normal" part of the prototype file. You can do this by running a normal "install" of the software, then using the 'pkgproto' utility in one of the following ways:


#### Absolute-path package

touch /tmp/timestamp
##[make install]

(echo "i pkginfo"; echo "i depend" ;
 echo "i copyright"; 
 find /opt/csw -newer /tmp/timestamp
) > |pkgproto > prototype

strip /opt/csw/bin/*
pkgmk -r / -a `uname -p`
filename=software-ver-SunOS`uname -r`-`uname -p`-CSW.pkg
pkgtrans -s /var/spool/pkg /tmp/$filename CSWyourpkg
rm -r /var/spool/pkg/CSWyourpkg

#### Relocatable-path package

touch /tmp/timestamp
##[make install]

(echo "i pkginfo"; echo "i depend" ;
 echo "i copyright"; 
 cd /opt/csw ;
 find . -newer /tmp/timestamp
) > |pkgproto > prototype

strip /opt/csw/bin/*
pkgmk -b /opt/csw -a `uname -p` BASEDIR=/opt/csw
filename=software-ver-SunOS`uname -r`-`uname -p`-CSW.pkg
pkgtrans -s /var/spool/pkg /tmp/$filename CSWyourpkg
rm -r /var/spool/pkg/CSWyourpkg

Use the Absolute-path way, if your executables have compiled in paths to /opt/csw/something. Otherwise, you may want to use the Relocatable-path version.

If your package does not have any dependancies, you should remove the "i depend" part.

Note: You should look through the prototype file, and verify that everything is owned by "root bin", not "root other", or some other uid local to your system. The STANDARD UID/GID combination is root:bin, unless there is a special need
(eg: things owned by 'nobody' for security reasons, etc)

You should now have a shiney new package file to submit. But you need to build TWO packages: one for Solaris 8 x86, and one for Solaris 8 sparc. The good news is, you can just copy over the pkginfo, prototype, etc. files to the other machine after you have installed the binaries, rather than having to hand-edit that stuff again.

How to create the package file without root access

If you are on a system where you do not have root access (like the shared sparc build machine), and dont have a custom prototype file to build a package straight from the build tree, there are a few different ways you could still make a package:

  1. A hand-built prototype file that translates build dir files to final destinations.
  2. An install as a non-root user, but hand-tweak the prototype file to have correct ownerships of files
  3. Use a tool to make your shell think it can do root type operations like chown and chmod, even though it cant realy.
Both #2 and #3 require that the software allow itself to be temporarily installed to an offset location. eg:
/tmp/destdir/opt/csw/bin instead of /opt/csw/bin

"direct from build tree" method

If you have a relatively simple program structure to install, it isnt so bad to make the prototype file by hand. This essentially replaces the normal "make install" process, by writing your own virtual install process to "install" to a package tree. A really simple example is the "links" program. A sample prototype file would look like the following:
i pkginfo
i depend
i copyright
d none /opt/csw/bin 0755 root bin
f none /opt/csw/bin/links=links 0755 root bin
d none /opt/csw/share/man 0755 root bin
d none /opt/csw/share/man/man1 0755 root bin
f none /opt/csw/share/man/man1/links.1=links.1 0644 root bin
To take advantage of this, once you have your pkginfo, depend, and copyright files all in the current directory, (and have 'strip'ped the executables) you just have to run
pkgmk -b /build/directory/path
pkgtrans -s /var/spool/pkg `pwd`/links-xxxx.pkg CSWlinks
rm -r /var/spool/pkg/CSWlinks

fakeroot method

This method can also potentially work even without fakeroot, (assuming the software allows non-root installs). It just means that you have to adjust the permissions in the prototype file by hand.

To have this work correctly, the software MUST HAVE an "install" target that respects a root directory offset. For some reason, a common name for a variable to do this is DESTDIR [A possible alternative is INSTALL_PREFIX] . The example assumes that DESTDIR is in effect.

Other assumptions:



$ mkdir -p /tmp/destdir/opt/csw                  #This may not be neccessary
$ fakeroot /bin/ksh                   #Or choose another shell if you prefer
# make DESTDIR=/tmp/destdir install   #
# cd /tmp/destdir/opt/csw
# (echo 'i pkginfo' ; echo 'i copyright'; pkgproto . )>prototype
####  You may have to add other stuff like a 'depend' file to the prototype
# exit
$ cd /tmp/destdir/opt/csw
$ cp {SOURCEDIR}/LICENSE copyright
$ cp ~/pkgs/pkginfo.xx pkginfo
$ strip *bin/*
$ pkgmk -b /tmp/destdir/opt/csw BASEDIR=/opt/csw
$ filename=yoursoftware-version-SunOS`uname -r`-`uname -p`-CSW.pkg
$ pkgtrans -s /var/spool/pkg /tmp/$filename CSWwhatever
$ rm -r /var/spool/pkg/CSWwhatever

How this works, is that the "fakeroot" pretends to let you do chown and chmod things like root would do, and stores the new fake ownership values until you exit the fakeroot shell. It will NOT let you do things like modify /etc/passwd or /etc/shadow.

BTW: If you do NOT want a relocatable package, you should use the following proceedure instead


$ mkdir /tmp/destdir                 #This may not be neccessary
$ fakeroot /bin/ksh                  #Or choose another shell if you prefer
# make DESTDIR=/tmp/destdir install  #or gmake
# cd /tmp/destdir
# (echo 'i pkginfo' ; echo 'i copyright'; pkgproto .) |  
     sed 's: none : none /:' >prototype
# exit
[cp copyright and pkginfo files into current directory, then]
$ strip opt/csw/*bin/*
$ pkgmk -r /tmp/destdir
$ filename=yoursoftware-version-SunOS`uname -r`-`uname -p`-CSW.pkg
$ pkgtrans -s /var/spool/pkg /tmp/$filename CSWwhatever
$ rm -r /var/spool/pkg/CSWwhatever


Resources

For full details on the finer points of pkg creation, you can try "man prototype", "man -s4 pkginfo", or go to Sun's Application Packaging Developer's Guide pages

It is suggested that you keep around your pkginfo and depend files, and any build notes you may have, so that when it comes time to upgrade the package, you have an easier time of it.

opencsw standards

Please note: this page is fairly generic for SYSV packaging. If you are interested in more of the CSW specific stuff, you should really look at our full packaging walkthrough page

Template archive

A "shortcut", if you will, can be taken by using Phil's template tarfile. This will extract an assortment of files to a 'template' directory. You should make your own directory to hold pkginfo type files, then copy the template files, and adjust as needed. [Although this tarfile may be a smidge out of date now]

After the first time you make a package, recreating it on the opposite CPU architecture will be trivial. Also, creating an updated package when new software comes out, will be similarly easy, as long as you keep around the directory with these files.


Signing up

Still up to the task? Then please let us know!