[hadrian] Rebuild programs on dynamicGhcPrograms/ghcProfiled change
authorArtem Pyanykh <artempyanykh@gmail.com>
Wed, 11 Sep 2019 20:12:32 +0000 (21:12 +0100)
committerMarge Bot <ben+marge-bot@smart-cactus.org>
Mon, 23 Sep 2019 21:54:04 +0000 (17:54 -0400)
Currently, if you change these ^ flavour parameters, rebuilding is not
triggered, since `programContext` doesn't set up a dependency on
those values.

Exposing these values via an oracle does set the dependency and
properly triggers a rebuild of binaries.

Several attempts to factor out these actions ended up in cyclic
dependency here or there. I'm not absolutely happy with this variant
either, but at least it works.

====

Issue repro:

In UserSettings.hs:
```
dbgDynamic = defaultFlavour { name = "dbg-dynamic"
                            , dynamicGhcPrograms = pure True,
                            ... }

dbgStatic = defaultFlavour { name = "dbg-static"
                           , dynamicGhcPrograms = pure False
                           ... }
```

Then in console:

```
$ hadrian/build.sh -j --flavour=dbg-dynamic
... does the build
$ hadrian/build.sh -j --flavour=dbg-static
... does nothing, considers binaries up to date
```

hadrian/hadrian.cabal
hadrian/src/Oracles/Flavour.hs [new file with mode: 0644]
hadrian/src/Oracles/TestSettings.hs
hadrian/src/Rules.hs
hadrian/src/Rules/BinaryDist.hs
hadrian/src/Rules/Program.hs
hadrian/src/Rules/Test.hs
hadrian/src/Settings.hs
hadrian/src/Settings/Builders/Make.hs
hadrian/src/Settings/Program.hs [new file with mode: 0644]

index 6037a21..02c64bc 100644 (file)
@@ -48,6 +48,7 @@ executable hadrian
                        , Hadrian.Target
                        , Hadrian.Utilities
                        , Oracles.Flag
+                       , Oracles.Flavour
                        , Oracles.Setting
                        , Oracles.ModuleFiles
                        , Oracles.TestSettings
@@ -102,6 +103,7 @@ executable hadrian
                        , Settings.Flavours.GhcInGhci
                        , Settings.Packages
                        , Settings.Parser
+                       , Settings.Program
                        , Settings.Warnings
                        , Stage
                        , Target
diff --git a/hadrian/src/Oracles/Flavour.hs b/hadrian/src/Oracles/Flavour.hs
new file mode 100644 (file)
index 0000000..88e9c89
--- /dev/null
@@ -0,0 +1,33 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module Oracles.Flavour
+  ( oracles
+  , askDynGhcPrograms
+  , askGhcProfiled
+  ) where
+
+import Base
+import Flavour
+import Settings (flavour)
+
+newtype DynGhcPrograms =
+  DynGhcPrograms () deriving (Show, Typeable, Eq, Hashable, Binary, NFData)
+type instance RuleResult DynGhcPrograms = Bool
+
+newtype GhcProfiled =
+  GhcProfiled () deriving (Show, Typeable, Eq, Hashable, Binary, NFData)
+type instance RuleResult GhcProfiled = Bool
+
+oracles :: Rules ()
+oracles = do
+  void $ addOracle $ \(DynGhcPrograms _) -> dynamicGhcPrograms =<< flavour
+  void $ addOracle $ \(GhcProfiled _) -> ghcProfiled <$> flavour
+
+askDynGhcPrograms :: Action Bool
+askDynGhcPrograms = askOracle $ DynGhcPrograms ()
+
+askGhcProfiled :: Action Bool
+askGhcProfiled = askOracle $ GhcProfiled ()
index 9d93e10..ba89e00 100644 (file)
@@ -10,8 +10,8 @@ module Oracles.TestSettings
 import Base
 import Hadrian.Oracles.TextFile
 import Oracles.Setting (topDirectory, setting, Setting(..))
-import Settings (programContext)
 import Packages
+import Settings.Program (programContext)
 
 testConfigFile :: Action FilePath
 testConfigFile = buildRoot <&> (-/- "test/ghcconfig")
index 5b26823..e72623d 100644 (file)
@@ -8,6 +8,7 @@ import qualified Hadrian.Oracles.Path
 import qualified Hadrian.Oracles.TextFile
 
 import Expression
+import qualified Oracles.Flavour
 import qualified Oracles.ModuleFiles
 import Packages
 import qualified Rules.BinaryDist
