Dr. Brian Robert Callahan
academic, developer, with an eye towards a brighter techno-social life
TLDR: Binaries are here.
I have a fleet of old PowerPC Macs: two iMac G4s, a PowerBook G4, an iBook G4, and an iBook G3. I've always wanted to get a modern web browser running on it. While TenFourFox is great it is not quite the same as a modern Chromium or Firefox or WebKit.
But the first thing I need is a modern compiler. See, Mac OS X 10.4 Tiger came with GCC 4.0.1, released in July 2005. We will need something a little more modern if we are to build large modern codebases.
LLVM dropped support for PowerPC/Darwin a long time ago. But GCC still supports it. But I read somewhere that the GCC people only support Mac OS X 10.5 Leopard on PowerPC. Thankfully, I've never let people smarter than me get in the way of my bad ideas. We're going to ignore them and get a native GCC 14.2.0 for Tiger.
I started by using Apple's software updater to update the machine to 10.4.11 and get all the updates for everything. Thanks Apple for still having all that stuff available to download. I also installed Xcode 2.5.
I read somewhere that you don't want the ld
that is installed with Xcode 2.5. Instead, you want ld64-97.17
, which you can get on Tigerbrew. I want my package of modern GCC to be self-contained, so I installed ld64
and then copied everything over to /opt/gcc14
.
I also heard that cctools-806
was the last version to support Tiger on PowerPC, so same thing: installed it from Tigerbrew and then copied everything over to /opt/gcc14
.
But it was not that simple. Modern versions of GCC emit a -mmacosx-version-min=
flag by default, set to -mmacosx-version-min=10.4
on Tiger. However, cctools-806
does not understand that flag. I would need a copy of the source code and would need to make some modifications. I had to teach the assembler that if we see that flag, we should simply ignore it.
There was one other issue that we had is that modern versions of GCC also emit a .macosx_version_min
line in the assembly output, which cctools-806
also does not understand. All I needed to do was teach the assembler if it ever comes across such a line, the entire line should be ignored.
The patch to make these changes is here.
Now I was able to rebuild the assembler and install it and all the rest of the cctools to /opt/gcc14
.
Tiger ships with GNU bash, version 2.05b.0(1)-release (powerpc-apple-darwin8.0)
out of the box. This is insufficient for building modern GCC; you will encounter a bunch of difficult to understand errors with that old version of bash.
To overcome this, I started by installing the apple-gcc42 formula
from Tigerbrew. This got me gcc-4.2.1
, and this compiler was good enough to build bash-5.2.37(1)-release
and this version of bash is plenty modern to build modern GCC. I needed to install the new shell into both /bin/bash
and /bin/sh
.
As far as I can tell, Mac OS X is happy with this new shell; I can reboot the machine just fine (something you cannot do if you install mksh as /bin/sh
, something I found out the hard way) and everything else feels as if I had not upgraded the shell, which I suppose is exactly what we want.
Now I could build GCC. However, I could not simply go from the gcc-4.0.1
straight to gcc-14.2.0
. We had to take it step by step.
I decided I would use gcc-4.2.1
as my starting compiler. I already had it from building bash, and 4.2.1 is closer to 14.2.0 than 4.0.1 is. Next, I downloaded GCC 4.7.4. Why? Because that was the last version that could be bootstrapped with an ISO C89 compiler according to the GCC website. From 4.8 to 10.4 requires an ISO C++98 compiler, 10.5 to 14.2 requires an ISO C++11 compiler, and 15 now requires a C++14 compiler. I was not sure if 4.2.1 qualified as a sufficient C++98 compiler, so I went with 4.7.4, since that version has enough C++11 support to move forward.
A newer GNU make was in order, grabbed from Tigerbrew.
I also installed gmp
, mpfr
, and libmpc
from Tigerbrew to have all the necessary library dependencies for GCC.
Using gcc-4.2.1
, I built gcc-4.7.4
with the following configure
invocation:
../gcc-4.7.4/configure --disable-checking --prefix=/opt/gcc47 --enable-languages=c,c++,objc,obj-c++ --with-as=/opt/gcc14/bin/as --with-ld=/opt/gcc14/bin/ld --disable-nls --disable-multilib --disable-bootstrap
And then built it with gmake
.
Because we are not really keeping GCC 4.7.4 around, I am not particularly interested in whether or not it can bootstrap itself. It just needs to be good enough to bootstrap the next version of GCC we build. This also saved an incredible amount of time. Turns out a 1.25 GHz PowerPC G4 with 1 GB of RAM, and building everything on a 128 GB USB flash drive over USB 2.0 is very slow. Who knew?
The GCC website recommends using gcc-9.5.0
as a good intermediate version to bootstrap later versions of GCC, as this is the version where C++17 support was declared stable. This version of GCC should be able to bootstrap future versions of GCC for quite some time.
I built GCC 9.5.0 the same way as 4.7.4:
../gcc-9.5.0/configure --disable-checking --prefix=/opt/gcc95 --enable-languages=c,c++,objc,obj-c++ --with-as=/opt/gcc14/bin/as --with-ld=/opt/gcc14/bin/ld --disable-nls --disable-multilib --disable-bootstrap
And again built it with gmake
.
As before, I'm not keeping this version of GCC; it only needs to be good enough to bootstrap the next version of GCC so it doesn't matter if it can bootstrap itself.
Now we can move on up to gcc-14.2.0
. If this works, we will have a modern GCC for PowerPC Tiger.
Because I want this GCC to be entirely self-contained so that it can be shipped to others and used without any external dependencies, I chose to place the gmp
, mpfr
, libmpc
, and isl
libraries into the GCC source tree so that GCC would build and link them statically into the compiler. The only two library dependencies are /usr/lib/libiconv.2.dylib
and /usr/lib/libSystem.B.dylib
, both included in the installation of the Tiger.
Now for the moment of truth, I configured GCC 14.2.0 as follows:
../gcc-14.2.0/configure --disable-checking --prefix=/opt/gcc14 --enable-languages=c,c++,fortran,objc,obj-c++ --with-as=/opt/gcc14/bin/as --with-ld=/opt/gcc14/bin/ld --with-sysroot=/Developer/SDKs/MacOSX10.4u.sdk --disable-multilib
We could have probably also included the Modula-2 frontend; I'll do that when GCC 15.1 is released.
One gmake
command later, and now we wait. For a very long time. I do want to make sure this version of GCC can bootstrap itself.
After quite a lot of waiting, the build finished successfully.
I started building some pkgsrc packages with my new compiler. I discovered some of the headers shipped with Xcode 2.5 needed some tweaking. You can grab the patch here. More patching will probably be needed.
We can certainly build future versions of GCC with our modern compiler. I would like to ship all the headers from Xcode 2.5 updated to modern C standards (and used by default with GCC). We could also use a library that adds all the new C functions that have been added to the standard library since 2005 and linked by default when the C standard library is also linked.
We did it. We were able to get the latest version of GCC running on PowerPC Tiger and it works well. I already have a bunch of pkgsrc packages built, like GNU coreutils 9.5, OpenSSL 3.3.2, OpenSSHi 9.9p1, wget 1.25.0, curl 8.11.1, vim 9.1 with patches 1-789, Python 3.12, Perl 5.40.0, and ninja 1.12.1, with more packages on the way. I'll have to find a place to post them too.
You can grab a tarball here. Also included there are tar(1)
and gzip(1)
utilities in case you need them on your Tiger machine.