You can build your own toolchain with GCC, Binutils, and Newlib (optional). This is not difficult but it is tedious, and it takes several minutes to compile GCC, which can make it very time-consuming to experiment with different compilation flags.
Also see: OSDev: GCC Cross-Compiler.
A working toolchain contains:
- Binutils, which contains the linker
as, and other tools like
- GCC, the compiler. This will provide certain headers like
<stdbool.h>that define types but don’t contain library functions.
- (Optional) A standard library, like Newlib, which contains headers like
<stdio.h>that define library functions.
These instructions install the toolchain in
/opt/n64, but you can choose any path.
These instructions build GCC for the “o32” ABI, which you get by compiling with
-mabi=32. This is the old 32-bit ABI, and it’s the ABI used by LibUltra / NuSys. If you are using something other than LibUltra, you will need to build GCC with different flags.
A “target tuple” identifies a system where code can run. The general format is “
cpu-vendor-os”. For example, the target tuple for an x86 Linux system might be
x86_64-pc-linux-gnu, and a Mac might be
x86_64-apple-darwin18.7.0. For the Nintendo 64, we are going to use
mips32-elf as the target tuple, which the build scripts will automatically expand to
mips64-unknown-elf (MIPS CPU, unknown vendor, generic ELF OS).
The target tuple is used by the toolchain build scripts to configure settings like build architecture, ABI, the format for compiled objects, linker scripts, and macros predefined by the compiler.
Out of Tree Builds
The toolchain is not designed to be built in the source directory. In other words, you cannot run
make inside the Binutils or GCC source directory, you have to create separate folders for the build.
Download the latest version of Binutils, GCC, and Newlib. As of November 2020, the latest versions are Binutils 2.35.1, GCC 10.2, and Newlib 3.3.0.
/opt/n64/bin to your
PATH environment variable before starting the build.
When you run
make, pass a
-j option with the number of cores your computer has. If your computer has four cores, pass
-j4. This guide will use
The following software must be installed:
- GNU Sed
On a Debian/Ubuntu system, run:
$ sudo apt install build-essential libgmp-dev libmpfr-dev libmpc-dev
On macOS, using Homebrew:
$ brew install gmp mpfr libmpc gnu-sed $ PATH=/usr/local/opt/gnu-sed/libexec/gnubin:$PATH
Extract and build Binutils.
$ tar xvf binutils-2.35.1.tar.xz $ mkdir build.binutils $ cd build.binutils $ ../binutils-2.35.1/configure --target=mips32-elf --prefix=/opt/n64 --with-cpu=vr4300 --disable-nls --with-sysroot=/opt/n64/mips32-elf/sysroot $ make -j4 $ sudo make install
Building GCC, Part 1
Extract and build GCC. Don’t delete the build directory, because it will be needed later.
Check that you have GNU Sed and not some other version. If you run
sed --version, it should print out “GNU sed”. Without GNU sed, the makefiles for GCC will be generated incorrectly, and you will get mysterious build errors.
$ tar xvf gcc-10.2.0.tar.xz $ mkdir build.gcc $ cd build.gcc $ ../gcc-10.2.0/configure --target=mips32-elf --prefix=/opt/n64 --with-languages=c,c++ --disable-shared --disable-threads --disable-nls --without-headers --disable-multilib --with-newlib --with-sysroot=/opt/n64/mips32-elf/sysroot --with-arch=vr4300 --with-abi=32 $ make -j4 all-gcc $ sudo make install-gcc
Extract and build Newlib.
$ tar xvf newlib-3.3.0.tar.gz $ mkdir build.newlib $ cd build.newlib $ ../newlib-3.3.0/configure --prefix=/usr --target=mips32-elf --disable-threads --disable-libssp CFLAGS_FOR_TARGET='-march=vr4300 -mfix4300 -G 0' $ make -j4
The installation will not work correctly without the path set, and the sudo will ignore any changes to PATH, so you have to put the PATH inside the sudo command. Ignore this if you are installing without sudo.
$ sudo sh -c 'PATH=/opt/n64/bin:$PATH; make DESTDIR=/opt/n64/mips32-elf/sysroot install'
Newlib installs itself in not exactly the place it needs to be, so move the installed files to the correct directory:
$ cd /opt/n64/mips32-elf/sysroot/usr $ sudo mv mips32-elf/* . $ sudo rmdir mips32-elf
Building GCC Part 2
GCC also includes LibGCC, which must also be built. This contains low-level functions that may be needed by code you compile with GCC even if you don’t explicitly call functions.
$ cd build.gcc $ make -j4 all-target-libgcc $ sudo make install-target-libgcc
You can now run GCC as