Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default to using a stack-installed, isolated GHC #2537

Merged
merged 6 commits into from
Oct 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ Major changes:
autogen files and run preprocessors. The `--no-build` flag is now deprecated
because it should no longer be necessary. See
[#1364](https://github.com/commercialhaskell/stack/issues/1364)
* Stack will now always use its own GHC installation, even when a suitable GHC
installation is available on the PATH. To get the old behaviour, use
the `--system-ghc` flag or run `stack config set system-ghc --global true`.
Docker- and Nix-enabled projects continue to use the GHC installations
in their environment by default.

NB: Scripts that previously used stack in combination with a system GHC
installation should now include a `stack setup` line or use the `--install-ghc`
flag.
[#2221](https://github.com/commercialhaskell/stack/issues/2221)

Behavior changes:

Expand Down
3 changes: 1 addition & 2 deletions doc/GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,7 @@ stack ghc, stack ghci, stack runghc, or stack exec
```

Thankfully, the command is smart enough to know not to perform an installation
twice. `setup` will either use the first GHC it finds on your PATH, or a sandboxed
version after installing it. As the command output above indicates, you can use `stack
twice. As the command output above indicates, you can use `stack
path` for quite a bit of path information (which we'll play with more later).
For now, we'll just look at where GHC is installed:

Expand Down
7 changes: 7 additions & 0 deletions doc/docker_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ The most basic configuration is to add this to your project's `stack.yaml`:
See [configuration](#configuration) for additional options. You can enable it on
the command-line using `stack --docker`.

Please note that in a docker-enabled configuration, stack uses the GHC installed
in the Docker container by default. To use a compiler installed by stack, add

system-ghc: false

(see [`system-ghc`](yaml_configuration.md#system-ghc)).

### Use stack as normal

With Docker enabled, most stack sub-commands will automatically launch
Expand Down
40 changes: 28 additions & 12 deletions doc/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,23 +155,39 @@ the following line to your .cabal file:

## I already have GHC installed, can I still use stack?

Yes. stack will default to using whatever GHC is on your `PATH`. If that GHC is
a compatible version with the snapshot you're using, it will simply use it.
Otherwise, it will prompt you to run `stack setup`. Note that `stack setup`
installs GHC into `~/.stack/programs/$platform/ghc-$version/` and not a global
location.
Yes. In its default configuration, stack will simply ignore any system GHC
installation and use a sandboxed GHC that it has installed itself (typically
via the `stack setup` command). You can find these sandboxed GHC installations
in `~/.stack/programs/$platform/ghc-$version/`.

Note that GHC installation doesn't work for all OSes, so in some cases the
first option will need to install GHC yourself.
If you would like stack to use your system GHC installation, use the
[`--system-ghc` flag](yaml_configuration.md#system-ghc) or run
`stack config set system-ghc --global true` to make stack check your
`PATH` for a suitable GHC by default.

Note that stack can only use a system GHC installation if its version is
compatible with the configuration of the current project, particularly the
[`resolver` setting](yaml_configuration.md#resolver).

Note that GHC installation doesn't work for all OSes, so in some cases you
will need to use `system-ghc` and install GHC yourself.

## How does stack determine what GHC to use?

It uses the first GHC that it finds on the `PATH`. If that GHC does not comply
with the various requirements (version, architecture) that your project needs,
it will prompt you to run `stack setup` to get it. `stack` is fully aware of
all GHCs that it has installed itself.
In its default configuration, stack determines from the current project which
GHC version, architecture etc. it needs. It then looks in
`~/.stack/programs/$platform/ghc-$version/` for a compatible GHC, requesting
to install one via `stack setup` if none is found.

If you are using the [`--system-ghc` flag](yaml_configuration.md/#system-ghc) or
have configured `system-ghc: true` either in the project `stack.yaml`
or the global `~/.stack/config.yaml`, stack will use the first GHC that it finds
on your `PATH`, falling back on its sandboxed installations only if the found GHC
doesn't comply with the various requirements (version, architecture) that your
project needs.

See [this issue](https://github.com/commercialhaskell/stack/issues/420) for a detailed discussion.
See [this issue](https://github.com/commercialhaskell/stack/issues/420) for a
detailed discussion of stack's behavior when `system-ghc` is enabled.

## How do I upgrade to GHC 7.10.2 with stack?

Expand Down
4 changes: 4 additions & 0 deletions doc/travis_ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ situation is simple:

```yaml
before_install:
# Install stack as above
# ...
# Configure stack to use the system GHC installation
- stack config set system-ghc --global true
- export PATH=/opt/ghc/7.10.2/bin:$PATH

addons:
Expand Down
13 changes: 8 additions & 5 deletions doc/yaml_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,14 @@ other projects by installing into your shared snapshot database.

### system-ghc

Enables or disables using the GHC available on the PATH. Useful to disable if
you want to force stack to use its own installed GHC (via `stack setup`), in
cases where your system GHC my be incomplete for some reason. Default is `true`.
Enables or disables using the GHC available on the PATH.
Useful to disable if you want to save the time, bandwidth or storage space needed to setup an isolated GHC.
Default is `false` unless the [Docker](docker_integration.md) or [Nix](nix_integration.md) integration is enabled.
In a Nix-enabled configuration, stack is incompatible with `system-ghc: false`.

```yaml
# Turn off system GHC
system-ghc: false
# Turn on system GHC
system-ghc: true
```

### install-ghc
Expand Down Expand Up @@ -452,6 +453,8 @@ Specify a variant binary distribution of GHC to use. Known values:
[setup-info](#setup-info) so `stack setup` knows where to download it, or
pass the `stack setup --ghc-bindist` argument on the command-line

This option is incompatible with `system-ghc: true`.

### ghc-build

(Since 1.2.1)
Expand Down
16 changes: 14 additions & 2 deletions src/Stack/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import Stack.Types.BuildPlan
import Stack.Types.Docker
import Stack.Types.Compiler
import Stack.Types.Internal
import Stack.Types.Nix
import Stack.Types.Urls
import Stack.Types.Version
import System.Environment
Expand Down Expand Up @@ -240,8 +241,6 @@ configFromConfigMonoid configStackRoot configUserConfigPath mresolver mproject C

configGHCVariant0 = getFirst configMonoidGHCVariant
configGHCBuild = getFirst configMonoidGHCBuild

configSystemGHC = fromFirst (isNothing configGHCVariant0) configMonoidSystemGHC
configInstallGHC = fromFirst False configMonoidInstallGHC
configSkipGHCCheck = fromFirst False configMonoidSkipGHCCheck
configSkipMsys = fromFirst False configMonoidSkipMsys
Expand Down Expand Up @@ -272,6 +271,19 @@ configFromConfigMonoid configStackRoot configUserConfigPath mresolver mproject C
dockerOptsFromMonoid (fmap fst mproject) configStackRoot mresolver configMonoidDockerOpts
configNix <- nixOptsFromMonoid configMonoidNixOpts os

configSystemGHC <-
case (getFirst configMonoidSystemGHC, nixEnable configNix) of
(Just False, True) ->
throwM NixRequiresSystemGhc
_ ->
return
(fromFirst
(dockerEnable configDocker || nixEnable configNix)
configMonoidSystemGHC)

when (isJust configGHCVariant0 && configSystemGHC) $
throwM ManualGHCVariantSettingsAreIncompatibleWithSystemGHC

rawEnv <- liftIO getEnvironment
pathsEnv <- augmentPathMap configMonoidExtraPath
(Map.fromList (map (T.pack *** T.pack) rawEnv))
Expand Down
2 changes: 1 addition & 1 deletion src/Stack/Options/ConfigParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ configOptsParser hide0 =
<*> nixOptsParser True
<*> firstBoolFlags
"system-ghc"
"using the system installed GHC (on the PATH) if available and a matching version"
"using the system installed GHC (on the PATH) if available and a matching version. Disabled by default."
hide
<*> firstBoolFlags
"install-ghc"
Expand Down
2 changes: 1 addition & 1 deletion src/Stack/Options/DockerParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dockerOptsParser hide0 =
DockerOptsMonoid
<$> pure (Any False)
<*> firstBoolFlags dockerCmdName
"using a Docker container"
"using a Docker container. Implies 'system-ghc: true'"
hide
<*> fmap First
((Just . DockerMonoidRepo) <$> option str (long (dockerOptName dockerRepoArgName) <>
Expand Down
2 changes: 1 addition & 1 deletion src/Stack/Options/GhcVariantParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ghcVariantParser hide =
readGHCVariant
(long "ghc-variant" <> metavar "VARIANT" <>
help
"Specialized GHC variant, e.g. integersimple (implies --no-system-ghc)" <>
"Specialized GHC variant, e.g. integersimple (incompatible with --system-ghc)" <>
hideMods hide
)
where
Expand Down
4 changes: 2 additions & 2 deletions src/Stack/Options/NixParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ nixOptsParser hide0 = overrideActivation <$>
(NixOptsMonoid
<$> pure (Any False)
<*> firstBoolFlags nixCmdName
"use of a Nix-shell"
"use of a Nix-shell. Implies 'system-ghc: true'"
hide
<*> firstBoolFlags "nix-pure"
"use of a pure Nix-shell"
"use of a pure Nix-shell. Implies 'system-ghc: true'"
hide
<*> optionalFirst
(textArgsOption
Expand Down
34 changes: 23 additions & 11 deletions src/Stack/Setup.hs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ defaultStackSetupYaml =
data SetupOpts = SetupOpts
{ soptsInstallIfMissing :: !Bool
, soptsUseSystem :: !Bool
-- ^ Should we use a system compiler installation, if available?
, soptsWantedCompiler :: !CompilerVersion
, soptsCompilerCheck :: !VersionCheck
, soptsStackYaml :: !(Maybe (Path Abs File))
Expand Down Expand Up @@ -357,13 +358,11 @@ ensureCompiler sopts = do

Platform expectedArch _ <- asks getPlatform

let needLocal = case msystem of
Nothing -> True
Just _ | soptsSkipGhcCheck sopts -> False
Just (system, arch) ->
not (isWanted system) ||
arch /= expectedArch
let canUseCompiler compilerVersion arch
| soptsSkipGhcCheck sopts = True
| otherwise = isWanted compilerVersion && arch == expectedArch
isWanted = isWantedCompiler (soptsCompilerCheck sopts) (soptsWantedCompiler sopts)
needLocal = not (any (uncurry canUseCompiler) msystem)

getSetupInfo' <- runOnce (getSetupInfo (soptsStackSetupYaml sopts) =<< asks getHttpManager)

Expand Down Expand Up @@ -422,18 +421,31 @@ ensureCompiler sopts = do
(soptsWantedCompiler sopts)
(soptsCompilerCheck sopts)
(soptsGHCBindistURL sopts)
| otherwise ->
| otherwise -> do
recommendSystemGhc <-
if soptsUseSystem sopts
then return False
else do
msystemGhc <- getSystemCompiler menv0 wc
return (any (uncurry canUseCompiler) msystemGhc)
let suggestion = fromMaybe
(mconcat
([ "To install the correct GHC into "
, T.pack (toFilePath (configLocalPrograms config))
, ", try running \"stack setup\" or use the \"--install-ghc\" flag."
] ++
[ " To use your system GHC installation, run \"stack config set system-ghc --global true\", or use the \"--system-ghc\" flag."
| recommendSystemGhc
]))
(soptsResolveMissingGHC sopts)
throwM $ CompilerVersionMismatch
msystem
(soptsWantedCompiler sopts, expectedArch)
ghcVariant
compilerBuild
(soptsCompilerCheck sopts)
(soptsStackYaml sopts)
(fromMaybe
("Try running \"stack setup\" to install the correct GHC into "
<> T.pack (toFilePath (configLocalPrograms config)))
$ soptsResolveMissingGHC sopts)
suggestion

-- Install msys2 on windows, if necessary
mmsys2Tool <- getMmsys2Tool
Expand Down
2 changes: 1 addition & 1 deletion src/Stack/SetupCmd.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ setupParser = SetupCmdOpts
"The default is to install the version implied by the resolver.")))
<*> OA.boolFlags False
"reinstall"
"reinstalling GHC, even if available (implies no-system-ghc)"
"reinstalling GHC, even if available (incompatible with --system-ghc)"
OA.idm
<*> OA.boolFlags False
"upgrade-cabal"
Expand Down
13 changes: 6 additions & 7 deletions src/Stack/Types/Build.hs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import qualified Data.ByteString as S
import Data.Char (isSpace)
import Data.Data
import Data.Hashable
import Data.List (dropWhileEnd, intercalate)
import Data.List.Extra
import qualified Data.Map as Map
import Data.Map.Strict (Map)
import Data.Maybe
Expand Down Expand Up @@ -93,14 +93,13 @@ import System.Process.Log (showProcessArgDebug)
data StackBuildException
= Couldn'tFindPkgId PackageName
| CompilerVersionMismatch
(Maybe (CompilerVersion, Arch))
(CompilerVersion, Arch)
GHCVariant
CompilerBuild
(Maybe (CompilerVersion, Arch)) -- found
(CompilerVersion, Arch) -- expected
GHCVariant -- expected
CompilerBuild -- expected
VersionCheck
(Maybe (Path Abs File))
(Maybe (Path Abs File)) -- Path to the stack.yaml file
Text -- recommended resolution
-- ^ Path to the stack.yaml file
| Couldn'tParseTargets [Text]
| UnknownTargets
(Set PackageName) -- no known version
Expand Down
15 changes: 15 additions & 0 deletions src/Stack/Types/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,8 @@ data ConfigException
| Won'tCreateStackRootInDirectoryOwnedByDifferentUser (Path Abs Dir) (Path Abs Dir) -- ^ @$STACK_ROOT@, parent dir
| UserDoesn'tOwnDirectory (Path Abs Dir)
| FailedToCloneRepo String
| ManualGHCVariantSettingsAreIncompatibleWithSystemGHC
| NixRequiresSystemGhc
deriving Typeable
instance Show ConfigException where
show (ParseConfigFileException configFile exception) = concat
Expand Down Expand Up @@ -1213,6 +1215,19 @@ instance Show ConfigException where
, commandName
, " is installed and available to stack on your PATH environment variable."
]
show ManualGHCVariantSettingsAreIncompatibleWithSystemGHC = T.unpack $ T.concat
[ "stack can only control the "
, configMonoidGHCVariantName
, " of its own GHC installations. Please use '--no-"
, configMonoidSystemGHCName
, "'."
]
show NixRequiresSystemGhc = T.unpack $ T.concat
[ "stack's Nix integration is incompatible with '--no-system-ghc'. "
, "Please use '--"
, configMonoidSystemGHCName
, "' or disable the Nix integration."
]
instance Exception ConfigException

showOptions :: WhichSolverCmd -> String
Expand Down
4 changes: 3 additions & 1 deletion test/integration/IntegrationSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ test :: FilePath -- ^ runghc
test runghc env' currDir origStackRoot newHome name = it name $ withDir $ \dir -> do
newHomeExists <- doesDirectoryExist newHome
when newHomeExists (removeDirectoryRecursive newHome)
copyTree toCopyRoot origStackRoot (newHome </> takeFileName origStackRoot)
let newStackRoot = newHome </> takeFileName origStackRoot
copyTree toCopyRoot origStackRoot newStackRoot
writeFile (newStackRoot </> "config.yaml") "system-ghc: true"
let testDir = currDir </> "tests" </> name
mainFile = testDir </> "Main.hs"
libDir = currDir </> "lib"
Expand Down