Skip to content

Commit

Permalink
Nix: select the right GHC version in more cases.
Browse files Browse the repository at this point in the history
Stack now selects the correct GHC version in the following cases:

* an abstract resolver was given,
* a concrete resolver was given,
* a compiler version was given.

Previously, we could only deal with concrete resolvers correctly.

Fixes #1641.
  • Loading branch information
mboes committed Jan 12, 2016
1 parent 1298300 commit 45ace0d
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/Stack/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ configFromConfigMonoid configStackRoot configUserConfigPath mresolver mproject c

configDocker <-
dockerOptsFromMonoid (fmap fst mproject) configStackRoot mresolver configMonoidDockerOpts
configNix <- nixOptsFromMonoid configMonoidNixOpts os
configNix <- nixOptsFromMonoid (fmap fst mproject) configMonoidNixOpts os

rawEnv <- liftIO getEnvironment
pathsEnv <- augmentPathMap (map toFilePath configMonoidExtraPath)
Expand Down
21 changes: 17 additions & 4 deletions src/Stack/Config/Nix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,25 @@ module Stack.Config.Nix
,StackNixException(..)
) where

import Control.Monad (when)
import Control.Applicative
import Control.Monad (join, when)
import qualified Data.Text as T
import Data.Maybe
import Data.Typeable
import Distribution.System (OS (..))
import Stack.Types
import Control.Exception.Lifted
import Control.Monad.Catch (throwM,MonadCatch)

import Prelude

-- | Interprets NixOptsMonoid options.
nixOptsFromMonoid
:: (Monad m, MonadCatch m)
=> NixOptsMonoid
=> Maybe Project
-> NixOptsMonoid
-> OS
-> m NixOpts
nixOptsFromMonoid NixOptsMonoid{..} os = do
nixOptsFromMonoid mproject NixOptsMonoid{..} os = do
let nixEnable = fromMaybe nixMonoidDefaultEnable nixMonoidEnable
defaultPure = case os of
OSX -> False
Expand All @@ -32,6 +34,17 @@ nixOptsFromMonoid NixOptsMonoid{..} os = do
nixInitFile = nixMonoidInitFile
nixShellOptions = fromMaybe [] nixMonoidShellOptions
++ prefixAll (T.pack "-I") (fromMaybe [] nixMonoidPath)
nixCompiler resolverOverride compilerOverride =
let mresolver = resolverOverride <|> fmap projectResolver mproject
mcompiler = compilerOverride <|> join (fmap projectCompiler mproject)
in case (mresolver, mcompiler) of
(_, Just (GhcVersion v)) ->
T.filter (== '.') (versionText v)
(Just (ResolverCompiler (GhcVersion v)), _) ->
T.filter (== '.') (versionText v)
(Just (ResolverSnapshot (LTS x y)), _) ->
T.pack ("haskell.packages.lts-" ++ show x ++ "_" ++ show y ++ ".ghc")
_ -> T.pack "ghc"
when (not (null nixPackages) && isJust nixInitFile) $
throwM NixCannotUseShellFileAndPackagesException
return NixOpts{..}
Expand Down
18 changes: 7 additions & 11 deletions src/Stack/Nix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import Network.HTTP.Client.Conduit (HasHttpManager)
import Path
import Path.IO
import qualified Paths_stack as Meta
import Prelude -- Fix redundant import warnings
import Prelude hiding (mapM) -- Fix redundant import warnings
import Stack.Constants (stackProgName,platformVariantEnvVar)
import Stack.Config (makeConcreteResolver)
import Stack.Docker (reExecArgName)
Expand All @@ -43,23 +43,22 @@ import Stack.Types
import Stack.Types.Internal
import System.Environment (lookupEnv,getArgs,getExecutablePath)
import System.Exit (exitSuccess, exitWith)
import Prelude hiding (mapM)


