summaryrefslogtreecommitdiff
path: root/content/bootstrapGcc/10_gcc_riscv_c++.md
blob: 4501d0de9388b7c3a0356279d5ba6c41337fc601 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
Title: GCC 4.6.4 with RISC-V support
Date: 2024-03-28
Category:
Tags: Bootstrapping GCC in RISC-V
Slug: bootstrapGcc10
Lang: en
Summary:
    We built GCC 4.6.4 with RISC-V support and C++ and all that in a Debian
    machine, in a VisionFive board. Here is how.

I already mentioned at the [FOSDEM-2024][fosdem2024] 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).

[fosdem2024]: https://fosdem.org/2024/schedule/event/fosdem-2024-1755-risc-v-bootstrapping-in-guix-and-live-bootstrap/

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:

``` bash
$ sudo apt install build-essential git
```

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

``` bash
$ 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.

``` bash
$ 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.

``` bash
$ 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
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:

``` bash
$ ./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.