2004-10-29 · in Tech Notes · 1024 words

Today's objective has been to get RMoX built with the most recent toolchain. I've succeeded, but I've found lots of broken stuff along the way that'll need fixing properly.

When Fred last built RMoX, he documented the build process on the RMoX web pages. These instructions (presumably) work with the software versions he lists, but quite a lot has changed since in the occam-pi world: we've had a new stable release of KRoC, for instance.

Assembling the pieces

I'm going to assume that you're doing this all in your home directory; it should be pretty obvious what to change if you're doing this elsewhere.

You'll obviously need the RMoX source. I'm working from the latest RMoX source in the Subversion repository on rmox-dev, but you'll also need the latest RMoX release tarball off the web site, because the toplevel Makefile is missing from the repository.

You'll need the KRoC source (even if you've got it already installed). I first tried kroc-1.3.4-pre1.tar.gz, the latest prerelease, but that won't compile some of the RMoX code owing to an interesting bug; get kroc-1.3.3.tar.gz instead.

The problem is that Fred enabled some internal checks in occ21 in this release that weren't previously present, and this exposes some previously-harmless compiler bugs. The particular one that I ran into building RMoX was a refusal to compile CLONE followed by an array subscript (for example, CLONE a[0]). This is the result of a bug in the cmobileio function in chk2.c: occ21 tries to ensure that if the argument to CLONE is a channel, then it must be a shared channel, but in the process it assumes that the argument to CLONE is a single variable name, which isn't true in this case. It looks like it'd be possible to fix this problem by using something like chk_gettype (which finds the declaration corresponding to the type of an expression elsewhere in the parse tree).

Finally, you'll need the Flux OSKit. This hasn't been maintained by its original authors for a couple of years, but the GNU Hurd developers have a patched version on Savannah which compiles with modern versions of GCC and binutils and has a few new features. Check it out from their CVS repository into a directory called oskit-source.

Building KRoC

A normal KRoC build will do nicely. If you've got KRoC 1.3.3 installed already, then you don't need to do this.

Before you build KRoC, take a copy of the src/ccsp-1.6 directory. RMoX requires a specially-built ccsp runtime, and we'll want to modify it in a minute.

cd ~/kroc-1.3.3
cp -a src/ccsp-1.6 ~/
./build --prefix=$HOME/kroc133
. ~/kroc133/bin/setup.sh

Building the OSKit

The Savannah OSKit very nearly works out of the box, but it doesn't succeed in building the multiboot-to-zImage adaptor that KRoC needs in order to generate a zImage, because it tries to use ld -oformat binary when that should actually be --oformat on modern binutils. Patching this and then building the result is easy:

cd ~/oskit-source
perl -i.bak -pe 's/-oformat/--oformat/g' configure
CC=gcc-2.95 ./configure --prefix=$HOME/oskit
perl -i.bak -pe 's/-oformat/--oformat/g' boot/linux/*
make
make install

It doesn't really need installing -- RMoX links stuff and runs scripts straight out of the build dir -- but the aforementioned adaptor scripts look for a boot image in the installed path.

I'm not sure if it's necessary to use GCC 2, but it certainly doesn't hurt; OSKit is very much GCC 2-era code.

Preparing the RMoX source

The RMoX source in the repository at the moment needs some twiddling to be buildable (the code's fine; it's just the build system that's broken).

CCSP will need some RMoX headers, but it tries to include oos/x.h instead of x.h; we drop a symlink into the RMoX source to deal with this.

cd ~/rmox/include
ln -s . oos

The RMoX repository is also missing the toplevel Makefile, so we copy that from Fred's released source. We need to edit the OSKIT and KROC_CCSP variables in there to point at the right paths too ($(HOME)/oskit-source and $(HOME)/ccsp-1.6 respectively). We run the config-building script provided to generate config.mk from config.occ. Finally, we create empty DEPS files in each of the source directories; the Makefiles aren't set up to correctly autogenerate them (the target's called depend, not DEPS), and doing make depend will fail because it tries to include the nonexistent files.

cd ~/rmox
cp ~/rmox-0.1.2/Makefile .
vim Makefile
cd occam
touch DEPS
for x in */ ; do touch $x/DEPS ; done

Building CCSP

The CCSP source needs modifying for the OSKit environment. The problem is that KRoC on Linux uses siglongjmp to return from a signal handler, but the OSKit doesn't provide siglongjmp, sigsetjmp or sigjmp_buf. The first two don't matter, but the last does, because the bsc_thread structure declared in include/i386/bsyscalls.h has a sigjmp_buf *jbuf; member. Find this, and change it to char jbuf[156];. (That's just to keep the structure size the same; I haven't yet investigated whether it'd be safe to just remove the member for RMoX.)

cd ~/ccsp-1.6
vim include/i386/bsyscalls.h

Then we can build it:

./preconfigure
./configure --enable-oos-build \
            --with-oskit=$HOME/oskit-source \
            --with-oos=$HOME/rmox
make

And now we have to build the specific version of CCSP as a library that RMoX needs, and copy it into our RMoX source directory:

make libkroc_oos.a
cp libkroc_oos.a ~/rmox/

While doing this, I noticed that CCSP's autoconf setup is broken: the --enable-blocking-syscalls option actually disables blocking syscalls (because the arguments to AC_ARG_ENABLE are backwards). Not that this matters much, because CCSP won't build without BSC anyway.

Building RMoX

Now that we've done all the dependencies, we should be able to compile the RMoX occam source:

cd ~/rmox/occam
make depend
make

For some reason, with KRoC 1.3.3, most of the symbols we need don't end up in librmox.a, so we just add all the object files to that library:

ar cru librmox.a *.o */*.o

Now we can build the zImage:

cd ..
make

Running RMoX under qemu

Now you should have a functioning RMoX zImage. And you don't even need another PC to prove it's working: RMoX runs fine under Fabrice Bellard's incredibly cool qemu PC emulator, provided you pad it to be the right size for a disk image first:

cat zImage /dev/zero | dd of=disk bs=1k count=1440
qemu -fda disk

Which looks like this:

qemu running RMoX