Ekaitz's tech blog:
I make stuff at ElenQ Technology and I talk about it

GCC 4.6.4 with RISC-V support

From the series: Bootstrapping GCC in RISC-V

I already mentioned at the FOSDEM-2024 that we built GCC 4.6.4 in a Debian machine in real RISC-V hardware, but I didn’t explain the specifics. Since then we’ve been working on many other parts and trying to package it for Guix, which happened to be harder than we thought (more on that later).

Today I decided to build it again to make sure it was possible to do, including GCC’s bootstrapping process that was giving us headaches in Guix and wrote the process down, because I remember the last time I tried it failed for me and I was worried. Maybe I did something I forgot? Or was my brain playing tricks on me?

That’s why I’m writing this down. You already know how it works. It has happened to you, and if it didn’t it probably will.

Debian

Install some simple deps:

$ sudo apt install build-essential git

Clone the repo and jump to it, to the working-compiler-c++ tag:

$ git clone https://github.com/ekaitz-zarraga/gcc.git
$ cd gcc
$ git checkout working-compiler-c++

In Debian the riscv64-linux-gnu standard library is installed in a weird location, so we need to make the compilation process find it.

$ export C_INCLUDE_PATH=/usr/include/riscv64-linux-gnu/
$ export CPLUS_INCLUDE_PATH=/usr/include/riscv64-linux-gnu/
$ export LIBRARY_PATH=/usr/lib/riscv64-linux-gnu/

We need to patch a couple of things, that we’ll set up in the Guix recipe. I decided to keep them out of the codebase because I want to keep the code consistent with the past.

This first patch is to convert the struct ucontext to the modern name: ucontext_t. This change only makes GCC compilable using a modern toolchain, in other contexts you might want to keep the old name.

$ sed -i 's/struct ucontext/ucontext_t/g' gcc/config/*/linux-unwind.h

Next, to avoid some error with pthread, you have to apply this diff. Which is just removing some pthread reference from gcc/config/riscv/linux.h

diff --git a/gcc/config/riscv/linux.h b/gcc/config/riscv/linux.h
index cd027813b41..d7d2b0978de 100644
--- a/gcc/config/riscv/linux.h
+++ b/gcc/config/riscv/linux.h
@@ -23,16 +23,6 @@ along with GCC; see the file COPYING3.  If not see

 #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux-riscv" XLEN_SPEC "-" ABI_SPEC ".so.1"

-/* FIXME */
-/* Because RISC-V only has word-sized atomics, it requries libatomic where
-   others do not.  So link libatomic by default, as needed.  */
-#undef LIB_SPEC
-#ifdef LD_AS_NEEDED_OPTION
-#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC \
-  " %{pthread:" LD_AS_NEEDED_OPTION  LD_NO_AS_NEEDED_OPTION "}"
-#else
-#endif
-
 #define LINK_SPEC "\
 -melf" XLEN_SPEC "lriscv \
 %{shared} \

Now, configure and build, classic GNU build-system:

$ ./configure --build=riscv64-linux-gnu --enable-languages=c,c++ \
    --disable-shared --disable-gomp --prefix=/data/prefix
$ make -j4

This should finish properly and give you a working GCC.

Guix

In the riscv branch you can see more work by Efraim Flashner trying to make a Guix package we can use later, but it’s not as easy as it looks. Guix is not like Debian in many things, and that makes the process a little bit harder.

Efraim managed to fix the package I made (see guix.scm) to work on i386 but the very same package didn’t work for RISC-V without changes.

The main problem has to do with GCC’s bootstrapping process.

GCC’s bootstrapping process

When we talk about GCC’s bootstrapping process we don’t mean the whole distribution bootstrapping which is what we are trying to achieve in this very project, but the process the compiler itself has to check itself.

When you build GCC from source, it is built with the compiler you have in your machine. Once it did that, the resulting compiler is used to compile the GCC’s source code again, and the resulting compiler builds GCC again. The binaries generated by the latest two steps are compared one to another, and if they are not identical (bit by bit) the build process is considered a failure.

This is giving us some headaches in Guix. We manage it to finish, but the latest steps are slightly different, for reasons we are not sure about yet.

So…

The reason why I built this thing in Debian again was to remind me it is possible to build it right, passing the comparison step, so I could get a little bit more of motivation to make it build in Guix properly.

Let’s see if this serves its purpose and we manage to make it soon.