This page is about how pkgsrc, the NetBSD Packages Collection, compiles and installs NetHack onto several Unix-like operating systems, by patching NetHack to be more Unix-portable.
- Important: The information on this wiki page so far is the result of a study of the pkgsrc documentation and CVS repository, with no actual experience using pkgsrc. Thus this page more probably contains errors.
Introduction[]
pkgsrc has its origins as a fork of the FreeBSD Ports Collection. It consists of Makefiles interpreted by the NetBSD "make" command. These Makefiles use dependencies so that packages build in the correct order. Thus when you do this:
# cd /usr/pkgsrc/games/nethack # make install
First, this installs any dependent packages, such as X11 or Qt, if they are missing. Then it runs several phases to download, patch, build and install the package. The pkgsrc Makefiles call the package's Makefiles to do the actual build and install.
An interesting study is to examine the patches that pkgsrc provides, to check if Unix software required portability fixes.
NetHack[]
Currently pkgsrc can install NetHack 3.4.3 above Unix. This uses five packages, because pkgsrc does not support something like OpenBSD's flavors or Gentoo's USE flags.
The nethack package simply depends on the nethack-qt, nethack-tty, nethack-x11 packages, so installing "nethack" gives you all three user interfaces. All three packages depend on nethack-lib package which installs the playground.
The nethack-{qt,tty,x11,lib} packages all interact with the NetHack sources, but by invoking different targets in NetHack's top Makefile. Thus it is well possible for a user with nethack-qt to install nethack-tty without uninstalling anything or rebuilding everything; this is an advantage over flavors or USE flags.
The result is up to three executables sharing one playground; this differs from the typical setup of having one executable and setting the win option in NETHACKOPTIONS or a nethackrc.
Patches[]
The patches live in /usr/pkgsrc/games/nethack-lib/patches, and there are eight patches. These patches are small portability fixes or tweaks to interface with pkgsrc. These patches are not like those from the NetHack Patch Database that add new features to the game.
There are eight patches, one per file, because pkgsrc does not here use "diff -r". (The following list is from HEAD on 2 December 2006, what will become pkgsrc 2006Q4. Compared to 2006Q3, it contains a build fix for Linux.)
- patch-aa to config.h; makes the common configuration changes of enabling vision tables and using gzip.
- patch-ab to Makefile.top; mostly tweaks to permissions and the installed file hierarchy, and new targets 'binfiles' and 'datastuff' to separate nethack-lib from interface packages.
- patch-ac to system.h; several portability fixes discussed below.
- patch-ad to nethack.sh; changes to support the five-package system.
- patch-ae to Makefile.doc; a simple change to install the nethack(6) manual page in the same prefix as everything else.
- patch-af to unixconf.h; define SYSV or BSD, disable TERMINFO, change a default mail setting above NetBSD.
- patch-ag to mail.c; change default mail settings above NetBSD.
Some of the patches add seemingly-useless words like XXXPREFIXXXX or __NETHACK_OS__ or @GZIP_PROGRAM@. In a post-patch phase, pkgsrc uses "sed" to replace these with the correct values. (The code is in Makefile.common.) Currently, __NETHACK_OS__ becomes SYSV if the system is Linux, and BSD above all other systems; LINUX is never set.
patch-ac (system.h)[]
The purpose of NetHack 3.4.3's system.h file is to implement the various settings from config.h and (above Unix) also unixconf.h. Generally, one edits or patches config.h and unixconf.h, not system.h.
What motivates pkgsrc to patch system.h is that system.h really does a poor job on Unix. It makes many outdated assumptions and fails to handle the existence of the newer Unix clones. One change demonstrates a problem in NetHack, for pkgsrc changes system.h#line82 from
if (!defined(SUNOS4) && !defined(bsdi) && !defined(__FreeBSD__)) || defined(RANDOM)
to
if (!defined(SUNOS4) && !defined(bsdi) && !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__DragonFly__) && !defined(__APPLE__)) || defined(RANDOM)
Notice how __NetBSD__, __DragonFly__ and __APPLE__ have joined bsdi and __FreeBSD__ here.
The problem is the "srandom" declaration at system.h#line83. The declaration causes a compiler error above DragonFly, NetBSD and Apple Mac OS X. Vanilla NetHack 3.4.3 does not build on DragonFly, NetBSD nor Mac OS X. The error is that /usr/include/stdlib.h declares "srandom" to take an unsigned long, but NetHack declares it to take an unsigned int; the two prototypes come to conflict.
pkgsrc does the minimum to port NetHack to DragonFly, NetBSD and Mac OS X. (It would be more correct if Unix NetHack never declared system functions, but relied all upon header files.)