Cross-Compiling User Programs on Instructional Machines

Follow these instructions to be able to compile user programs on instructional machines:
  1. Go to the nachos/test directory in your own copy of nachos.

  2. cd ~/nachos/test
  3. Copy the new Makefile to your test directory.

  4. cp ~cs162/nachos/test/Makefile .
  5. Then do the same to get the new Makefile for the bin directory.

  6. cd ../bin/
    cp ~cs162/nachos/bin/Makefile .

Now, you should be able to go into the your nachos/test directory, and type "gmake" to compile the sample user programs. Be sure to delete any old object files or programs that are in that directory before you recompile. Note, you do not need to run "gmake depend" to compile the user programs.

For the advanced reader

You can build your own cross-compilation tools if you want to work on a platform we don't support. The cross-compiler is a specially built version of gcc which compiles to a different target (in this case a MIPS processor) from the host platform. You also need to have a set of binutils (linker, assembler) etc, that works for the MIPS target. The process of building these is fairly straightforward, although it takes a bit of time. You can build these on your own for almost any host that supports gcc (Mac, Linux, Windows+Cygwin).

You can get binutils and gcc archives from a gnu mirror such as:

Create a directory somewhere, lets call it <MIPS> (that's an alias) to do the building. Copy the compressed tar files for binutils-<version> and gcc-<version> there. The binaries below were built with the latest binutils and gcc, which as of this writing (Fall 2013) are binutils-2.23.2 and gcc-4.8.1

cd <MIPS>

extract the source trees:

tar xvzf binutils-<version>.tar.bz2
tar xvzf gcc-<version>.tar.bz2

(in cygwin you may need to bunzip2 and then tar xvf separately).

Create build subdirectories of <MIPS> which are not inside the source directories, (so you dont pollute the source trees with build files). In <MIPS>, do :

mkdir binutils-mips
mkdir gcc-mips


cd binutils-mips

and do

../binutils-2.23.2/configure --target=mipsel-elf --enable-targets=mipsel-elf,mips-dec-ultrix42 --prefix=/usr/local/mips --program-prefix=mips- --disable-werror

This will create a makefile and put all the binaries in the <MIPS>/binutils-mips tree, not in the source tree <MIPS>/binutils-<version>. This configuration actually builds for two targets (two binary formats). The main one is ELF, which is the most common binary format today. The target "mips-elf" allows you to manipulate ELF binaries for various MIPS processors. The other "mips-dec-ultrix42" allows you to examine and create COFF binaries which are currently used in nachos. The --prefix indicates where files will be installed. You can change this if you want to install somewhere else. --program-prefix=mips- adds "mips-" to the binutil names, such as "mips-as", "mips-ld" etc, which helps avoid collisions with the machine's native binutils. "--disable-werror" prevents the build from being too conservative, and labeling some benign warnings as errors.

NOTE: The gnu lists have announced discontinued support for mips-coff platforms like "mips-*-ultrix*", so the above configuration will stop working at some point. This is fine. By then we will have direct support for ELF within nachos. Now just do:

make install

(or sudo make install, if you are installing into a system directory). This will first compile, and then install the binutil binaries in the directory pointed to by --prefix. Next set the PATH to include the new binaries:

export PATH=/usr/local/mips/bin:$PATH

Building gcc is similar although you may have to install some prerequisites first. If you try the steps below and see messages about gcc requiring GMP, MPFR and MPC, you will either have to install them with your package manager (on Linux), or download and build them (e.g. MacOSX). You should find that a simple "./configure; make; make install" sequence works for them.

Now to build the gcc cross-compiler, do:

cd <MIPS>/gcc-mips
../gcc-4.8.1/configure --target=mipsel-elf --prefix=/usr/local/mips --program-prefix=mips- --with-gnu-as --with-gnu-ld --enable-languages=c
make all-gcc
make install-strip-gcc

This sequence specifies the target architecture, installation directory location (--prefix) and a program-prefix "mips-" so that the compiler commands are "mips-gcc", "mips-cpp" etc. The other options ensure that the build uses gnu versions of as and ld (assembler and linker) instead of the systems native ones, in case they are not gnu. The make commands build and install only the compiler. If you used default targets "make" and "make install", you would also be building a variety of runtime libraries for the target platform. This isnt necessary and usually wont work because of missing config and header files - we arent building for a real target OS/system after all, and many options to build these libraries depend on details of that platform.

You'll notice that we built gcc for ELF binaries and not COFF. gcc already stopped supporting COFF a while back, but luckily we can compile C source files to ELF .o files, and then use the bilingual binutils to link the ELF .o files into COFF executables. Nachos runs these COFF executables and is never the wiser. I suppose this is "double-cross compilation". Well it works anyway.

This should put all the compiler commands you need into /usr/local/mips. You can run them from there, or copy that tree somewhere else. To run from within nachos, remember to set ARCHDIR to /usr/local/mips/bin, or whichever other location you installed or copied to.

JFC updated 9/17/2013