How to make a Solaris package
Packages are the method Sun use to manage software on Solaris systems. Ordinary users can make them too, so I'm going to show you how. This is a very simplified version of Sun's Application Packaging Developer's Guide, with a few additions based on my experiences. Sun's guide is available from http://docs.sun.com/db/doc/805-6338?a=load (Solaris 8 version) or http://docs.sun.com/db/doc/806-7008?a=load (Solaris 9 version). I haven't yet read the Solaris 9 version, so I don't know if there are any major differences. The documentation available from Sun covers everything, but they don't really provide a step-by-step guide which takes you through making a simple package.
Q: Why would I want to make a Solaris package?
A: There are a few reasons, but basically it'll make your life easier.
pkgrm foo; pkgadd -d foo-new.pkg
Want to downgrade, because this version is buggy and produces garbage output?
pkgrm foo; pkgadd -d foo-old.pkg
Want to move to a new machine, and need to have all the same programs installed on the new one?
pkginfo | grep -v SUNW # Skip Sun packages.
How to install all the packages in the current directory:2
yes "" | for package in *.pkg; do
pkgadd -d "$package";
done
Enough arguments in favour of packaging: lets get to the instructions.
How to do it
There are 5 steps in packaging:
Steps 1, 2, 3 and 5 are easy; step 4 is the one you might have trouble with. None of these steps need to be done as root.
All the programs listed here should be in your PATH already on Computer Science or netsoc machines. If not they're in ~tobinjt/bin or can be downloaded from wherever you got this document4. All the examples will use the mythical foo program, version 3.5.7. These instructions are not cast in stone; you'll need to interpret them for yourself, as they won't work for every program. Likewise the instructions on extra files to include don't necessarily have to be followed, but experience has shown that including them helps.
tar zxf foo-3.5.7.tar.gz
make_doc foo-3.5.7
The first command (tar zxf foo-3.5.7.tar.gz) extracts the source, and should put it in a directory named foo-3.5.7. The second command (make_doc foo-3.5.7) creates another directory for documentation, foo-3.5.7-doc, and places 4 files within that directory:
E.g. OpenSSH depends on OpenSSL, so you would put this (all on one line)
in README.depend
P OpenSSL OpenSSL is an open
source SSL and TLS
library, used by OpenSSH, web browsers and
other
clients.
P makes this a prerequesite.
OpenSSL is the
package name.
OpenSSL is an open source SSL and TLS
library, used by
OpenSSH, web browsers and other clients. is
the package description.
#!/usr/bin/env bash
set -e
./configure --mandir=/usr/local/share/man \
--infodir=/usr/local/share/info
make
make DESTDIR=/tmp/foo/foo install
PKG= NAME= VERSION= CATEGORY= EMAIL=John.Tobin@cs.tcd.ie PSTAMP=John Tobin 2003/ BASEDIR=/usr/local CLASSES=none
You might want to customise the script so that it uses your name instead of mine. The meaning of the various variables are as follows:
For foo, we use (lines wrapped once more):
./configure --mandir=/usr/local/share/man \
--infodir=/usr/local/share/info
The binaries will go in /usr/local/bin, the configuration files in /usr/local/etc, manpages in /usr/local/share/man.
make
If this fails you may need to go back and change the options you passed to configure, install dependencies, or possibly fix broken Makefiles/source code. Sometimes there are tests for the program, which are usually run by make test, make check or make checks. You should create/compile as much documentation about the program as you can; many programs have HTML documentation, additional manpages, info pages, etc., and your users will thank you for providing as much information as you can.
make DESTDIR=/tmp/foo/foo install
DESTDIR is prepended to every path created. However if the author has written their own make(1) rules, then this might not work properly. You can check for this with the following command:
grep DESTDIR Makefile */Makefile
If you see any output, there's a good chance that it'll work.
make prefix=/tmp/foo/foo \
mandir='${prefix}/share/man' \
infodir='${prefix}/share/info' \
sysconfigdir='${prefix}/etc' \
install
Here the values of mandir, infodir and sysconfigdir are based on the value of prefix, thus the need for quoting.
DESTDIR=/tmp/foo/foo make -e install
This will work for sh(1), bash(1), ksh(1) and zsh(1) (tcsh(1) and csh(1) are left as exercises for the interested reader). Making it work for case 2 is similar.
If the installation is failing because the ownership of the files cannot be changed, try creating a dummy chown(1) program. It can be as simple as a symlink to /bin/true, or it might record the files and their correct ownership in a temporary file.
If you've gotten to here, you'll really want to record how you got it to work in the package via the README.install file.
cd /tmp/foo
mv foo/usr/local/* foo && rmdir -p foo/usr/local
add_doc .../foo-3.5.7-doc foo/share/doc
make_package foo tmp foo-3.5.7-solX-local.pkg \
"s/$USER $USER/root/bin/; s/0600/0644/; s/0700/0755/"
Several simple steps here:
Change to the directory you've installed the program into.
Remove the /usr/local/ prefix from the files. This will only be necessary if you've used DESTDIR; redefining prefix will strip /usr/local/ regardless. Don't do this if there are any files installed outside /usr/local/, e.g. in /etc or /var. Then empty directories foo/usr/local and foo/usr are unnecessary and removed.
add_doc creates foo/share/doc/foo-3.5.76, and copies
everything from .../foo-3.5.7-doc to
foo/share/doc/foo-3.5.7. It then hardlinks:
foo/share/doc/foo-3.5.7/README.pkginfo to ./pkginfo,
foo/share/doc/foo-3.5.7/README.depend to
./depend,
ready for the next command. Generally
add_doc will Do What I Mean with the arguments you give it.
make_package creates a package from a directory full of files. The arguments are:
make_package will generate a prototype file, determine the name of the package from the pkginfo file, run $EDITOR7 on that file so that you can make changes, create the package and then offer to remove the temporary files created during the process. You should ensure that ownership and permissions on every file are correct. You should also change the ownership and permissions on preexisting directories8 to ? ? ? so that they won't clash with the existing permissions. You may want to remove some files, e.g. static libraries if you prefer dynamic linking. When you quit the editor, the package will be created. If you've made any mistakes such as putting non-alphanumeric characters in certain pkginfo fields the packaging process will halt with an error message. If make_package offers to delete the temporary directory, you know you've been successful, and there should be a file containing the new package in the current directory.
You can now install this with:
pkgadd -d
foo-3.5.7-sol9-local.pkg
Woohoo!, you've made a package :)
Because it's a single file, you can compress it, move it elsewhere,
whatever you want. If you're not sure the package is correct, you can
install it to an alternate root directory like so:
pkgadd -d foo-3.5.7-sol9-local.pkg -R /some/directory
Now you're done with the first package. Play around with packaging - some programs will be trivially easy to package, others will be a nightmare (nethack comes to mind here). After you've done three or four you'll be flying. Good luck, and I hope this has helped somewhat.
This document was written as part of my job as a Systems Administrator in the Computer Science Department of Trinity College, Dublin. It is thanks to their generosity that this document has been made available to others.
Written by John Tobin
John.Tobin@cs.tcd.ie
, 2003.
Copyright Computer Science Department, Trinity College, Dublin.
Id: packaging.tex,v 1.4 2003/05/15 13:35:07 tobinjt Exp