{-# LANGUAGE LambdaCase #-} module Stage (Stage (..), WhichLibs(..), Inplace(..), isStage0, stage0InTree, stage0Boot, allStages,predStage, succStage, stageString) where import Development.Shake.Classes import GHC.Generics -- | A stage refers to a certain compiler in GHC's build process. -- -- * Stage0 GlobalLibs is for **executables** which are built with the boot compiler -- and boot compiler packages. For example, this was motivated by needing to -- build hsc2hs, a build dependency of unix with just the boot toolchain. (See #21634) -- -- * Stage 0 (InTreeLibs) is built with the bootstrapping compiler, i.e. the one already -- installed on the user's system. The compiler that is produced during -- stage 0 is called /stage 1 compiler/. Stage0 executables and libraries are -- build against the other libraries (in-tree) built by the stage 0 compiler. -- -- * Stage 1 is built using the stage 1 compiler and all GHC sources. The result -- is called /stage 2 compiler/ and it has all features of the new GHC. -- -- * Stage 2 is built using the stage 2 compiler. The result is a compiler -- fully "built by itself", commonly referred to as /bootstrapping/. -- -- * Stage 3 is built as a self test. The resulting compiler should have -- the same object code as the one built in stage 2, which is a good test -- for the compiler. Since it serves no other purpose than that, the stage 3 -- build is usually omitted in the build process. data Stage = Stage0 WhichLibs | Stage1 | Stage2 | Stage3 deriving (Show, Eq, Ord, Generic) {- Note [Inplace vs Final package databases] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There are two package databases we maintain an "inplace" one and a "final" one. The inplace one is created by pre-configuring all the packages before doing any building. All GHC invocations to build .hs files will use an inplace package database for two reasons. 1. To increase parallelism 2. ./hadrian/ghci-multi can use the inplace package db to avoid having to build everything before starting. The "inplace" database has .conf files which point directly to the build folders. The "final" database has a .conf file which points like normall to the install folder. Therefore when we are building modules, we can start compiling a module as soon as all it's dependencies are available in the build folder, rather than waiting for the whole package to finish, be copied and installed like before. Once we need to do a final link then we need to wait for the "final" versions to be enabled because then we want to make sure to create objects with the right rpaths and so on. The "final" .conf has dependencies on all the objects in the package (unlike the "inplace" .conf which has no such dependencies). -} data Inplace = Inplace | Final deriving (Show, Eq, Generic) instance Binary Inplace instance Hashable Inplace instance NFData Inplace -- | See Note [Stage 0 build plans] data WhichLibs = GlobalLibs -- ^ Build build tools against the globally installed libraries | InTreeLibs -- ^ Build the compiler against the in-tree libraries. deriving (Show, Eq, Ord, Generic) allStages :: [Stage] allStages = [Stage0 GlobalLibs, Stage0 InTreeLibs, Stage1, Stage2, Stage3] stage0InTree, stage0Boot :: Stage stage0InTree = Stage0 InTreeLibs stage0Boot = Stage0 GlobalLibs isStage0 :: Stage -> Bool isStage0 Stage0 {} = True isStage0 _ = False predStage :: Stage -> Stage predStage Stage1 = stage0InTree predStage Stage2 = Stage1 predStage Stage3 = Stage2 predStage s = error ("predStage: " ++ show s) succStage :: Stage -> Stage succStage (Stage0 {}) = Stage1 succStage Stage1 = Stage2 succStage Stage2 = Stage3 succStage Stage3 = error "succStage: Stage3" instance Binary Stage instance Hashable Stage instance NFData Stage instance Binary WhichLibs instance Hashable WhichLibs instance NFData WhichLibs -- | Prettyprint a 'Stage'. stageString :: Stage -> String stageString = \case Stage0 GlobalLibs -> "stageBoot" Stage0 InTreeLibs -> "stage0" Stage1 -> "stage1" Stage2 -> "stage2" Stage3 -> "stage3" {- Note [Stage 0 build plans] ~~~~~~~~~~~~~~~~~~~~~~~~~~ The Stage refers to which compiler we will use to perform the builds. Stage0: Build with the boot toolchain Stage1: Build with compiler built in stage 0 Stage2: Build with compiler built in stage 1 Stage 0 also has two different package databases. Stage0 GlobalLibs: Used for building build tool dependencies (hsc2hs, unlit, linters etc) Mostly using the libraries from the boot compiler. Stage0 InTreeLibs: Used for building the Stage 1 compiler (ghc executable) and all libraries needed by that. The reason for this split is 1. bytestring depends on template-haskell so we need to build bytestring with stage0 (and all packages which depend on it). This includes unix and hence directory (which depends on unix) but unix depends on hsc2hs (which depends on directory) and you get a loop in the build rules if you try to build them all in the same package database. The solution is to build hsc2hs with the global boot libraries in Stage0 GlobalLibs 2. We want to build linters and other build tools which we don't distribute in a separate package database so they don't end up in the bindist package database. -}