Building a multilib MIPS toolchain: my journey through gcc's build system

Joey Dumont bio photo By Joey Dumont Comment

This article assumes that you know to compile a cross-compiler from scratch. If not, I recommend this succinct guide, or this longer guide if you want to have some context.

On x86_64 architectures, building gcc such that it can generate both 32- and 64-bit code is easy: just use the --enable-multilib flag at configuration time, and everything will follow smoothly (see Arch Linux’s PKGBUILD for gcc, the packaging is a bit more complicated, but the build itself is simple).

It is not as easy when targeting the MIPS architecture, specifically mips64-elf. By default, the 32-bit ABIs are not part of the multilib setup. gcc exposes the multilib setup that was used to compile a toolchain via the -print-multi-lib option. On your own x86_64 system, you should see something similar to this (assuming you have gcc-multilib on your system)

valandil ~ $ gcc -print-multi-lib

where the second line shows the use of -m32 in the build options for the gcc toolchain itself, and the libraries are stored in the 32/ directory. This toolchain is thus comprised of two sets of GCC libraries, one compiled with default options, and one with -m32.

If you had installed a mips64-elf toolchain with --enable-multilib, by default you would get the following output

valandil ~ $ mips64-elf-gcc -print-multi-lib
soft-float/el;@[email protected]

In order to enable other ABIs, specify other build options for the GCC libraries in general, you need to know about Target makefile fragments.

In short, target Makefile fragments are the gcc/config/<target>/t* files in gcc’s source tree. When you specify a target at the configure step, it looks for those in order to generate the Makefile that will actually build the gcc libraries 1. For a mips64-elf target, the file that is of interest to us is the gcc/config/mips/t-elf file. By default, it sets three Makefile variables

MULTILIB_DIRNAMES = soft-float el eb
MULTILIB_MATCHES = EL=mel EB=meb msingle-float=m4650

which instructs the gcc build system to generate libraries for combinations of these three build flags. Flags that are separated by a space are combined, while incompatible flag are separated with a slash. It is this fragment that generated the mips64-elf-gcc -print-multi-lib output that we saw above.

So, if you want to generate libraries for other ABIs, you simply edit (or create a new one!) that file to what you need. In my case, I wanted to have libraries compiled with -mabi=32, at it is the ABI used by most N64 games. So, I edited my t-elf fragment to be

MULTILIB_OPTIONS = mabi=32 msoft-float EL/EB
MULTILIB_DIRNAMES = 32 soft-float el eb
MULTILIB_MATCHES = EL=mel EB=meb msingle-float=m4650

If you were to compile this toolchain, you would get the following -print-multib-lib output:

soft-float/el;@[email protected]
32/soft-float;@mabi=[email protected]
32/el;@mabi=[email protected]
32/soft-float/el;@mabi=[email protected]@EL

MULTILIB_DIRNAMES controls the name of the folder in which the libraries reside. Note that this corresponds to the information before the semi-colon in the -print-multilib-output, while the string after describes the build options, preppended with @. and MULTILIB_MATCHES provides the synonyms of some build options.

There are other options than those discussed here. Feel free to read the Makefile Fragment of the gcc docs to have the whole story, or look at an example of custom target in glank’s n64 repo, under config (as of July 9th, this is only in the n64-ultra branch).

  1. At least, that is how I think it works. 

comments powered by Disqus