-- | If Nix is enabled, re-runs the currently running OS command in a Nix container.
-- Otherwise, runs the inner action.
reexecWithOptionalShell
:: M env m
=> Maybe (Path Abs Dir)
-> Maybe AbstractResolver
-> Maybe CompilerVersion
-> IO ()
-> m ()
reexecWithOptionalShell mprojectRoot maresolver inner =
reexecWithOptionalShell mprojectRoot maresolver mcompiler inner =
do config <- asks getConfig
inShell <- getInShell
isReExec <- asks getReExec
if nixEnable (configNix config) && not inShell && not isReExec
then runShellAndExit mprojectRoot maresolver getCmdArgs
then runShellAndExit mprojectRoot maresolver mcompiler getCmdArgs
else liftIO inner
where
getCmdArgs = do
Expand All @@ -74,9 +73,10 @@ runShellAndExit
:: M env m
=> Maybe (Path Abs Dir)
-> Maybe AbstractResolver
-> Maybe CompilerVersion
-> m (String, [String])
-> m ()
runShellAndExit mprojectRoot maresolver getCmdArgs = do
runShellAndExit mprojectRoot maresolver mcompiler getCmdArgs = do
config <- asks getConfig
mresolver <- mapM makeConcreteResolver maresolver
envOverride <- getEnvOverride (configPlatform config)
Expand All @@ -85,11 +85,7 @@ runShellAndExit mprojectRoot maresolver getCmdArgs = do
traverse (resolveFile (fromMaybeProjectRoot mprojectRoot)) $
nixInitFile (configNix config)
let pkgsInConfig = nixPackages (configNix config)
pkgs =
pkgsInConfig ++ [case mresolver of
Just (ResolverSnapshot (LTS x y)) ->
T.pack ("haskell.packages.lts-" ++ show x ++ "_" ++ show y ++ ".ghc")
_ -> T.pack "ghc"]
pkgs = pkgsInConfig ++ [nixCompiler (configNix config) mresolver mcompiler]
pureShell = nixPureShell (configNix config)
nixopts = case mshellFile of
Just fp -> [toFilePath fp]
Expand Down
5 changes: 5 additions & 0 deletions src/Stack/Types/Config.hs-boot
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Stack.Types.Config where

data AbstractResolver
data Resolver
data Config
9 changes: 7 additions & 2 deletions src/Stack/Types/Nix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ import Control.Applicative
import Data.Aeson.Extended
import Data.Text (Text)
import Data.Monoid

import Prelude
import Stack.Types.Compiler (CompilerVersion)
import {-# SOURCE #-} Stack.Types.Config (Resolver)
import Text.Show.Functions ()

-- | Nix configuration.
-- | Nix configuration. Parameterize by resolver type to avoid cyclic
-- dependency.
data NixOpts = NixOpts
{nixEnable :: !Bool
,nixPureShell :: !Bool
Expand All @@ -23,6 +26,8 @@ data NixOpts = NixOpts
-- ^ The path of a file containing preconfiguration of the environment (e.g shell.nix)
,nixShellOptions :: ![Text]
-- ^ Options to be given to the nix-shell command line
,nixCompiler :: !(Maybe Resolver -> Maybe CompilerVersion -> Text)
-- ^ Yield a compiler attribute name given a resolver override.
}
deriving (Show)

Expand Down
5 changes: 3 additions & 2 deletions src/main/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ setupCmd SetupCmdOpts{..} go@GlobalOpts{..} = do
(lcProjectRoot lc)
Nothing
(runStackTGlobal manager (lcConfig lc) go $
Nix.reexecWithOptionalShell (lcProjectRoot lc) globalResolver $
Nix.reexecWithOptionalShell (lcProjectRoot lc) globalResolver globalCompiler $
runStackLoggingTGlobal manager go $ do
(wantedCompiler, compilerCheck, mstack) <-
case scoCompilerVersion of
Expand Down Expand Up @@ -864,7 +864,7 @@ withBuildConfigExt go@GlobalOpts{..} mbefore inner mafter = do
(lcProjectRoot lc)
mbefore
(runStackTGlobal manager (lcConfig lc) go $
Nix.reexecWithOptionalShell (lcProjectRoot lc) globalResolver (inner'' lk0))
Nix.reexecWithOptionalShell (lcProjectRoot lc) globalResolver globalCompiler (inner'' lk0))
mafter
(Just $ liftIO $
do lk' <- readIORef curLk
Expand Down Expand Up @@ -1008,6 +1008,7 @@ execCmd ExecOpts {..} go@GlobalOpts{..} =
Nix.reexecWithOptionalShell
(lcProjectRoot lc)
globalResolver
globalCompiler
(runStackTGlobal manager (lcConfig lc) go $
exec menv cmd args))
Nothing
Expand Down

0 comments on commit 45ace0d

Please sign in to comment.