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
(package
(inherit hello)
(source (local-file (string-append (dirname (current-filename)) "/hola.cpp")
#:recursive? #t))
(inputs (list gcc-mine))
(arguments
`(#: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"))))))))))
my-hello
And a hola.cpp
file:
#include<iostream>
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:
/gnu/store/niszn6sh1hd6hqwg0xjcw2q7q4lbjvbb-hello-2.12.1.drv
building /gnu/store/niszn6sh1hd6hqwg0xjcw2q7q4lbjvbb-hello-2.12.1.drv...
... BLABLABLAH ...
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
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
phase `build' succeeded after 1.4 seconds
successfully built /gnu/store/niszn6sh1hd6hqwg0xjcw2q7q4lbjvbb-hello-2.12.1.drv
The following graft will be made:
/gnu/store/hnvji18y322q408x3h6i0wafmd6hqmdf-hello-2.12.1.drv
applying 2 grafts for hello-2.12.1 ...
... BLABLABLAH ...
successfully built /gnu/store/hnvji18y322q408x3h6i0wafmd6hqmdf-hello-2.12.1.drv
/gnu/store/dbkz567v66ry813svva2j3lnmdchb5r5-hello-2.12.1
And that I could run (using Qemu binfmt magic):
$ /gnu/store/dbkz567v66ry813svva2j3lnmdchb5r5-hello-2.12.1/bin/hola
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
/gnu/store/fpqqyym3w1ym24jr2xiwz94hjfgr5hjm-glibc-2.35/lib/ld-linux-riscv64-lp64d.so.1,
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
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
(package
(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")))) ))))))
gcc-with-mine
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.
-
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. ↩