Well, that's the theory. In practice this is only going to work on
some platforms, such as x86 Linux, because there's a hidden dependency
or two in this sequence of bootstrapping. The big hidden dependency is
long term operating system compatibility with 'old' binaries. When
you build Go 1.4 with your modern C compiler and OS, you will get a
modern binary that calls your modern C standard library and kernel
system calls in the appropriate way. But when you use your newly built
Go 1.4 to build Go 1.19, the Go binary it produces is one that was
effectively frozen around the time Go 1.4 was released; it makes the
system calls and expects the ABIs and so on that were current then,
not that are current now. Then the binary of Go 1.21 that your Go 1.19
toolchain produces will similarly be frozen at the state of ABIs as of
Go 1.19, and so on.
The Linux kernel is extremely good about backwards compatibility with
old binaries; binaries that are literally decades old can and will
still run happily. On Linux, you can expect this sequence of 'new old
stock' Go toolchain binaries to work without problems. But not all
operating systems consider binary backward compatibility to be
critical, or even deeply important. For example, OpenBSD doesn't
guarantee it will maintain ABI compatibility between releases (cf) and in the past it's made changes that
mattered for Go. I wouldn't be surprised if
older versions of the Go toolchain produce binaries that won't run on
the current version of OpenBSD, which would obviously complicate a
from-scratch bootstrapping of Go on OpenBSD.
The other hidden dependency is on how any outside programs used by the toolchain work, for example what specific arguments they accept or require. If your language's toolchain at some point uses the standard system linker, assembler, C compiler, or whatever, it depends on being able to pass them the right arguments and in general for them to operate the way it expects. Old versions of your toolchain will be using the command line arguments for outside programs that were current when those old toolchains were supported, not the ones you may need today, possibly years after the fact. Not all language toolchains are self-contained the way Go (mostly) is; it's perfectly reasonable to use the system assembler or linker or whatever rather than write your own (in addition to your actual compiler system). But this leaves you depending on their command line arguments and how they work, and often the programs don't consider that sort of thing a stable API that has to be preserved over the long term.
(As covered in the Go documentation, Go has
actually had to update the old 'Go 1.4' toolchain in order to keep it
working on more modern systems. You can get an idea of the changes
necessary by looking at the Go 1.4 branch's commit log.)
09
October
2026.
| | |
| « | On modern hardware, who handles what bit of hardware state can be unclear |
| Why have policies even if you aren't going to enforce them much | » |