Skip to content

Updating the Bootstrap Compiler

PÁLI Gábor János edited this page Aug 15, 2015 · 10 revisions

Generic Notes

GHC needs a working GHC in order to be built. This is currently solved by having a pre-built binary distribution of GHC prepared that is first installed and then used to build the sources.

  • GHC has some requirement on the version of the bootstrap compiler, something like version N.M can be only built with a compiler of version N.(M - 4) at least. For example, building the GHC 7.6.x ports requires a GHC 7.2.x bootstrap compiler at minimum. Usually it is fine to have the same version as the port itself, but since rolling a new version of the bootstrap out takes time and space, it is a good idea to change it only when it is really required.

  • The version of the bootstrap compiler is controlled by the BOOT_GHC_VERSION variable in the Makefile of lang/ghc. This should be always in sync with the bootstraps available in the distinfo file.

  • Optionally, the user may use the existing GHC by choosing the BOOT option at configure. Note that this is only available if ${LOCALBASE}/bin/ghc exists.

  • The bootstrap compiler is a lite version of the original compiler, without documentation and with the less (base system and port) dependencies as possible. However, those dependencies may change inevitably. In this case, the bootstrap for the affected versions and architectures must be rebuilt and lang/ghc must be updated.

  • The bootstraps shall be available for all supported operating system versions and architectures. As of the time of writing, this is 9.x (9.3), 10.x (10.1), and head, for i386 (32-bit) and amd64 (64-bit). This means one shall maintain the bootstraps separately for every possible combination.

  • A pre-built binary for the compiler may be fetched from the GHC web site which may be then used for bootstrapping. It shall work for 8.4-RELEASE or later systems, although one may need to hack it around a bit (like installing the misc/compat8x port on non-8.x systems) to make it work.

Building the Bootstrap Compiler

Here are the recommended steps for rebuilding the bootstrap compiler.

Prerequisites

The following assumptions must be held for the build environment:

  • It must be a clean build environment, containing only the software components there are indispensable for the build. Hence setting up a separate jail(8) or chroot(8) environment for this purpose is highly recommended. The details of this is not elaborated here.

  • All the build tools must be available. This also means that if any of the run-time dependencies change in any incompatible way, a new bootstrap is needed.

    • converters/libiconv
    • devel/autoconf
    • devel/automake
    • devel/binutils
    • devel/gmake
    • lang/gcc
    • lang/perl5.20
    • Some working version of GHC (see the Generic Notes above).

Note that the most problems will probably be with the last item, the working version of GHC. For this, there is no generic recipe. Try to make it work at all costs, otherwise it will not be possible to rebuild the bootstrap for the port.

Getting the GHC Sources

GHC sources, along with the pre-built binaries, can be found at its web site, in the dist directory by the versions:

http://www.haskell.org/ghc/dist/

For example, fetching the sources for version 7.10.2 can be done by:

# fetch http://www.haskell.org/ghc/dist/7.10.2/ghc-7.10.2-src.tar.xz

Note that only the ghc-${GHC_VERSION}-src.tar.xz file is needed. Once it is downloaded, just unpack it:

# tar -xf ghc-7.10.2-src.tar.xz

Configuring the Build

Before running the associated configure script, a customized build.mk file shall be created under the mk directory in the GHC source tree. This will help to cut down on the dependencies and build the lite version of the compiler. Note that the full list of build options can be found in the mk/build.mk.sample file.

# cd ghc-7.10.2
# echo GhcLibWays = v > mk/build.mk
# echo XMLDocWays = >> mk/build.mk
# echo HADDOCK_DOCS = >> mk/build.mk
# echo HSCOLOUR_SRCS = >> mk/build.mk
# echo INTEGER_LIBRARY = integer-simple >> mk/build.mk
# echo DYNAMIC_GHC_PROGRAMS = >> mk/build.mk
# echo 'BIN_DIST_NAME = ghc-$(ProjectVersion)-boot' >> mk/build.mk
# echo 'BIN_DIST_TAR  = ghc-$(ProjectVersion)-boot.tar' >> mk/build.mk

Now the configure script may be run.

# env CC=gcc48 ./configure --with-iconv-includes=$LOCALBASE/include --with-iconv-libraries=$LOCALBASE/lib \
  --with-gcc=$LOCALBASE/bin/gcc48 --with-ld=$LOCALBASE/bin/ld

where $LOCALBASE is usually /usr/local/.

Patching the Sources

Sometimes it may happen that the vanilla sources do not build properly, hence they have to be fixed up first. For example, integer-simple suffered some build problems in version 7.6.3 that has to be addressed. (Fortunately, this has been fixed since then, but the release is still had this bug...) One may also experience build problems with the newer version of dependencies (such as iconv(3) symbols are shuffled around) which can be solved here.

Again, no generic recipes can be given here. Be careful, this step requires some familiarity with the GHC build system and the Haskell programming language itself. Though, this step may be skipped in a lucky case :-) For documentation on the build system and other internals of GHC, see the GHC Developer Wiki.

Launching the Build

After the configuration has completed, simply launch GNU make(1), even on multiple threads. However, the build parallelism in the GHC build system does not work out well above about four concurrent threads.

# gmake -j 4

Creating the Bindist File

Once the build has finished without problems, the bootstrap distribution shall be built. This is what GHC calls "binary distribution" or "bindist". Thus it is done by invoking the binary-dist make(1) target. Here, the TAR_COMP variable is also recommended to set to xz so the resulting tarball will be compressed with xz(1) and becomes smaller in size (but it will take more time to create).

# gmake binary-dist TAR_COMP=xz

Adding the Bindist to the Port

In order to add the bindist to the lang/ghc port, the bindist file has to be renamed and the associated distfile information (SHA256 checksum and file size) has to be generated for it.

# mv ghc-${GHC_VERSION}-boot-${GHC_ARCH}-unknown-freebsd.tar.xz ghc-${GHC_VERSION}-${ARCH}-freebsd${FREEBSD_MAJOR_VERSION}-boot.tar.xz
# sha256 ghc-${GHC_VERSION}-${ARCH}-freebsd${FREEBSD_MAJOR_VERSION}-boot.tar.xz > distinfo.txt
# echo -n "SIZE (ghc-${GHC_VERSION}-${ARCH}-freebsd${FREEBSD_MAJOR_VERSION}-boot.tar.xz) = " >> distinfo.txt
# stat -f %z ghc-${GHC_VERSION}-${ARCH}-freebsd${FREEBSD_MAJOR_VERSION}-boot.tar.xz >> distinfo.txt

Note that the ${GHC_ARCH} may be different from ${ARCH}. Namely, the 64-bit x86 platform is called x86_64 in GHC's terminology, while this is amd64 for FreeBSD.

Update distinfo with the contents of the generated distinfo.txt file under lang/ghc. The Makefile for the port has to be also edited to accommodate the new file in the DISTFILES variable.