@@ -24,10 +25,10 @@ import qualified Rules.Register
 import qualified Rules.Rts
 import qualified Rules.SimpleTargets
 import Settings
+import Settings.Program (programContext)
 import Target
 import UserSettings
 
-
 -- | @tool-args@ is used by tooling in order to get the arguments necessary
 -- to set up a GHC API session which can compile modules from GHC. When
 -- run, the target prints out the arguments that would be passed to @ghc@
@@ -176,4 +177,5 @@ oracleRules = do
     Hadrian.Oracles.DirectoryContents.directoryContentsOracle
     Hadrian.Oracles.Path.pathOracle
     Hadrian.Oracles.TextFile.textFileOracle
+    Oracles.Flavour.oracles
     Oracles.ModuleFiles.moduleFilesOracle
index 11301a0..fb7fa47 100644 (file)
@@ -7,6 +7,7 @@ import Expression
 import Oracles.Setting
 import Packages
 import Settings
+import Settings.Program (programContext)
 import Target
 import Utilities
 
index b5dde25..6273f3d 100644 (file)
@@ -12,6 +12,7 @@ import Oracles.Setting (topDirectory)
 import Packages
 import Settings
 import Settings.Default
+import Settings.Program (programContext)
 import Target
 import Utilities
 import Rules.Library
index 5dea40a..84374ff 100644 (file)
@@ -12,6 +12,7 @@ import Packages
 import Settings
 import Settings.Default
 import Settings.Builders.RunTest
+import Settings.Program (programContext)
 import Target
 import Utilities
 
index 0548bcc..ba0cff7 100755 (executable)
@@ -1,8 +1,7 @@
 module Settings (
     getArgs, getLibraryWays, getRtsWays, flavour, knownPackages,
     findPackageByName, unsafeFindPackageByName, unsafeFindPackageByPath,
-    isLibrary, stagePackages, programContext, getIntegerPackage,
-    completeSetting
+    isLibrary, stagePackages, getIntegerPackage, completeSetting
     ) where
 
 import CommandLine
@@ -68,22 +67,6 @@ flavour = do
 getIntegerPackage :: Expr Package
 getIntegerPackage = expr (integerLibrary =<< flavour)
 
--- TODO: there is duplication and inconsistency between this and
--- Rules.Program.getProgramContexts. There should only be one way to get a
--- context / contexts for a given stage and package.
-programContext :: Stage -> Package -> Action Context
-programContext stage pkg = do
-    profiled <- ghcProfiled <$> flavour
-    dynGhcProgs <- dynamicGhcPrograms =<< flavour
-    return $ Context stage pkg (wayFor profiled dynGhcProgs)
-
-    where wayFor prof dyn
-            | prof && dyn                          =
-                error "programContext: profiling+dynamic not supported"
-            | pkg == ghc && prof && stage > Stage0 = profiling
-            | dyn && stage > Stage0                = dynamic
-            | otherwise                            = vanilla
-
 -- TODO: switch to Set Package as the order of packages should not matter?
 -- Otherwise we have to keep remembering to sort packages from time to time.
 knownPackages :: [Package]
index 56bb8e3..431c2cb 100644 (file)
@@ -4,6 +4,7 @@ import Oracles.Setting
 import Packages
 import Rules.Gmp
 import Settings.Builders.Common
+import Settings.Program (programContext)
 import CommandLine
 
 makeBuilderArgs :: Args
diff --git a/hadrian/src/Settings/Program.hs b/hadrian/src/Settings/Program.hs
new file mode 100644 (file)
index 0000000..d98b1a9
--- /dev/null
@@ -0,0 +1,24 @@
+module Settings.Program
+  ( programContext
+  ) where
+
+import Base
+import Context
+import Oracles.Flavour
+import Packages
+
+-- TODO: there is duplication and inconsistency between this and
+-- Rules.Program.getProgramContexts. There should only be one way to
+-- get a context/contexts for a given stage and package.
+programContext :: Stage -> Package -> Action Context
+programContext stage pkg = do
+    profiled <- askGhcProfiled
+    dynGhcProgs <- askDynGhcPrograms --dynamicGhcPrograms =<< flavour
+    return $ Context stage pkg (wayFor profiled dynGhcProgs)
+
+    where wayFor prof dyn
+            | prof && dyn                          =
+                error "programContext: profiling+dynamic not supported"
+            | pkg == ghc && prof && stage > Stage0 = profiling
+            | dyn && stage > Stage0                = dynamic
+            | otherwise                            = vanilla