Notes on cross-compiling GHC for a Darwin target.
TL;DR I managed to get most of a stage1 to build. I got a linker failure during ghc-prim
,
but most of the libraries had already built successfully, including some C FFI-heavy
packages like bytestring
. I suspect my toolchain was just in the wrong spot, and/or libraries
misconfigured.
- We need a normal host GCC toolchain (
build-essential
),autoconf
,happy
,alex
, and a platform copy of GHC (the Stage0). - As per the GHC CrossCompiling page on Trac, we need a GCC crosschain. I used
osxcross
. - We also need
binutils
, which don't come withosxcross
. I might have gone wrong here: I built these using the host's GCC chain, with--target=x86_64-apple-darwin
. The configure script confirmed that we were cross-compiling, but still proceeds with the 'can we run a GCC-compiled file' check, which suggested to me that this was the right way to go. We need to runobjdump
andreadelf
on the host, so it makes sense to use the host GCC. But not sure. - We need
ncurses
andtinfo
headers. Supposedly ncurses is just for GHCI (which we don't need), whiletinfo
ends up in theterminfo
library, which we build with our Stage1 and link into target binaries. - We need a GHC source tree, checked out for the whatever version we want to build. Their submodules are broken
if you clone the copy on GitHub, so either clone it direct from Haskell.org or paste some git config into a
terminal (find the relevant lines on the Getting The Sources page on Trac). Check out the tag you want
(
ghc-7.10.3-release
in my case), and don't forget to synchronise your submodules (git submodule init; git submodule update
). I wasted about 30 minutes googling CPP errors because my submodules all pointed toHEAD
. - We need a
mk/build.mk
to disable Stage2. Usually the Stage0 builds a Stage1, which then builds a Stage2. In our case, the Stage1 produces binaries that our host platform can't run, so the Stage2 wouldn't be useful. I just used the presetquick-cross
, note that this builds with-O0
and shipsinteger-simple
instead ofinteger-gmp
. We want to successfully build and useinteger-gmp
before we can use this cross-compiler in production. However, those are problems for after `"Hello world!" configure.ac
checks for some Xcode artefacts when the target is set to Darwin. This seems to be a bug, it probably should only check when the host is Darwin. I just edited that segment out of the configure script. If it detects an old version of Xcode, it disables split-objs../boot
- run the perl script to do library configuration thingsautoreconf
to generateconfigure
- Configure for cross-compilation. As the CrossCompiling page says,
--target=x86_64-apple-darwin
is the least we need here. In my case,osxcross
(or the dodgy Dockerfile I used to install it) does not prefix the toolchain in the correct way, so I had to manually override the locations ofghc
,ld
,ar
,as
,ranlib
,objdump
, andreadelf
. We also needinstall_name_tool
on PATH. make
There were lots of subtly wrong things in my setup here. It's not really surprising that it died with a linker error;
it might have been using the wrong ar
or as
or ld
; I'm also pretty sure my binutils weren't where I thought they were.
When trying again, I'll use osxcross
to bootstrap a clean install of gcc
, and make sure all my toolchain have the proper
x86_64-apple-darwin
prefix. That way the host and target toolchains can share a namespace in the way that almost every build script
seems to expect.