💾 Archived View for thebird.nl › blog › 2022 › risc-v-on-guix.gmi captured on 2022-04-28 at 17:28:56. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
Thanks to the hard work of the GNU Guix community we can cross-compile RISC-V software, run it in emulation and even push binary blobs to RISC-V hardware. In this BLOG we will:
Install GNU Guix on any distro using the binary download. On Debian it is a simple `apt-get install guix`.
After running
mkdir -p ~/opt guix pull -p ~/opt/guix-pull source ~/opt/guix-pull/etc/profile
we should be on the latest guix. This takes a while because guix packages get compiled. Note it is possible to install an earlier version of GNU Guix by passing in the git hash of the guix repository. Make sure guix-daemon has a large enough tmpdir (10Gb I would recommend).
After installing GNU Guix and running a `guix pull` we can install the latest package and cross-compile to RISC-V with a disconcertingly simple
guix build --target=riscv64-linux-gnu hello
This fetches the full build chain and installs
/gnu/store/fnsg59lb4c1gaqzbn553rdjcnam355gs-hello-2.10/bin/hello
Trying to run it will give `cannot execute binary file`. We'll need to use qemu to run a RISC-V binary. Let's install qemu in ~/opt/amd64-dev
guix package -i qemu -p ~/opt/amd64-dev
The `-p` switch creates of profile of symlinks so we can reach the tools easily. What is interesting is that qemu does not require a VM to run(!). We can now simply run:
~/opt/amd64-dev/bin/qemu-riscv64 /gnu/store/fnsg59lb4c1gaqzbn553rdjcnam355gs-hello-2.10/bin/hello Hello, world!
To view the shared libraries included in a binary we can use the `ldd` tool, part of the gcc-toolchain.
guix build --target=riscv64-linux-gnu gcc-toolchain --keep-going
this may take a while if not all binary substitutes are available (to get a list use the `--dry-run` switch. RISC-V is not much used yet, so this is likely the case. With more users we will get better coverage. The good news is that builds are in parallel (see -c and -M switches) and only happen once. And because it is cross-compilation, it will build relatively fast.
While trying above I found that gcc-toolchain is currently not building. WIP.
Another way to test for dependencies is to invoke
guix gc --references /gnu/store/mxiglsphimzg27ibyfgjfvy6gwrx6grd-hello-2.12 /gnu/store/1wijzqplqypcvlgmsnczj530ciq8ny8r-gcc-cross-riscv64-linux-gnu-10.3.0-lib /gnu/store/bzk4a5ip4mmprbw3f2af8l52zshc9dwl-glibc-cross-riscv64-linux-gnu-2.33 /gnu/store/mxiglsphimzg27ibyfgjfvy6gwrx6grd-hello-2.12
The AMD64 version shows that the binary is linked against the following shared libs:
ldd /gnu/store/khaaib6s836bk5kbik239hlk6n6ianc4-hello-2.11/bin/hello linux-vdso.so.1 (0x00007ffdff9b6000) libgcc_s.so.1 => /gnu/store/094bbaq6glba86h1d4cj16xhdi6fk2jl-gcc-10.3.0-lib/lib/libgcc_s.so.1 (0x00007f2571d1b000) libc.so.6 => /gnu/store/5h2w4qi9hk1qzzgi1w83220ydslinr4s-glibc-2.33/lib/libc.so.6 (0x00007f2571b59000) /gnu/store/5h2w4qi9hk1qzzgi1w83220ydslinr4s-glibc-2.33/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f2571d37000)
To build a static binary we need to modify the build script. I lifted the definition from guix packages and made the following guix.scm file:
(use-modules (guix download) (guix packages) (guix build-system gnu) (guix licenses)) (define-public hello (package (name "hello") (version "2.11") (source (origin (method url-fetch) (uri (string-append "mirror://gnu/hello/hello-" version ".tar.gz")) (sha256 (base32 "1g84a3hqs4pgx3yzs99cysv3iq440ncdw77bf03fsi1w5mby174c")))) (build-system gnu-build-system) (arguments `(#:make-flags '("CFLAGS=-static"))) (synopsis "Hello, GNU world: An example GNU package") (description "GNU Hello prints the message \"Hello, world!\" and then exits. It serves as an example of standard GNU coding practices. As such, it supports command-line arguments, multiple languages, and so on.") (home-page "https://www.gnu.org/software/hello/") (license gpl3+))) hello
The only addition is
(arguments `(#:make-flags '("CFLAGS=-static")))
This can be compiled with
guix build -f guix.scm
resulting in
/gnu/store/0nfr261c948mdfdj6pm7yffgws98kvi3-hello-2.11/bin/hello Hello, world! ldd /gnu/store/0nfr261c948mdfdj6pm7yffgws98kvi3-hello-2.11/bin/hello not a dynamic executable
Now this works, lets do the risc64 version:
guix build --target=riscv64-linux-gnu -f ../guix.scm /gnu/store/hk6l0hxq5fga9kcj2z65pxd93l841ws7-hello-2.11 ldd /gnu/store/hk6l0hxq5fga9kcj2z65pxd93l841ws7-hello-2.11/bin/hello not a dynamic executable ~/opt/amd64-dev/bin/qemu-riscv64 /gnu/store/hk6l0hxq5fga9kcj2z65pxd93l841ws7-hello-2.11/bin/hello Hello, world!
Success!
Let's try running hello on its own by copying the static binary and
deleting the installed package from the store
cp /gnu/store/hk6l0hxq5fga9kcj2z65pxd93l841ws7-hello-2.11/bin/hello hello-riscv64 guix gc -D /gnu/store/hk6l0hxq5fga9kcj2z65pxd93l841ws7-hello-2.11
and run standalone
~/opt/amd64-dev/bin/qemu-riscv64 hello-riscv64 Hello, world!
At this point we can take a GNU Guix package and cross compile that directly to RISC-V 64-bits with a standard toolchain. We can turn that into a statically linked binary that can be deployed anywhere.
In the near future we hope to show a native development environment running in a RISC-V container or virtual machine.
We thank the excellent free software GNU Mes and GNU Guix projects that make this work possible. We thank UTHSC and the NSF for funding RISC-V development for pangenomics and the NLNet foundation that is funding the GNU Mes bootstrapping effort for RISC-V. Efforts are underway to migrate all important GNU Guix packages to RISC-V, including for Rust development.