Comprehensive overview of using the Build System

This part of the guide is about using the build system, that is, how to interact with the build system when you're developing some part of GHC, its libraries or tools. The section aims to be comprehensive; for a quick start, read Contributing first.

Booting, configuring, cleaning

GHC uses the autoconf tools in the standard Unixy way, described in more detail in subsequent subsections on this page:

      |             |
      | Source code | <--------------------\
      |             |                      |
      ---------------            maintainer-clean
        |                                  |
      ./boot (runs autoconf)               |
        |                                  |
        v                                  |
      ----------------------------         |
      | Source tar-ball          |>-------/|
      |  ./configure             |         |
      |  libraries/*/GNUmakefile |         |
      |  libraries/*/      |<-\      |
      ----------------------------  |      |
        |                           |      |
      ./configure               distclean  |
        |                           |      |
        v                           |      |
      ------------------            |      |
      | Configured     |>----------/|      |
      |   mk/ |>-----------------/|
      |                |<---\       |      |
      ------------------    |       |      |
        |                   |       |      |
       make                 |       |      |
        |                 clean     |      |
        v                   |       |      |
      ------------------    |       |      |
      | Built          |>---/       |      |
      |                |>-----------/      |
      |                |>------------------/

To clean the whole tree:

$ make clean

There's also make distclean, which will clean files that are generated by configure, and make maintainer-clean, which cleans all build-generated files, including those present in end-user distributions (such as configure).

See also standard targets and Commentary/SourceTree.

Steps to prepare for building

We gave a quick getting-started introduction to building GHC in Newcomers, the following sections describe each step in more detail.

In the build system, the path to the top of your build tree is referred to as $(TOP), and we will use that convention in the following sections.

Generate configure scripts

NOTE: if you're starting from a source distribution that you downloaded from the GHC web site, rather than git sources, you can skip this step. Source distributions come with configure scripts pre-generated for you.

Change directory to $(TOP) and issue the command

$ ./boot

