summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--content/bootstrapGcc/12_gcc_backported_works.md193
-rw-r--r--content/bootstrapGcc/13_tcc_to_gcc.md243
-rw-r--r--content/bootstrapGcc/14_g++4.6.4.md185
3 files changed, 621 insertions, 0 deletions
diff --git a/content/bootstrapGcc/12_gcc_backported_works.md b/content/bootstrapGcc/12_gcc_backported_works.md
new file mode 100644
index 0000000..9747c41
--- /dev/null
+++ b/content/bootstrapGcc/12_gcc_backported_works.md
@@ -0,0 +1,193 @@
+Title: GCC 4.6.4 with RISC-V support in Guix
+Date: 2024-04-02
+Modified: 2024-04-05
+Category:
+Tags: Bootstrapping GCC in RISC-V
+Slug: bootstrapGcc12
+Lang: en
+Summary:
+ We built GCC 4.6.4 with RISC-V support and C++ and all that and we made it
+ run in Guix, finally.
+
+Short post now, following what we did in [previous
+episodes](/bootstrapGcc10.html) 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][gcc] you can use for your own
+packages. If you know Guix, that's probably all you need to know.
+
+[gcc]: https://github.com/ekaitz-zarraga/gcc
+
+In my case, I did some ugly testing on this thing, so I made another folder,
+adjacent to the `gcc` project folder and made this[^ugly]:
+
+[^ugly]: 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.
+
+I added a `guix.scm` file:
+
+``` scheme
+(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:
+
+``` clike
+#include<iostream>
+int main (){
+ std::cout << "Hola!\n";
+ return 0;
+}
+```
+
+Jumped into the folder and called this:
+
+``` bash
+guix build -f guix.scm --system=riscv64-linux-gnu -K
+```
+
+Which gave me something like this, but way longer (beware of the `BLABLABLAH`):
+
+``` something
+$ 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):
+
+``` bash
+$ /gnu/store/dbkz567v66ry813svva2j3lnmdchb5r5-hello-2.12.1/bin/hola
+Hola!
+```
+
+Let's use `file` command just in case:
+
+``` bash
+$ 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:
+
+``` scheme
+(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.
diff --git a/content/bootstrapGcc/13_tcc_to_gcc.md b/content/bootstrapGcc/13_tcc_to_gcc.md
new file mode 100644
index 0000000..0d3bcde
--- /dev/null
+++ b/content/bootstrapGcc/13_tcc_to_gcc.md
@@ -0,0 +1,243 @@
+Title: TinyCC to GCC gap is slowly closing
+Date: 2024-05-02
+Category:
+Tags: Bootstrapping GCC in RISC-V
+Slug: bootstrapGcc13
+Lang: en
+Summary: The sidetrack we took in the past started to give us some good news.
+ Here there are some.
+
+In [previous episodes we talked about getting
+sidetracked](/bootstrapGcc11.html) and we mentioned we needed to build Musl
+because we had limitations in our standard library. We didn't explain them in
+detail and I think it's the moment to do so, as many of the changes we proposed
+there have been tested and upstreamed, and explain the ramifications that
+process had.
+
+#### Symptoms
+
+TinyCC and our MeslibC are powerful enough to build Binutils. But not enough to
+make some of the programs, like GNU As, work.
+
+MeslibC is supersimple, meaning it doesn't really implement some of the things
+you might consider obvious. One of the best examples is `fopen`. Instead of
+returning a fresh `FILE` structure, in MeslibC `fopen` simply returns the
+underlying file descriptor, as returned by the kernel's `open` call. This is
+not a big problem, as the `fread` and `fclose` provided with MeslibC are
+compatible with this behaviour, but there's a very specific case where this is
+a problem. In GNU As, if no file is given as an input, it just tries to read
+from standard input, and it fails, saying there was no valid file descriptor.
+Why? Let's read the code GNU As uses to read files (`gas/input-file.c`):
+
+``` clike
+/* Open the specified file, "" means stdin. Filename must not be null. */
+
+void
+input_file_open (const char *filename,
+ int pre)
+{
+ int c;
+ char buf[80];
+
+ preprocess = pre;
+
+ gas_assert (filename != 0); /* Filename may not be NULL. */
+ if (filename[0])
+ {
+ f_in = fopen (filename, FOPEN_RT);
+ file_name = filename;
+ }
+ else
+ {
+ /* Use stdin for the input file. */
+ f_in = stdin;
+ /* For error messages. */
+ file_name = _("{standard input}");
+ }
+
+ if (f_in == NULL)
+ {
+ as_bad (_("can't open %s for reading: %s"),
+ file_name, xstrerror (errno));
+ return;
+ }
+
+ c = getc (f_in);
+ /* ... Continues ...*/
+```
+
+If MeslibC uses file descriptor integers as `FILE` structures, it's not hard to
+detect the problem in the example. For the cases where the selected filename is
+empty (no file to read from) `filename[0]` will be false (`\0` character), and
+`f_in` will be set to `stdin`. That should normally mean some `FILE` structure
+with an internal file descriptor of value `0`, the one corresponding to the
+standard input. As the structure is not `NULL` the error message below won't
+trigger. As I just explained, MeslibC uses kernel's file descriptors instead of
+`FILE` structures so `stdin` in MeslibC is just `0`, which is equal to `NULL`
+for the compiler, so the error message is triggered and the execution stops.
+
+MeslibC's clever solution for filenames is simply failing due to the fact that
+C has no error types, and errors are signalled in the standard library using
+`NULL`.
+
+This is just a simple case to exemplify how MeslibC affects our bootstrapping
+chain, but there are others. For example, MeslibC can't `ungetc` more than once
+because that was enough for the bootstrapping as it was designed for x86, but
+as we moved to a more recent binutils version (the first one supporting
+RISC-V), that became an obstacle, and it's preventing us from running GNU As.
+
+Of course, all of these problems could be fixed in MeslibC, but in the end the
+goal of MeslibC is not to be a proper C standard library implementation, but a
+helper for the bootstrapping of more powerful standard libraries that already
+exist. These problems, and some others we also found, are just drawing the line
+of *when* do we need to jump to a more mature C standard library in our chain.
+Looks like binutils is where that line is drawn.
+
+#### Musl
+
+The bootstrapping chain as conceived in Guix uses GLibC, as Guix is a GNU
+project, but we found Musl to be a more suitable C standard library for these
+initial steps as it is simple an easy to build while keeping all the
+functionality you might expect from a proper C standard library.
+
+We ran into some issues though, as upstream TinyCC's RISC-V backend wasn't
+ready to build it.
+
+First of all, TinyCC's RISC-V backend had no support for Extended ASM, so I
+implemented it and sent it upstream.
+
+Once I did that we built Musl and we realized we had issues in some functions.
+The problem was the Extended Asm implementation was not understanding the
+constraints properly and those parameters marked as read and write were not
+considered correctly. I talked with Michael, the author of that piece of code,
+because I didn't understand the behaviour well. He guided me a little and I
+proceeded to fix it in all architectures.
+
+Still, we couldn't build Musl because it was using some atomic instructions
+that were not implemented in TinyCC's RISC-V assembler and we decided to avoid
+them, patching around them in Musl. They happened to be important for memory
+allocation (LOL) so I decided to implement them in TinyCC's assembler and push
+the changes upstream. I implemented `lr` (load reserved), `sc` (store
+conditional) and extended `fence`'s behaviour to match what the GNU Assembler
+(the reference RISC-V assembler) would do.
+
+Still this wasn't enough for Musl to build properly as TinyCC's RISC-V backed
+was not implemented as a proper assembly but as instructions in human readable
+text. RISC-V is a RISC architecture and makes a heavy use of pseudoinstructions
+to ease the development of assembly programs. Before all this work, TinyCC
+only implemented simple instructions and almost no pseudoinstruction expansion.
+
+Also, its architecture couples argument parsing with relocation generation and
+it doesn't really help to implement pseudoinstructions with variable argument
+count or default values. I added enough code to avoid falling in the problems
+this design decision had and pushed everything upstream. The list includes
+support for many pseudoinstructions, proper relocation use for several
+instruction families like `jal` and branches, and some other things. In the
+end, we do not have a fully featured assembler yet, but we do have enough to
+build the simple code we find in a C standard library like Musl. In fact, even
+using the syntax that any RISC-V assembler would expect, as I explained in
+more detail [here](/bootstrapGcc11.html).
+
+#### Meslibc
+
+Once all those changes are finally applied to TinyCC, we can remove the weird
+split we needed to do in MeslibC to support make it match the TinyCC assembly
+syntax, so I did that. Less code, less problems.
+
+Also my colleague Andrius added a `realpath` stub, to make us able to build
+upstream TinyCC without having to patch the places where `realpath` was used in
+it. `realpath` is not a simple function to implement, and it's not critical in
+TinyCC. Again MeslibC doesn't need to be perfect, only let us start building
+everything.
+
+#### TinyCC
+
+With all those changes coming to MeslibC and the ones we upstreamed, we now
+don't need to patch on top of upstream TinyCC, so all our small changes on top
+of it are dropped now. Less code, less problems.
+
+We could have kept these changes for ourselves, but sharing them is not only
+easier, but also better for everyone. The following is the complete list of
+changes I upstreamed to TinyCC, a project that we are not really part of, but
+this is what we do and what we believe in.
+
+* `0aca8611` fixup! riscv: Implement large addend for global address
+* `8baadb3b` riscv: asm: implement `j offset`
+* `15977630` riscv: asm: Add branch to label
+* `671d03f9` riscv: Add full `fence` instruction support
+* `c9940681` riscv: asm: Add load-reserved and store-conditional
+* `0703df1a` Fix Extended Asm ignored constraints
+* `6b3cfdd0` riscv: Add extended assembly support
+* `e02eec6b` riscv: fix jal: fix reloc and parsing
+* `02391334` fixup! riscv: Add .option assembly directive (unimp)
+* `cbe70fa6` riscv: Add .option assembly directive (unimp)
+* `618c1734` riscv: libtcc1.c support some builtins for \_\_riscv
+* `3782da8d` riscv: Support $ in identifiers in extended asm.
+* `e2d8eb3d` riscv: jal: Add pseudo instruction support
+* `409007c9` riscv: jalr: implement pseudo and parse like GAS
+* `8bfef6ab` riscv: Add pseudoinstructions
+* `8cbbd2b8` riscv: Use GAS syntax for loads/stores:
+* `019d10fc` riscv: Move operand parsing to a separate function
+* `7bc0cb5b` riscv: Implement large addend for global address
+
+#### Bootstrappable TinyCC
+
+During the bootstrapping process we detected new issues and one of them was so
+deep it took pretty long to detect and solve.
+
+Most of the programs we were building with our Bootstrappable TinyCC worked:
+GZip, Make... But we reached a point were we needed to rebuild upstream TinyCC
+with Musl, in order to start using Musl to build the next programs. It didn't
+work.
+
+We had a really hard time finding the problem behind this because it appeared
+too far in the chain to be easy. The process goes like this.
+
+We use Mes to build our very first Bootstrappable TinyCC, which compiles itself
+several times (6), until it reaches its final state. That then builds upstream
+TinyCC and with that we build TinyCC again this time using Musl as its standard
+library. We found this last one was unable to build simple files and we started
+digging.
+
+We realized TinyCC was using sign extension in `unsigned` values, and that was
+messing up with the next TinyCC, making it unable to build programs correctly.
+Researching this deeply we found the problem was in the `load` function of
+TinyCC but a TinyCC built with GCC didn't have this problem. The only option
+was that the Bootstrappable TinyCC had the bug that was later affecting the
+compilers compiled with it.
+
+Digging a little bit further I found the casts from Bootstrappable TinyCC had
+some missing cases that I didn't backport properly but as I wasn't able to
+understand them very well I decided to backport the full `gen_cast` function
+from upstream to the Bootstrappable TinyCC. With that, the errors from TinyCC
+were gone.
+
+It feels like an accidental trusting trust attack, yes. This is the kind of
+things we have to deal with, and they are pretty tiring and frustrating to
+find.
+
+#### The new Bootstrapping chain
+
+So, all of this brings us to the new bootstrapping chain. We need to make
+things very different to the way Guix does them right now, because we are
+skipping many steps (GCC 2.95, now we need Musl for Binutils...) so I started
+[a project](https://github.com/ekaitz-zarraga/commencement.scm) to track how we
+go forward in the bootstrapping chain (it's just a wip, for our tests, take
+that in account).
+
+We had good and bad news in that regard. At the moment of writing we managed to
+build up to the GCC 4.6.4 I added RISC-V support to, but the compiler is faulty
+and it's unable to build itself again with the C++ support.
+
+I'm using non-bootstrapped versions of `flex` and `bison`, but those
+shouldn't be hard to bootstrap either. I just didn't have the time to make them
+from scratch. And I'm using a `bash` instead of `gash` because we had found a
+blocking error in `gash` that is not letting us continue forward from Binutils.
+
+In any case, this means we are near from the next milestone: building GCC 4.6.4
+with TinyCC; and as we described in the previous post we already built GCC 7.5
+from GCC 4.6.4 so we solved the next already.
+
+After those, we would need to clean this new bootstrapping chain and talk with
+Guix for its inclusion in there. I hope we can finish all this before hitting
+the deadline that is silently approaching...
diff --git a/content/bootstrapGcc/14_g++4.6.4.md b/content/bootstrapGcc/14_g++4.6.4.md
new file mode 100644
index 0000000..9df600f
--- /dev/null
+++ b/content/bootstrapGcc/14_g++4.6.4.md
@@ -0,0 +1,185 @@
+Title: Milestone – Bootstrapped GCC 4.6.4 for RISC-V
+Date: 2024-05-17
+Category:
+Tags: Bootstrapping GCC in RISC-V
+Slug: bootstrapGcc14
+Lang: en
+Summary: So yeah, we bootstrapped GCC 4.6.4 for RISC-V. We even have C++
+ support!
+
+In latest posts we talked about many things: problems, our changes to other
+projects and other things. Now it's time to actually talk about something we
+actually *did*.
+
+But first, we fixed more extra things... This is a never ending story.
+
+### The things we need to deal with
+
+We have been trying to build GCC 4.6.4 with the backported RISC-V support using
+TinyCC. We already did a GCC 4.6.4 that worked but we only tested it building
+with a modern GCC. Building with a TinyCC with an incomplete backend that we
+had to improve ourselves is not that obvious as it would be with the very well
+established architecture like i386.
+
+We could build a minimal GCC, from TinyCC and Musl, but it didn't work. Me and
+my colleague Andrius Štikonas detected and patched around a problem that we
+still don't know where it is coming from ([we reported upstream][upstream]).
+This is the only one we need to apply to GCC, as we fixed many things in
+TinyCC.
+
+[upstream]: https://lists.nongnu.org/archive/html/tinycc-devel/2024-04/msg00028.html
+
+This simple patch was enough to build the whole GCC. Can you spot the
+difference?
+
+We find this kind of problems making small reproducers that we tried to tweak,
+and happened to work if we split things.
+
+``` diff
+diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
+index d05f8149170..d4ef8de4813 100644
+--- a/gcc/tree-ssa-operands.c
++++ b/gcc/tree-ssa-operands.c
+@@ -300,6 +300,7 @@ static inline void *
+ ssa_operand_alloc (unsigned size)
+ {
+ char *ptr;
++ int x;
+
+ gcc_assert (size == sizeof (struct use_optype_d)
+ || size == sizeof (struct def_optype_d));
+@@ -334,8 +335,8 @@ ssa_operand_alloc (unsigned size)
+ gimple_ssa_operands (cfun)->operand_memory_index = 0;
+ }
+
+- ptr = &(gimple_ssa_operands (cfun)->operand_memory
+- ->mem[gimple_ssa_operands (cfun)->operand_memory_index]);
++ x = gimple_ssa_operands (cfun)->operand_memory_index;
++ ptr = &(gimple_ssa_operands (cfun)->operand_memory->mem[x]);
+ gimple_ssa_operands (cfun)->operand_memory_index += size;
+ return ptr;
+ }
+```
+
+### We need to rebuild with Musl
+
+Once that very first GCC compiles, it's necessary to rebuild Musl with that
+GCC, and use the new GCC+Musl combination to rebuild GCC, now adding the C++
+support we missed first time.
+
+This gives us several things: a more stable GCC and a better Musl, that is
+compatible with GCC.
+
+If we don't do that, and we don't rebuild Musl, we see errors when building the
+second GCC, the `genmddeps` program, which is created and run during build
+process of GCC just fails.
+
+Also, we have to `--disable-bootstrap`, so rebuilding it is like doing the
+GCC's bootstrap ourselves.
+
+### Backport Musl support to GCC 4.6.4
+
+Next thing, remember from previous posts why we had to use Musl for our
+process. First, because it's a fully-featured C standard library; second,
+because it's simple and easy to build and, lastly, because we can't use GlibC:
+the newest version we can build doesn't support RISC-V.
+
+The main problem we have with GCC 4.6.4 since we started with all this journey
+is that 4.6.4 was written before our architecture, RISC-V, was invented, and
+this also happened with Musl.
+
+Andrius detected some missing declarations during the compilation process of
+the `libstdc++`, which happened because GCC was trying to use some GlibC
+specific functions for the build we didn't have, as we were using Musl instead.
+
+Turns out GCC needs extra configuration for Musl, that was added after our
+version was released, so I backported all that (not much) to GCC 4.6.4. Maybe I
+missed something, but now we can build GCC 4.6.4 with C++ support, using Musl,
+for RISC-V!
+
+### But it doesn't work!
+
+Right after building it, we tried to use it on a simple program:
+
+``` clike
+#include<iostream>
+
+int main (int argc, char* argv[]){
+ std::cout << "Hello World" << std::endl;
+ return 10;
+}
+```
+
+But this returns a huge set of errors looking like:
+
+``` something
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(c++locale.o): In function `.L0 ':
+(.text._ZSt14__convert_to_vIfEvPKcRT_RSt12_Ios_IostateRKPi+0x3a): undefined reference to `operator new[](unsigned long)'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(c++locale.o): In function `.L15':
+(.text._ZSt14__convert_to_vIfEvPKcRT_RSt12_Ios_IostateRKPi+0x172): undefined reference to `operator delete[](void*)'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(c++locale.o): In function `.L11':
+(.text._ZSt14__convert_to_vIfEvPKcRT_RSt12_Ios_IostateRKPi+0x190): undefined reference to `__cxa_call_unexpected'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(c++locale.o): In function `.L0 ':
+(.text._ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi+0x3a): undefined reference to `operator new[](unsigned long)'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(c++locale.o): In function `.L39':
+(.text._ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi+0x1b4): undefined reference to `__cxa_call_unexpected'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L23':
+(.text._ZNSi6ignoreEl+0x21c): undefined reference to `__cxa_end_catch'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L24':
+(.text._ZNSi6ignoreEl+0x22e): undefined reference to `__cxa_end_catch'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.LEHB2':
+(.text._ZNSi6ignoreEl+0x24c): undefined reference to `__cxa_begin_catch'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L31':
+(.text._ZNSi6ignoreEl+0x272): undefined reference to `__cxa_rethrow'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.LEHE2':
+(.text._ZNSi6ignoreEl+0x27c): undefined reference to `__cxa_begin_catch'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L30':
+(.text._ZNSi6ignoreEl+0x29c): undefined reference to `__cxa_end_catch'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L51':
+(.text._ZNSt13basic_istreamIwSt11char_traitsIwEE6ignoreEl+0x22c): undefined reference to `__cxa_end_catch'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L52':
+(.text._ZNSt13basic_istreamIwSt11char_traitsIwEE6ignoreEl+0x23e): undefined reference to `__cxa_end_catch'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.LEHB9':
+(.text._ZNSt13basic_istreamIwSt11char_traitsIwEE6ignoreEl+0x25c): undefined reference to `__cxa_begin_catch'
+/gnu/store/f3chm93gvrina083lqp36qpf2w4fc3f1-profile/lib/libstdc++.a(compatibility.o): In function `.L59':
+(.text._ZNSt13basic_istreamIwSt11char_traitsIwEE6ignoreEl+0x282): undefined reference to `__cxa_rethrow'
+collect2: ld returned 1 exit status
+```
+
+Again, Andrius detected there was a line in the huge logs we have that said we
+were missing the `find` command. So we added it, and worked[^until-it-broke].
+
+[^until-it-broke]: There's something weird in this case, if I do a change like
+ this one below it fails:
+ <!-- Using a markdown fenced code block here fails -->
+
+ <pre class="language-diff">
+ <code class="language-diff">
+ (native-inputs `(("gcc" ,gcc-muslboot0)
+ ("libc" ,musl-boot)
+ - ("find" ,findutils)
+ ,@(modify-inputs (package-native-inputs gcc-muslboot0)
+ + (append findutils)
+ (replace "make" gnu-make-muslboot)
+ (delete "libc")
+ (delete "tcc"))))
+ </code>
+ </pre>
+
+### The thing built, and worked!
+
+So we managed to make it build and run, improving TinyCC in the process. Now
+TinyCC can build Musl and GCC 4.6.4 (with a very small patch), and that GCC is
+able to build itself, adding C++ support. And of course, the thing works!
+
+You can try if this thing worked, and see how, in the
+[`commencement.scm`][commencement] project where I'm keeping track of all this.
+
+[commencement]: https://github.com/ekaitz-zarraga/commencement.scm/commit/9bbb1c61a87e206fb275c3040d0493beba6ae0fe
+
+### Next
+
+So yeah, success but this didn't end. Now we need to use that GCC to build GCC
+7.5, and compile the world with it.
+
+Cross fingers.