Magnus pushed to branch wip/hadrian-persistent-flavour at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • changelog.d/hadrian-persist-flavour
    1
    +section: packaging
    
    2
    +synopsis: Hadrian now persists the flavour name in the build root. When
    
    3
    +  rebuilding, the previously used flavour is automatically restored, removing
    
    4
    +  the need to re-specify it on every invocation and avoiding accidental build
    
    5
    +  root invalidation.
    
    6
    +issues: #20650
    
    7
    +mrs: !7017

  • hadrian/doc/flavours.md
    ... ... @@ -3,7 +3,14 @@
    3 3
     Hadrian supports a few predefined _build flavours_, i.e. collections of build
    
    4 4
     settings that fully define a GHC build (see `src/Flavour.hs`). Users can add their
    
    5 5
     own build flavours if need be, as described
    
    6
    -[here](https://gitlab.haskell.org/ghc/ghc/blob/master/hadrian/doc/user-settings.md#build-flavour).
    
    6
    +[here](https://gitlab.haskell.org/ghc/ghc/blob/master/hadrian/doc/user-settings.md#build-flavour) or modify existing flavours using the flavour transformers notion seem below.
    
    7
    +
    
    8
    +The flavour to be used for a build root can be specified on the command-line
    
    9
    +via the `--flavour` flag. Moreover, this flavour name is saved in the build
    
    10
    +root; future invocations of Hadrian without a `--flavour` flag will default to
    
    11
    +the last-used flavour.
    
    12
    +
    
    13
    +See `Note [Persisting the flavour]` in `hadrian/src/Settings.hs` 
    
    7 14
     
    
    8 15
     ## Arguments
    
    9 16
     
    

  • hadrian/src/Rules.hs
    ... ... @@ -129,6 +129,7 @@ packageRules = do
    129 129
     
    
    130 130
     buildRules :: Rules ()
    
    131 131
     buildRules = do
    
    132
    +    Settings.flavourFileRules
    
    132 133
         Rules.BinaryDist.bindistRules
    
    133 134
         Rules.Generate.copyRules
    
    134 135
         Rules.Generate.generateRules
    

  • hadrian/src/Settings.hs
    1
    +{-# LANGUAGE TupleSections #-}
    
    2
    +{-# LANGUAGE TypeFamilies  #-}
    
    3
    +
    
    1 4
     module Settings (
    
    2 5
         getExtraArgs, getArgs, getLibraryWays, getRtsWays, flavour, knownPackages,
    
    3 6
         findPackageByName, unsafeFindPackageByName, unsafeFindPackageByPath,
    
    4 7
         isLibrary, stagePackages, getBignumBackend, completeSetting,
    
    5 8
         queryBuildTarget, queryHostTarget,
    
    6 9
         queryBuild, queryHost,
    
    7
    -    queryArch, queryOS, queryVendor
    
    10
    +    queryArch, queryOS, queryVendor,
    
    11
    +    flavourFileRules
    
    8 12
         ) where
    
    9 13
     
    
    10 14
     import CommandLine
    
    ... ... @@ -58,6 +62,56 @@ hadrianFlavours =
    58 62
         , ghcInGhciFlavour, validateFlavour, slowValidateFlavour
    
    59 63
         ]
    
    60 64
     
    
    65
    +{-
    
    66
    +Note [Persisting the flavour]
    
    67
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    68
    +Passing the flavour on the command-line means the user must consistently pass
    
    69
    +the same --flavour flag to all Hadrian invocations on a particular build root.
    
    70
    +Forgetting even once can result in a full rebuild of the tree.
    
    71
    +
    
    72
    +To avoid this we persist the flavour name in the build root itself
    
    73
    +(specifically, in `<build root>/flavour`). We refer to this file when looking
    
    74
    +up the active flavour, defaulting to it if the user does not specify a flavour
    
    75
    +name explicitly.
    
    76
    +-}
    
    77
    +
    
    78
    +-- | Oracle query type for the active flavour name.
    
    79
    +-- See Note [Persisting the flavour].
    
    80
    +newtype FlavourName = FlavourName ()
    
    81
    +    deriving (Binary, Eq, Hashable, NFData, Show)
    
    82
    +type instance RuleResult FlavourName = String
    
    83
    +
    
    84
    +flavourFileRules :: Rules ()
    
    85
    +flavourFileRules = do
    
    86
    +    root <- buildRootRules
    
    87
    +
    
    88
    +    -- Cache the flavour name lookup for the whole Shake run.
    
    89
    +    -- alwaysRerun ensures the oracle re-executes on every new invocation so
    
    90
    +    -- that a changed --flavour flag is never ignored due to a stale cross-run
    
    91
    +    -- cache entry (CLI args are not tracked as Shake dependencies).
    
    92
    +    -- See Note [Persisting the flavour].
    
    93
    +    void $ addOracleCache $ \(FlavourName _) -> do
    
    94
    +        alwaysRerun
    
    95
    +        let flavourFile = root -/- "flavour"
    
    96
    +        cmdFlavour >>= \case
    
    97
    +          Just nm -> do
    
    98
    +            putBuild $ "Flavour: " ++ nm
    
    99
    +            liftIO $ writeFile flavourFile nm
    
    100
    +            return nm
    
    101
    +          Nothing -> do
    
    102
    +            exists <- doesFileExist flavourFile
    
    103
    +            if exists
    
    104
    +              then do nm <- liftIO $ readFile flavourFile
    
    105
    +                      putBuild $ "Flavour: " ++ nm ++ " (cached from last build, override by passing --flavour=... explicitly)"
    
    106
    +                      return nm
    
    107
    +              else return userDefaultFlavour
    
    108
    +
    
    109
    +-- | Lookup the requested flavour name, referring to the persistent flavour
    
    110
    +-- file saved from the previous Hadrian execution if not specified.
    
    111
    +-- The result is cached for the whole Shake run via the 'FlavourName' oracle.
    
    112
    +getFlavourName :: Action String
    
    113
    +getFlavourName = askOracle (FlavourName ())
    
    114
    +
    
    61 115
     -- | This action looks up a flavour with the name given on the
    
    62 116
     --   command line with @--flavour@, defaulting to 'userDefaultFlavour'
    
    63 117
     --   when no explicit @--flavour@ is passed. It then applies any
    
    ... ... @@ -66,7 +120,7 @@ hadrianFlavours =
    66 120
     --   syntax. See Note [Hadrian settings] at the bottom of this file.
    
    67 121
     flavour :: Action Flavour
    
    68 122
     flavour = do
    
    69
    -    flavourName <- fromMaybe userDefaultFlavour <$> cmdFlavour
    
    123
    +    flavourName <- getFlavourName
    
    70 124
         when ("quickest" `isPrefixOf` flavourName) $
    
    71 125
           fail $ "The `quickest` flavour has been deprecated. Use `quick` instead.\n"
    
    72 126
               ++ "Skip building dynamic libraries with `quick+no_dynamic_libs`\n"