Making Packages I

Posted on June 11, 2004 by Chris Lumens in NeXTSTEP.

I’ve recently gotten tired of spamming my NeXTstation with software. Instead, I’d like to use its packaging system to create pacakges out of the things that I build. This has several advantages.

After some searching around, I was unable to find any documentation on the system about how to make packages. However, I was able to find a csh script in /NextAdmin/Installer.App called package. After a brief examination of that script, I figured out that it was used to make packages.

It turns out that making a NeXTSTEP package is pretty easy. In this article, I will cover the basics. Later on, I’ll talk about the scripts that you can embed in your package, multiple architectures, and maybe even multiple languages. So let’s get on to a description of the NeXT package format.

Package Format

A NeXT package is simply a directory that fits the name foo.pkg. When you download a package, it can come archived in any way that the packager desires; the most common are tar-gzipped and tar-compressed. The contents of that directory make up the package. A simple package will have the following files in it:

Building a Package

Now that you’ve got a basic understanding of what goes into a package, let’s create one. The first thing to do is figure out what you want to package. For this example, I’ll be using diff, which takes files and finds the differences between them. diff is a common Unix utility used by software developers.

Building the Software

First, I download the diff source, extract it, and build it. The most important aspect of this is choosing an installation prefix. I prefer /usr/local for anything that I build. The distributor installs things with a prefix of /usr, but software added by the local administrator should most likely go into /usr/local. For big NeXTSTEP graphical things, I would probably choose /LocalApps.

The other details of building diff are unimportant for this example. Once it has been built, you should then install it to the system. make install will usually do it. Here comes one important thing to note about the NeXTSTEP packaging system. When you create a package, all you really do is create a fake root tree and copy into that tree everything that should go into the package. Since you specify an installation prefix for your package, you should leave that off.

Additionally, you should pay careful attention to the permissions and ownerships of the files that you copy into this package tree. Always copy things over as root and make sure that permissions are set properly. package does nothing to modify the permissions and ownerships of the files in a package, so make sure that they are correct.

Creating the Package Root

Continuing with our example, doing a make install on the diff source will install the following:

/usr/local/bin/diff
/usr/local/bin/diff3
/usr/local/bin/sdiff
/usr/local/bin/cmp
/usr/local/man/man1/cmp.1
/usr/local/man/man1/diff.1
/usr/local/man/man1/diff3.1
/usr/local/man/man1/sdiff.1
/usr/local/info/diff.info
/usr/local/info/diff.info-1
/usr/local/info/diff.info-2
/usr/local/info/diff.info-3
/usr/local/info/diff.info-4

I would then make a directory called /tmp/root to serve as the package building tree. Think of /tmp/root as taking the place of /usr/local for all the files listed above. Therefore, I would want to make the following directories: /tmp/root/bin, /tmp/root/man/man1, and /tmp/root/info. Then, just copy all the files from the running system into your package tree. After you’re done, you would then have a tree that looked like this:

/tmp/root/bin/diff
/tmp/root/bin/diff3
/tmp/root/bin/sdiff
/tmp/root/bin/cmp
/tmp/root/man/man1/cmp.1
/tmp/root/man/man1/diff.1
/tmp/root/man/man1/diff3.1
/tmp/root/man/man1/sdiff.1
/tmp/root/info/diff.info
/tmp/root/info/diff.info-1
/tmp/root/info/diff.info-2
/tmp/root/info/diff.info-3
/tmp/root/info/diff.info-4

Writing the diff.info File

Double check that all the permissions and ownerships are right. And you’re basically done with the hard part. Now you’ll need to write the info file; in this case, that would be named diff.info. Where you put this file is not important, but I prefer to just throw it into /tmp. The info file contains a keyword, followed by whitespace, followed by a value. These are the most common elements of an info file:

Here’s the diff.info file that I’d write up for the diff package. Note that I make the whitespace between keyword and value a tab, but I don’t know if it has to be.

Title          diff utilities
Version        2.7
Description    The GNU diff utilities find differences between files (to make source code patches, for instance).

DefaultLocation      /usr/local
Diskname             diff
Relocatable          YES
Application          YES
LibrarySubdirectory  Standard

Running package

Having created the package tree in /tmp/root and having written the diff.info file, I’m now ready to create the package. package has two required arguments: the package tree, and the location of the info file. Call package like so:

$ cd /tmp
$ /NextAdmin/Installer.App/package /tmp/root/ /tmp/diff.info

You’ll see package output some messages as it works on the package:

Generating Installer package ./diff.pkg ...
        creating package archive ... done.
        copying diff.info ... done.
        generating bom file ... done.
        generating sizes file ... done.
   ... finished generating ./diff.pkg.

And package will drop the diff.pkg directory into the directory you called it from. That’s why I changed into /tmp first. If you examine the resulting diff.pkg/diff.tar.Z, you’ll see that package strips the /tmp/root from the beginning of every file. When you go to install the package, the DefaultLocation (or location that the installer specifies, if Relocatable) will get tacked to the beginning of each file.

Distribution

You may now install the package onto your system if you’d like to keep track of it. Then, simply archive the package using your favorite archiver (I prefer tar-gzipped) and you’re ready to distribute it. Here’s how I would package up that diff.pkg directory:

$ cd /tmp
$ tar -cvf - diff.pkg | gzip -9c > diff-2.7-N.tar.gz

I’ve chosen that name because it shows what’s in the archive, what version the software is, and for what architecture it was compiled (N - NeXT hardware).

Cleanup

After archiving the package, you can delete the info file, the root directory, the diff.pkg directory, and any source that you have laying around. Just don’t delete the archived package, or you’ll have to do all this stuff over again.

Closing

That’s all for this introduction to the NeXTSTEP packaging system. Later, I will be talking about installing and removing packages, having control scripts in your packages, and an introduction to multiple languages and architectures in the same package. I hope you’ve enjoyed this article.

If you have any comments or corrections for this article, or would like to fill in the gaps in my knowledge, feel free to send me an email. I can be reached at: chris@bangmoney.org