Building packages using pkgsrc

2020-07-13

HitchHiker was conceived to be as Unix-like as possible while running a Linux kernel and quite a bit of GNU userland. To that end a lot of Unix conventions are followed in the build tree, such as driving the entire system build using make. The original system of ten years ago had a ports tree and it's own shell based package tools, and I strongly considered bringing that back. However, I have an aversion to the constant reinvention of the wheel that plagues OSS development and do not desire to put another package manager out there if there is something that can be adapted to our needs.

Having used pkgsrc previously (both natively on NetBSD and on Linux) I knew that it works, but not without some hacking if you're using it elsewhere than NetBSD. It's simply a huge project to maintain a packaging system that works across different platforms. However, I felt that my knowledge might have increased to the point of being ready to give it another go.

The initial bootstrap brought up a few problems immediately. It turns out that dash is unable to bootstrap pkgsrc due to an incompatible echo builtin, and zsh, while not being officially unsupported, has issues with the way patching is done in pkgsrc due to the difference in the way zsh handles a no-match situation when using file globbing (most shells return an empty string, while zsh returns an error). My solution is something that I was already toying with - replace dash with mksh.

As shells go, mksh is in a nice niche. It's small yet has a lot of features, and it doesn't require external libraries to build (even dash requires libedit if you want line-editing capability). If built as the lksh variant it is very POSIX compliant and makes a quite suitable /bin/sh for running shell scripts. It's probably not as powerful as bash or zsh, but that's not quite the point. It's also crazy fast. Some tests put it ahead of dash in speed, while some put dash ahead. The jury is out on that so far as I can tell, but it's definitely quick enough to see a notable increase in speed when running large shell scripts or running many scripts in parallel.

I managed to bootstrap pkgsrc with no issues against lksh (installed as /bin/sh) and have had a lot of success building packages. There have been a few errors, and the process has helped me to find a few bugs, which I will enumerate below.

  • The ulimit builtin in mksh does not accept the -m option, breaking the build for libcups (and possibly other packages). There is already a solution, as the current sources for mksh accept ulimit -m on MacOSX for compatibility. I just extended that particular ifdef structure to include Linux as well and rebuilt the shell. My patch has been submitted upstream.
  • The glibc build looks for bash specifically and sed's the shebang to point to wherever it finds bash. As there is a symlink pointing from /usr/bin/bash to busybox ash in the temporary toolchain, for compatibility reasons, that's how ldd was getting installed. This was only discovered when building certain packages, as the interpreter did not actually exist after removing the temporary tools. I've created another patch that changes this behavior to use /bin/sh, with no problems in usage so far.
  • At some point (I'm not up for researching this) the function definitions for major() and minor() were moved from <sys/types.h> to <sys/sysmacros.h> in Linux. This caused a failure in the build of the Intel video driver shipped with pkgsrc and required patching 3 .c files to include the correct header on Linux. My patches have again been sent upstream to the package maintainer.
  • There were numerous build failures when linking against our version of curses (NetBSD curses ported to Linux by Sabotage). Considering the number of packages that would need to be patched in order to retain this package I have reverted HitchHiker back to the official ncurses.

The actual build directory for mksh has the source directly imported, bypasses the official build system and uses it's own Makefile to build both mksh and lksh in place in /bin, with intermediate object files placed in /obj/mksh and /obj/lksh. Quite a bit like our build of the ee text editor. The dash shell and libedit still exist in the tree for now, but are not built by default.

It is not yet decided whether pkgsrc will be the permanent source for third party packages on HitchHiker, or whether a ports tree will be developed to replace it. There are pros and cons that must be weighed. The chief complaints are that there are a fairly significant number of packages that pkgsrc duplicates which are already present in the base system, and that there are still build failures on Linux that must be fixed. However, for the time being using pkgsrc will both provide a quick way to get a large number of packages built for HItchHiker and also help to contribute back to the pkgsrc project and hopefully make the framework function better on Linux in general.


Tags for this post:

NonGNU Package Pkgsrc