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

GCC 4.6.4 with RISC-V support in Guix

From the series: Bootstrapping GCC in RISC-V

Short post now, following what we did in previous episodes where we explained how to build it and run it in Debian, now we can run it in Guix thanks to Efraim Flashner’s help.

We didn’t get rid of the GCC Bootstrapping issue we explained in that post (comparing binaries and all that, you remember). But we patched around it because the differences were minimal, and this is not going to be a production compiler after all. If this causes trouble in the future, we’ll fix it, but I don’t think it will (I’ve said this before…).

How to use this thing

We provide a guix.scm file in the repository you can use for your own packages. If you know Guix, that’s probably all you need to know.

In my case, I did some ugly testing on this thing, so I made another folder, adjacent to the gcc project folder and made this1:

I added a guix.scm file:

(use-modules (gnu packages base)
             (gnu packages)
             (guix licenses)
             (guix gexp)
             (guix utils)
             (guix build-system gnu)
             (guix packages))

(load "../gcc/guix.scm")

(define-public my-hello
    (inherit hello)
    (source (local-file (string-append (dirname (current-filename)) "/hola.cpp")
              #:recursive? #t))
    (inputs (list gcc-mine))
      `(#:tests? #f
        #:phases (modify-phases %standard-phases
         (delete 'configure)
         (delete 'install)
         (replace 'build (lambda* (#:key outputs #:allow-other-keys)
            (let ((out (assoc-ref outputs "out")))
              (mkdir-p (string-append out "/bin"))
              (invoke "g++" "--version")
              (invoke "g++" "hola.cpp" "-o" (string-append out "/bin/hola"))))))))))

And a hola.cpp file:

int main (){
    std::cout << "Hola!\n";
    return 0;

Jumped into the folder and called this:

guix build -f guix.scm --system=riscv64-linux-gnu -K

Which gave me something like this, but way longer (beware of the BLABLABLAH):

$ guix build -f guix.scm --system=riscv64-linux -K
fatal: not a git repository (or any parent up to mount point /)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
substitute: updating substitutes from 'https://substitutes.nonguix.org'... 100.0%
substitute: updating substitutes from 'https://ci.guix.gnu.org'... 100.0%
substitute: updating substitutes from 'https://bordeaux.guix.gnu.org'... 100.0%
The following derivation will be built:
building /gnu/store/niszn6sh1hd6hqwg0xjcw2q7q4lbjvbb-hello-2.12.1.drv...


starting phase `build'
g++ (GCC) 4.6.4
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO

phase `build' succeeded after 1.4 seconds
successfully built /gnu/store/niszn6sh1hd6hqwg0xjcw2q7q4lbjvbb-hello-2.12.1.drv
The following graft will be made:
applying 2 grafts for hello-2.12.1 ...


successfully built /gnu/store/hnvji18y322q408x3h6i0wafmd6hqmdf-hello-2.12.1.drv

And that I could run (using Qemu binfmt magic):

$ /gnu/store/dbkz567v66ry813svva2j3lnmdchb5r5-hello-2.12.1/bin/hola

Let’s use file command just in case:

$ file /gnu/store/dbkz567v66ry813svva2j3lnmdchb5r5-hello-2.12.1/bin/hola
/gnu/store/dbkz567v66ry813svva2j3lnmdchb5r5-hello-2.12.1/bin/hola: ELF 64-bit
LSB executable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV),
dynamically linked, interpreter
for GNU/Linux 2.6.32, stripped

No tricks here, it’s a RISC-V file, and you can see up in the Guix output it was built using GCC 4.6.4. That’s what we promised, isn’t it?


Next we need to connect this thing to the bootstrapping chain. It needs to be built using TinyCC and it needs to be able to build a modern GCC that is more stable.

With that, we might be able to build the whole RISC-V world.

Wish us luck.

Extra (added 2024-04-05)

In a similar fashion to the my-hello I shared as an example, I just tried this:

(use-modules (gnu packages gcc)
             (ice-9 rdelim)
             (gnu packages)
             (guix licenses)
             (guix gexp)
             (guix utils)
             (guix build-system gnu)
             (guix packages))

(load "../gcc/guix.scm")

(define-public gcc-with-mine
    (inherit gcc-7)
    (inputs `(("gcc" ,gcc-mine) ,@(alist-delete "gcc" (package-inputs gcc-7))))
    (arguments (substitute-keyword-arguments (package-arguments gcc-7)
      ((#:phases phases)
       `(modify-phases ,phases
         (add-after 'unpack 'setenv
             ;; We don't want gcc-11:lib in CPLUS_INCLUDE_PATH, it messes with
             ;; libstdc++ from gcc-4.6.
             (lambda _
               (setenv "CPLUS_INCLUDE_PATH" (getenv "C_INCLUDE_PATH")))) ))))))


And guess what? It worked.

This is really interesting because GCC 7.5 is the first one with official RISC-V support. Being able to build it means from here we can follow the existing bootstrapping chain and build the world. Also, GCC is a huge program and, as I told you before, it does some checks during the build, building itself twice and then comparing the resulting binaries to make sure it’s stable. Building an stable GCC that is also able to build itself means a lot.

At this point we can consider my GCC-4.6.4 backport is correct, and not only that, our package definition is, too. In projects like this bootstrapping thing it still feels weird when things just work, it makes you be suspicious… I’ll try to ignore that feeling and be happy, just for once.

  1. Oh yes, I said ugly. If you know Guix you’ll understand what I mean. There are plenty of ways to do this clean, but I don’t care. I’m ugly.