(Note: the $ is the prompt. You don't type that bit.) This runs autoreconf on the various scripts in the GHC build tree, generating configure scripts and other miscellaneous files.

You have to re-do this step if (and only if) you ever change one of the files that autoconf uses to generate the configure scripts, such as, or aclocal.m4.

Run the configure script

Run the configure script, thus:

$ ./configure <args>

configure's mission is to scurry round your computer working out what architecture it has, what operating system, whether it has the vfork system call, where tar is kept, whether gcc is available, where various obscure #include files are, whether it's a leap year, and what the systems manager had for lunch. It communicates these snippets of information in two ways:

  • It translates various files such as mk/ to mk/, substituting for things between "@" brackets. So, "@HaveGcc@" will be replaced by "YES" or "NO" depending on what configure finds. mk/ is included by every Makefile (directly or indirectly), so the configuration information is thereby communicated to all Makefiles.
  • It translates mk/ to mk/config.h. The latter is #included by various C source files, which can thereby make use of configuration information.

configure takes some optional arguments. Use ./configure --help to get a list of the available arguments. Here are some of the ones you might need:

Set the "host platform" (see platform names). Usually only necessary if cross-compiling.
Set the "target platform" (see platform names). Usually only necessary if cross-compiling.
Specifies the path to an installed GHC which you would like to use. This compiler will be used for compiling GHC-specific code (eg. GHC itself). This option cannot be specified using (see later), because configure needs to auto-detect the version of GHC you're using. The default is to look for a compiler named ghc in your $PATH.
Specifies the path to the installed GCC. This compiler will be used to compile all C files, except any generated by the installed Haskell compiler, which will have its own idea of which C compiler (if any) to use. The default is to use gcc. On Windows, this should be set to the gcc that comes with MinGW, which by default is c:/mingw/bin/gcc.
Specifies which ld program to use. Normally only necessary on Windows, where you should set it to the ld that comes with MinGW, which is usually c:/mingw/bin/ld.
Tells the build system where you would like GHC to be eventually installed. You don't have to install GHC in order to use it: it is entirely possible to work on GHC and test it without ever modifying anything outside the build tree. However, if you do want to install GHC, then the --prefix directory is the root of the install tree. Typically on Unix systems the default for --prefix is /usr/local. See also Building/Installing for more details.
On Windows in order to build GHC and to be able to create a binary distribution package some extra binaries are needed. These binaries only have to be downloaded once. This flag serves as consent to allow the automatic download of dependencies if they are missing. It is fine to leave the flag in even if you already have the tarballs.

Build configuration

Next, you say how this build of GHC is to differ from the standard defaults by creating a new file mk/ in the build tree. This file is the one and only file you edit in the build tree, precisely because it says how this build differs from the source. (Just in case your build tree does die, you might want to keep a private directory of files, and use a symbolic link in each build tree to point to the appropriate one.)

mk/ is purely for overriding settings that are found in mk/ You should never edit mk/ directly, since it is automatically generated from mk/ by configure. Neither should you edit mk/; just provide your settings in mk/

We provide a sample file, mk/, which you can copy to mk/ and edit. It provides a number of pre-defined configurations, such as a "fast build" or a "development build". Take a look in the file itself for details.

To understand more about what you can put in mk/, read on.

Common options

The following are some common variables that you might want to set in your mk/ For other variables that you can override, take a look in mk/

(default: -H32m -O)
Options passed to GHC for all Haskell compilations.
(default: -Rghc-timing)
Options added when compiling GHC (all stages)

-Rghc-timing prints out a line of timing info about each compilation. It is not set when V=0, but handy to keep an eye on otherwise.

(default: empty)
Options added when compiling the stage 1 GHC.
(default: -O2)
Options added when compiling the stage 2 GHC.
(default: -O2)
Options added when compiling the stage 3 GHC.
(default: -O2)
Options added when compiling the libraries.
(default: NO)
Set to YES to enable profiling for GHC itself (stage 2). You'll also need to add GhcLibWays += p to make this work.
(default: NO)
Set to YES to pass -debug when building GHC (stage 1, 2 and 3). This links GHC (stage 1, 2 and 3) with the debugging RTS. (It does not imply GhcStage2HcOpts+=-DDEBUG, see below for that)
(default: v p)
Ways in which to build the libraries. Must contain at least v (the vanilla way). Also contains p by default (profiling). For other ways, see mk/
(default: YES if supported, NO otherwise)
When set to YES, static library object files are split into smaller pieces. This means that less of the library code needs to be linked into the final application, which makes smaller binaries. It takes longer to build libraries this way, though.
(default: NO)
When set to YES, dependencies on the ghc executable will be turned into order-only dependencies (c.f. relevant make documentation). What this means in practice is that less needless recompilation will be done while you are making changes to ghc's sources, but for certain types of changes it means the build will fail.
(default: YES)
Build haddock and run it on the compiler and libraries source?
(default: YES if supported, NO otherwise)
When set to YES, these build the sphinx documentation (e.g. the users guide) as HTML and PDF respectively.
By default this is set to integer-gmp, which means Integer is implemented on top of the C GMP library. If you set it to integer-simple then a simple, BSD-licensed Haskell implementation will be used instead.
(default: NO) Enable building of DPH libraries (no longer supported since GHC 8.6)
(default: NO) Enable building of the extra libraries: those packages that have an 'extra' tag in the ./packages file. To quick way to see what those packages are, is to run make show VALUE=PACKAGES_STAGE2 BUILD_EXTRA_PKGS=YES (although BUILD_DPH=YES adds packages to that list as well).
(default: 1) Set V=0 to get prettier build output. See Building/Using#Verbosebuild below.

Building things

At this point you have made yourself a fully-configured build tree, so you are ready to start building real things.

The first thing you need to know is that you must use GNU make. On some systems (eg. FreeBSD) this is called gmake, whereas on others it is the standard make command. In this document we will always refer to it as make; please substitute with gmake if your system requires it. If you use the wrong make you will get all sorts of error messages (but no damage) because the GHC Makefiles use GNU make's facilities extensively.

Type make help to display help on available build targets.

To just build the whole thing, cd to the top of your build tree and type make. This will prepare the tree and build the various parts in the correct order, resulting in a complete build of GHC that can even be used directly from the tree (as inplace/bin/ghc-stage2), without being installed first.

Order of the build

Here is a high level view of what happens when you build GHC:

  • First, we build a few packages that GHC itself depends on, such as Cabal, using your installed GHC. These packages are under libraries, and each is built in a subdirectory dist-boot; for example the bootstrap build of Cabal will be in libraries/Cabal/dist-boot.
  • Then we build package ghc, still using the installed GHC. The ghc package is a perfectly ordinary package. The source code for the package is all the files in compiler/.
  • Now, still using the installed GHC, we build the ghc executable, from source code in ghc/. This source code is just a small Haskell program that depends on package ghc.

The resulting executable is called the "stage 1" compiler (see stages). You can run the stage 1 compiler by invoking inplace/bin/ghc-stage1. The stage 1 build of GHC happens in compiler/stage1.

  • The stage 1 compiler is now used to build all the packages in the libraries subdirectory, and the runtime system in rts.
  • Finally, the stage 1 compiler is used to build GHC itself again, this time against the libraries we just built. This GHC is called stage 2, and can be invoked as inplace/bin/ghc-stage2.

There's an optional final stage, using the stage 2 compiler to build a stage 3 compiler, but this isn't strictly necessary, and is only used to check that the stage 2 compiler is working properly.

Building Documentation

To build the users guide type make html from the top level directory. You can find the output html in docs/users_guide/build-html directory. Similarlypdf or ps targets can also be used to build a pdf or ps output.

Note that documentation targets will not be enabled by default unless you have sphinx-build (for html) or xelatex (for pdf) installed. If you install them later then do not forget to run configure again. The variables to enable or disable documentation targets are BUILD_SPHINX_HTML and BUILD_SPHINX_PDF.

For more details see Building/Docs.

What to do after make has finished

If make completes successfully, then it should have created inplace/bin/ghc-stage2, which is a GHC binary you can run directly. It supports all the usual features, including GHCi if you pass the --interactive flag.

In fact, the inplace directory looks a lot like an installed copy of GHC (see Building/Installing): there is a bin subdirectory containing various programs that can be run, including ghc-pkg, Haddock and hsc2hs.

You can now run the testsuite, see Building/RunningTests. You can now install GHC, by typing make install.

Developing in a GHC build tree

This section describes how to make changes to the sources of GHC, or its libraries and tools, and use the build system to build and test those changes.

Bringing the whole tree up to date

The easy way to bring the tree up to date after making some changes is simply to go to the top of the tree and say make. The build system has enough dependencies encoded into it that this should rebuild everything that needs to be rebuilt, in the correct order. The downside is that it will build everything right through to the stage2 compiler and including all the documentation, which might be overkill if all you wanted to do was to test a small change to GHC.

Building a single file

It's possible to tell make to build a single file, from any subdirectory in the tree. For example, suppose I want to build just the module Control.Monad in the base package, I can do it like this:

$ make libraries/base/dist-install/build/Control/Monad.o

(you have to know that dist-install is the distdir for a package, and object files are put in the subdirectory build). It's also possible to do this from the libraries/base subdirectory:

$ cd libraries/base
$ make dist-install/build/Control/Monad.o

suppose you wanted to build this module with a few extra flags, perhaps because you want to see what GHC's optimiser is doing on this module:

$ rm dist-install/build/Control/Monad.o
$ make dist-install/build/Control/Monad.o EXTRA_HC_OPTS=-dcore-lint

you could also cut-and-paste the command-line to add flags, but sometimes the EXTRA_HC_OPTS method is more convenient.

Fast rebuilding

How to make GHC build quickly

The GHC build tree is set up so that, by default, it builds a compiler ready for installing and using. That means full optimisation, and the build can take a long time. If you unpack your source tree and right away say ./configure; make, expect to have to wait a while. For hacking, you want the build to be quick - quick to build in the first place, and quick to rebuild after making changes. Tuning your build setup can make the difference between several hours to build GHC, and less than an hour.

In the file, select BuildFlavour = devel2 to make the build fast, and suitable for working on the stage2 compiler.

Here's the reasoning behind some of the devel2 settings:

GhcStage1HcOpts = -O
Build stage 1 optimised: we're going to be rebuilding stage 2 a lot, so we want the compiler that does the building to be fast.
GhcStage2HcOpts = -O0 -DDEBUG
We turn off optimisation here, assuming you'll be modifying and testing stage 2. With optimisation off, rebuilding GHC after modifying it will be much quicker, not only because the individual compilations will be quicker, but also there will be fewer dependencies between modules, so much less stuff is recompiled after each modification.

Also we turn on -DDEBUG, because that enables assertions and debugging code in the compiler itself (Haskell source files only, use GhcDebugged=YES to link GHC with the debugging RTS, see above). Turning on DEBUG makes the compiler about 30% slower.
GhcLibHcOpts = -O -dcore-lint
You almost certainly want optimisation on when building libraries, otherwise the code you build with this compiler goes really slowly.

When building the libraries, also turn on heavyweight intra-pass sanity-checking within GHC, at the Core level.

Working on an optimized stage 2 compiler.

If you are going to rebuild an optimized stage 2 compiler more often you should use -O2 to speed up the build.

A full build with GhcStage1HcOpts = -O2 and GhcStage2HcOpts = -O will be slower by ~3% than the default. But each rebuild off stage2 afterwards will be faster.

Building a single sub-component

Often when you're working in a particular part of the tree, the rest of the tree is up to date, and you just want to rebuild the component you're working on after making changes. So the GHC build system provides ways to do this.

Each subdirectory of the source tree has a stub makefile, most of which follow this pattern:

dir = libraries/base
TOP = ../..
include $(TOP)/mk/

the main purpose of the stub makefile is to invoke make at the top-level of the tree: GHC's build system is non-recursive, so in effect there is really just one Makefile, at the top level. However, the stub makefile has another purpose: it passes a target to the top-level Makefile, telling it to build just the component in this directory.

For example:

$ cd compiler
$ make

is actually equivalent to:

$ make -C .. all_compiler

where "-C .." tells make to invoke the Makefile in the directory "..", and all_compiler is the target that makes everything in the compiler subdirectory.

Equivalently, make all_libraries/base at the top level would build everything in the libraries/base subdirectory. To understand how the all targets are defined, see standard targets.

You can also clean a single component of the tree, just by saying make clean in a subdirectory. Again this is equivalent to issuing a command at the top of the tree of the form make clean_libraries/base.

Freezing stage 1

We can "freeze" the stage 1 compiler by adding a line to mk/


Setting stage=2 has the effect of disabling all the rules that build the stage 1 compiler, so the build system will ignore the fact that the stage 1 compiler is also out of date, and hence all the libraries are also potentially out of date. If you ran make without setting stage=2, all of these dependencies would be taken into account, and a lot of rebuilding would probably ensue.

Should you then want to rebuild from scratch (say, to switch build flavours), you can still do so by saying:

$ make clean
$ make stage=

Skip dependency building

Use make fast to skip dependency building. This command works only in the subdirectories.

make fast is a shorthand for make all FAST=YES. Setting FAST=YES causes make to omit rebuilding the .depend file (if any), and also omits some of the phases. FAST=YES is allowed in conjunction with any other target; for example, it also makes sense when rebuilding a single file.

Note that with FAST=YES, if you have changed the imports in any modules, those new dependencies will not be taken into account by the build system, so you might get a build failure. On the other hand, this shortcut usually works and the few seconds it saves can make GHC development a much more interactive experience.

Rebuilding the GHC binary after making changes

There are specific commands to quickly rebuild the GHC binary. These commands work in the ghc subdirectory, but also in the compiler subdirectory (which is probably why they were added).

If you followed the advice of freezing the stage 1 compiler, by setting stage=2 in your file, you won't need these, and make fast in the ghc subdirectory accomplishes the same thing. They can be handy shorthands though.

  • make 1 means make stage=1 FAST=YES
  • make 2 means make stage=2 FAST=YES
  • make 3 means make stage=3 FAST=YES

The re1, re2, and re3 targets are sometimes used for relinking the compiler after a change like GhcDebugged=YES.

  • make re1 means rm $PATH_TO_STAGE1_EXECUTABLE; make 1
  • make re2 means rm $PATH_TO_STAGE2_EXECUTABLE; make 2
  • make re3 means rm $PATH_TO_STAGE3_EXECUTABLE; make 3

Note that if you’ve never built stage3 before, you will need to create dependencies for it using make stage=3. This is because a normal build will skip building the stage3 compiler. You will then be able to run make 3.

If your builds fail because of -Werror make sure there is no mk/ file in your tree. It's created by/for validate and adds some options which are not required for regular builds.

Verbose build

From Design/BuildSystem:

"The build system should clearly report what it's doing (and sometimes why), without being too verbose. It should emit actual command lines as much as possible, so that they can be inspected and cut & pasted."

That's why, by default, the build log is printed with the full command lines that are being used, so you can copy/paste and rerun them on build failures/warnings.

You can use make V=0 for a prettier, more compact output, where each invocation of the compiler looks something like.

HC [stage 0] compiler/stage1/build/Constants.o

You can also put the "V=0" in your or file.

Profiling the compiler

It is possible to build a profiled compiler by setting BuildFlavour=prof in mk/ However, by default the build will have very few cost-centres defined. There are a few ways to add cost-centres,

  • Add SCC pragmas in the source
  • Add {-# OPTIONS_GHC -fprof-auto #-} pragmas to the modules of interest
  • Add an appropriate -fprof-* flag to the build system's flag set for modules of interest, for instance, by adding the following to mk/,
    compiler/typecheck/TcBinds_HC_OPTS += -fprof-auto

You can also add flags to an entire subdirectory of the compiler by adding something like the following to mk/,

define add_mods_flag =
  $(foreach mod,$(2),$(eval $(basename $(mod))_HC_OPTS += $(1)))

$(call add_mods_flag,-fprof-auto,$(wildcard compiler/typecheck/*.hs))

Also make sure the change isn't a regression when going from -O1 to -O2 as not all changes behave the same for both.

Installing extra packages

The boot libraries are built as part of building GHC; they are built with the stage1 compiler, and imported when the stage2 compiler is compiled with stage1.

All other libraries are stand-alone Cabal packages, and the build system knows nothing about them. Nevertheless, it is common to want to install extra packages for the GHC in your build tree. Here are instructions for how to do so.

Last modified 12 months ago Last modified on Jan 4, 2019 7:37:10 PM