diff --git a/.gitignore b/.gitignore index 435ea3258a..4ed120413f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ .stack-root/ /.cabal-sandbox/ TAGS -Setup +/Setup/ cabal-dev/ cabal.sandbox.config dist/ diff --git a/ChangeLog.md b/ChangeLog.md index 4fe0c51837..3a5ee352de 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -8,11 +8,22 @@ Release notes: Major changes: +* `setup-info-locations` yaml configuration now allows overwriting the default locations of `stack-setup-2.yaml`. + [#5031](https://github.com/commercialhaskell/stack/pull/5031) + [#2983](https://github.com/commercialhaskell/stack/issues/2983) + [#2913](https://github.com/commercialhaskell/stack/issues/2913) + +* The `setup-info` configuration key now allows overwriting parts of the default `setup-info` + +* The `--setup-info-yaml` command line flag now may be used in all stack commands such as `stack build`, and not only in `stack setup` + +* The `--setup-info-yaml` may specify multiple locations for `stack-setup.yaml` files. Behavior changes: +* Remove the deprecated `--stack-setup-yaml` command line argument in favor of `--setup-info-yaml` + [#2647](https://github.com/commercialhaskell/stack/issues/2647) Other enhancements: - * Add `build-output-timestamps` flag in yaml. Setting it to true prefixes each build log output line with a timestamp. @@ -26,6 +37,9 @@ Other enhancements: * Remove warning for using Stack with GHC 8.8 and Cabal 3.0. +* Allow relative paths in `--setup-info-yaml` and tool paths + [#3394](https://github.com/commercialhaskell/stack/issues/3394) + Bug fixes: * Upgrade `pantry`: module mapping insertions into the database are now atomic. diff --git a/doc/install_and_upgrade.md b/doc/install_and_upgrade.md index 23c3dea5a7..1fda7f7671 100644 --- a/doc/install_and_upgrade.md +++ b/doc/install_and_upgrade.md @@ -319,11 +319,10 @@ If you're attempting to install stack from within China: ``` ###ADD THIS IF YOU LIVE IN CHINA -setup-info: "http://mirrors.tuna.tsinghua.edu.cn/stackage/stack-setup.yaml" +setup-info-locations: +- "http://mirrors.tuna.tsinghua.edu.cn/stackage/stack-setup.yaml" urls: latest-snapshot: http://mirrors.tuna.tsinghua.edu.cn/stackage/snapshots.json - lts-build-plans: http://mirrors.tuna.tsinghua.edu.cn/stackage/lts-haskell/ - nightly-build-plans: http://mirrors.tuna.tsinghua.edu.cn/stackage/stackage-nightly/ package-indices: - name: Tsinghua download-prefix: http://mirrors.tuna.tsinghua.edu.cn/hackage/package/ diff --git a/doc/yaml_configuration.md b/doc/yaml_configuration.md index 51e63b9385..f596268342 100644 --- a/doc/yaml_configuration.md +++ b/doc/yaml_configuration.md @@ -617,8 +617,9 @@ Specify a variant binary distribution of GHC to use. Known values: * `integersimple`: Use a GHC bindist that uses [integer-simple instead of GMP](https://ghc.haskell.org/trac/ghc/wiki/ReplacingGMPNotes) * any other value: Use a custom GHC bindist. You should specify - [setup-info](#setup-info) so `stack setup` knows where to download it, or - pass the `stack setup --ghc-bindist` argument on the command-line + [setup-info](#setup-info) or [setup-info-locations](#setup-info-locations) + 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`. @@ -630,13 +631,91 @@ Specify a specialized architecture bindist to use. Normally this is determined automatically, but you can override the autodetected value here. Possible arguments include `standard`, `gmp4`, `tinfo6`, and `nopie`. +### setup-info-locations + +(Since 2.3) + +Possible usages of this config are: +1. Using `stack` offline or behind a firewall +2. Extending the tools known to `stack` such as cutting-edge versions of `ghc` or builds for custom linux distributions. + +The `setup-info` dictionary specifies locations for installation of Haskell-related tooling - it maps `(Tool, Platform, Version)` to the location where it can be obtained, such as `(GHC, Windows64, 8.6.5)` to the url hosting the `*.tar.xz` for GHC's installation. + +By default, it's obtained from [stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml). + +The `setup-info` dictionary is constructed in the following order: +1. `setup-info` yaml configuration - inline config +2. `--setup-info-yaml` command line arguments - urls or paths, multiple locations may be specified. +3. `setup-info-locations` yaml configuration - urls or paths + +The first location which specifies the location of a tool `(Tool, Platform, Version)` takes precedence, so one can extend the default tools with a fallback to the default `setup-info` location: + +```yaml +setup-info-locations: +- C:/stack-offline/my-stack-setup.yaml +- relative/inside/my/project/setup-info.yaml +- \\smbShare\stack\my-stack-setup.yaml +- http://stack-mirror.com/stack-setup.yaml +- https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml +``` + +The default `setup-info` location is included only if no locations in the `setup-info-locations` config or the `--setup-info-yaml` command line argument were specified. + +Thus the following will cause `stack setup` not to consult github for the `setup-info`: +```yaml +setup-info-locations: +- C:/stack-offline/my-stack-setup.yaml +``` + +```yaml +setup-info-locations: [] +``` + +Relative paths are resolved relative to the `stack.yaml` file - either in the local project or the global `stack.yaml` in the stack directory. + +Relative paths may also be used inside paths to tool installs - such as for ghc or 7z, which allows vendoring the tools inside a monorepo. +For example: + +Directory structure: +``` +- src/ +- installs/ + - my-stack-setup.yaml + - 7z.exe + - 7z.dll + - ghc-8.2.2.tar.xz +- stack.yaml +``` + +In the project's `stack.yaml`: +```yaml +setup-info-locations: +- installs/my-stack-setup.yaml +``` + +In `installs/my-stack-setup.yaml`: +```yaml +sevenzexe-info: + url: "installs/7z.exe" + +sevenzdll-info: + url: "installs/7z.dll" + +ghc: + windows64: + 8.2.2: + url: "installs/ghc-8.2.2.tar.xz" +``` + ### setup-info (Since 0.1.5) Allows augmenting from where tools like GHC and msys2 (on Windows) are downloaded. Most useful for specifying locations of custom GHC binary -distributions (for use with the [ghc-variant](#ghc-variant) option): +distributions (for use with the [ghc-variant](#ghc-variant) option). + +The format of this field is the same as in the default [stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml): ```yaml setup-info: @@ -646,19 +725,15 @@ setup-info: url: "https://example.com/ghc-7.10.2-i386-unknown-mingw32-foo.tar.xz" ``` -Or you can point to external setup-info: +This configuration **adds** the specified setup info metadata to the default; +Specifying this config **does not** prevent the default `stack-setup-2.yaml` from being consulted as a fallback. + +If you need to **replace** the default setup-info, add the following: ```yaml -setup-info: "https://example.com/my-stack-setup-info.yaml" +setup-info-locations: [] ``` -This may be either URL or (since 1.2.0) absolute file path. - -Note that this **adds** the specified setup info metadata to the default. -If you need to **replace** it, use the `stack --setup-info-yaml` command-line -argument instead. The default setup metadata is in -[stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml). - ### pvp-bounds (Since 0.1.5) diff --git a/src/Stack/Config.hs b/src/Stack/Config.hs index 7008c33e77..eef5b56b09 100644 --- a/src/Stack/Config.hs +++ b/src/Stack/Config.hs @@ -320,6 +320,7 @@ configFromConfigMonoid configGhcOptionsByName = coerce configMonoidGhcOptionsByName configGhcOptionsByCat = coerce configMonoidGhcOptionsByCat configSetupInfoLocations = configMonoidSetupInfoLocations + configSetupInfoInline = configMonoidSetupInfoInline configPvpBounds = fromFirst (PvpBounds PvpBoundsNone False) configMonoidPvpBounds configModifyCodePage = fromFirstTrue configMonoidModifyCodePage configExplicitSetupDeps = configMonoidExplicitSetupDeps diff --git a/src/Stack/Options/ConfigParser.hs b/src/Stack/Options/ConfigParser.hs index 7d5f5509f6..e1874c8787 100644 --- a/src/Stack/Options/ConfigParser.hs +++ b/src/Stack/Options/ConfigParser.hs @@ -21,8 +21,8 @@ configOptsParser :: FilePath -> GlobalOptsContext -> Parser ConfigMonoid configOptsParser currentDir hide0 = (\stackRoot workDir buildOpts dockerOpts nixOpts systemGHC installGHC arch ghcVariant ghcBuild jobs includes libs overrideGccPath overrideHpack - skipGHCCheck skipMsys localBin modifyCodePage allowDifferentUser - dumpLogs colorWhen -> mempty + skipGHCCheck skipMsys localBin setupInfoLocations modifyCodePage + allowDifferentUser dumpLogs colorWhen -> mempty { configMonoidStackRoot = stackRoot , configMonoidWorkDir = workDir , configMonoidBuildOpts = buildOpts @@ -41,6 +41,7 @@ configOptsParser currentDir hide0 = , configMonoidOverrideHpack = overrideHpack , configMonoidSkipMsys = skipMsys , configMonoidLocalBinPath = localBin + , configMonoidSetupInfoLocations = setupInfoLocations , configMonoidModifyCodePage = modifyCodePage , configMonoidAllowDifferentUser = allowDifferentUser , configMonoidDumpLogs = dumpLogs @@ -128,6 +129,11 @@ configOptsParser currentDir hide0 = <> help "Install binaries to DIR" <> hide )) + <*> many ( + strOption + ( long "setup-info-yaml" + <> help "Alternate URL or relative / absolute path for stack dependencies" + <> metavar "URL" )) <*> firstBoolFlagsTrue "modify-code-page" "setting the codepage to support UTF-8 (Windows only)" diff --git a/src/Stack/Setup.hs b/src/Stack/Setup.hs index 0fd7ee59ff..df2314b7b7 100644 --- a/src/Stack/Setup.hs +++ b/src/Stack/Setup.hs @@ -121,8 +121,6 @@ data SetupOpts = SetupOpts -- ^ Do not use a custom msys installation on Windows , soptsResolveMissingGHC :: !(Maybe Text) -- ^ Message shown to user for how to resolve the missing GHC - , soptsSetupInfoYaml :: !FilePath - -- ^ Location of the main stack-setup.yaml file , soptsGHCBindistURL :: !(Maybe String) -- ^ Alternate GHC binary distribution (requires custom GHCVariant) , soptsGHCJSBootOpts :: [String] @@ -225,7 +223,6 @@ setupEnv needTargets boptsCLI mResolveMissingGHC = do , soptsSkipGhcCheck = configSkipGHCCheck config , soptsSkipMsys = configSkipMsys config , soptsResolveMissingGHC = mResolveMissingGHC - , soptsSetupInfoYaml = defaultSetupInfoYaml , soptsGHCBindistURL = Nothing , soptsGHCJSBootOpts = ["--clean"] } @@ -450,13 +447,13 @@ addIncludeLib (ExtraDirs _bins includes libs) config = config -- | Ensure both the compiler and the msys toolchain are installed and -- provide the PATHs to add if necessary ensureCompilerAndMsys - :: (HasConfig env, HasGHCVariant env) + :: (HasBuildConfig env, HasGHCVariant env) => SetupOpts -> RIO env (CompilerPaths, ExtraDirs) ensureCompilerAndMsys sopts = do didWarn <- warnUnsupportedCompiler $ getGhcVersion $ wantedToActual $ soptsWantedCompiler sopts - getSetupInfo' <- memoizeRef (getSetupInfo (soptsSetupInfoYaml sopts)) + getSetupInfo' <- memoizeRef getSetupInfo (cp, ghcPaths) <- ensureCompiler sopts getSetupInfo' warnUnsupportedCompilerCabal cp didWarn @@ -519,7 +516,7 @@ warnUnsupportedCompilerCabal cp didWarn = do -- | Ensure that the msys toolchain is installed if necessary and -- provide the PATHs to add if necessary ensureMsys - :: HasConfig env + :: HasBuildConfig env => SetupOpts -> Memoized SetupInfo -> RIO env (Maybe Tool) @@ -549,7 +546,7 @@ ensureMsys sopts getSetupInfo' = do _ -> return Nothing installGhcBindist - :: HasConfig env + :: HasBuildConfig env => SetupOpts -> Memoized SetupInfo -> [Tool] @@ -610,7 +607,7 @@ installGhcBindist sopts getSetupInfo' installed = do -- | Ensure compiler (ghc or ghcjs) is installed, without worrying about msys ensureCompiler - :: forall env. (HasConfig env, HasGHCVariant env) + :: forall env. (HasBuildConfig env, HasGHCVariant env) => SetupOpts -> Memoized SetupInfo -> RIO env (CompilerPaths, ExtraDirs) @@ -652,7 +649,7 @@ ensureCompiler sopts getSetupInfo' = do pure (cp, paths) ensureSandboxedCompiler - :: HasConfig env + :: HasBuildConfig env => SetupOpts -> Memoized SetupInfo -> RIO env (CompilerPaths, ExtraDirs) @@ -826,7 +823,7 @@ pathsFromCompiler wc compilerBuild isSandboxed compiler = withCache $ handleAny buildGhcFromSource :: forall env. ( HasTerm env , HasProcessContext env - , HasConfig env + , HasBuildConfig env ) => Memoized SetupInfo -> [Tool] -> CompilerRepository -> Text -> Text -> RIO env (Tool, CompilerBuild) buildGhcFromSource getSetupInfo' installed (CompilerRepository url) commitId flavour = do @@ -1070,26 +1067,25 @@ sourceSystemCompilers wanted = do | otherwise = id -- | Download the most recent SetupInfo -getSetupInfo :: HasConfig env => String -> RIO env SetupInfo -getSetupInfo stackSetupYaml = do +getSetupInfo :: HasConfig env => RIO env SetupInfo +getSetupInfo = do config <- view configL - setupInfos <- - mapM - loadSetupInfo - (SetupInfoFileOrURL stackSetupYaml : - configSetupInfoLocations config) - return (mconcat setupInfos) + let inlineSetupInfo = configSetupInfoInline config + locations' = configSetupInfoLocations config + locations = if null locations' then [defaultSetupInfoYaml] else locations' + + resolvedSetupInfos <- mapM loadSetupInfo locations + return (inlineSetupInfo <> mconcat resolvedSetupInfos) where - loadSetupInfo (SetupInfoInline si) = return si - loadSetupInfo (SetupInfoFileOrURL urlOrFile) = do - bs <- - case parseUrlThrow urlOrFile of - Just req -> liftM (LBS.toStrict . getResponseBody) $ httpLbs req - Nothing -> liftIO $ S.readFile urlOrFile - WithJSONWarnings si warnings <- either throwM return (Yaml.decodeEither' bs) - when (urlOrFile /= defaultSetupInfoYaml) $ - logJSONWarnings urlOrFile warnings - return si + loadSetupInfo urlOrFile = do + bs <- + case parseUrlThrow urlOrFile of + Just req -> liftM (LBS.toStrict . getResponseBody) $ httpLbs req + Nothing -> liftIO $ S.readFile urlOrFile + WithJSONWarnings si warnings <- either throwM return (Yaml.decodeEither' bs) + when (urlOrFile /= defaultSetupInfoYaml) $ + logJSONWarnings urlOrFile warnings + return si getInstalledTool :: [Tool] -- ^ already installed -> PackageName -- ^ package to find @@ -1108,7 +1104,7 @@ getInstalledTool installed name goodVersion = else Nothing goodPackage _ = Nothing -downloadAndInstallTool :: HasTerm env +downloadAndInstallTool :: (HasTerm env, HasBuildConfig env) => Path Abs Dir -> DownloadInfo -> Tool @@ -1127,7 +1123,7 @@ downloadAndInstallTool programsDir downloadInfo tool installer = do liftIO $ ignoringAbsence (removeDirRecur tempDir) return tool -downloadAndInstallCompiler :: (HasConfig env, HasGHCVariant env) +downloadAndInstallCompiler :: (HasBuildConfig env, HasGHCVariant env) => CompilerBuild -> SetupInfo -> WantedCompiler @@ -1199,7 +1195,7 @@ getWantedCompilerInfo key versionCheck wanted toCV pairs_ = -- | Download and install the first available compiler build. downloadAndInstallPossibleCompilers - :: (HasGHCVariant env, HasConfig env) + :: (HasGHCVariant env, HasBuildConfig env) => [CompilerBuild] -> SetupInfo -> WantedCompiler @@ -1266,41 +1262,53 @@ getOSKey platform = Platform AArch64 Cabal.Linux -> return "linux-aarch64" Platform arch os -> throwM $ UnsupportedSetupCombo os arch +downloadOrUseLocal + :: (HasTerm env, HasBuildConfig env) + => Text -> DownloadInfo -> Path Abs File -> RIO env (Path Abs File) +downloadOrUseLocal downloadLabel downloadInfo destination = + case url of + (parseUrlThrow -> Just _) -> do + ensureDir (parent destination) + chattyDownload downloadLabel downloadInfo destination + return destination + (parseAbsFile -> Just path) -> do + warnOnIgnoredChecks + return path + (parseRelFile -> Just path) -> do + warnOnIgnoredChecks + root <- view projectRootL + return (root path) + _ -> + throwString $ "Error: `url` must be either an HTTP URL or a file path: " ++ url + where + url = T.unpack $ downloadInfoUrl downloadInfo + warnOnIgnoredChecks = do + let DownloadInfo{downloadInfoContentLength=contentLength, downloadInfoSha1=sha1, + downloadInfoSha256=sha256} = downloadInfo + when (isJust contentLength) $ + logWarn "`content-length` is not checked and should not be specified when `url` is a file path" + when (isJust sha1) $ + logWarn "`sha1` is not checked and should not be specified when `url` is a file path" + when (isJust sha256) $ + logWarn "`sha256` is not checked and should not be specified when `url` is a file path" + downloadFromInfo - :: HasTerm env + :: (HasTerm env, HasBuildConfig env) => Path Abs Dir -> DownloadInfo -> Tool -> RIO env (Path Abs File, ArchiveType) downloadFromInfo programsDir downloadInfo tool = do - at <- + archiveType <- case extension of ".tar.xz" -> return TarXz ".tar.bz2" -> return TarBz2 ".tar.gz" -> return TarGz ".7z.exe" -> return SevenZ _ -> throwString $ "Error: Unknown extension for url: " ++ url + relativeFile <- parseRelFile $ toolString tool ++ extension - path <- case url of - (parseUrlThrow -> Just _) -> do - let path = programsDir relativeFile - ensureDir programsDir - chattyDownload (T.pack (toolString tool)) downloadInfo path - return path - (parseAbsFile -> Just path) -> do - let DownloadInfo{downloadInfoContentLength=contentLength, downloadInfoSha1=sha1, - downloadInfoSha256=sha256} = - downloadInfo - when (isJust contentLength) $ - logWarn ("`content-length` in not checked \n" <> - "and should not be specified when `url` is a file path") - when (isJust sha1) $ - logWarn ("`sha1` is not checked and \n" <> - "should not be specified when `url` is a file path") - when (isJust sha256) $ - logWarn ("`sha256` is not checked and \n" <> - "should not be specified when `url` is a file path") - return path - _ -> - throwString $ "Error: `url` must be either an HTTP URL or absolute file path: " ++ url - return (path, at) + let destinationPath = programsDir relativeFile + localPath <- downloadOrUseLocal (T.pack (toolString tool)) downloadInfo destinationPath + return (localPath, archiveType) + where url = T.unpack $ downloadInfoUrl downloadInfo extension = loop url @@ -1311,6 +1319,7 @@ downloadFromInfo programsDir downloadInfo tool = do where (fp', ext) = FP.splitExtension fp + data ArchiveType = TarBz2 | TarXz @@ -1438,7 +1447,7 @@ instance Alternative (CheckDependency env) where Left _ -> y Right x' -> return $ Right x' -installGHCWindows :: HasConfig env +installGHCWindows :: HasBuildConfig env => Maybe Version -> SetupInfo -> Path Abs File @@ -1451,7 +1460,7 @@ installGHCWindows mversion si archiveFile archiveType _tempDir destDir = do withUnpackedTarball7z "GHC" si archiveFile archiveType tarComponent destDir logInfo $ "GHC installed to " <> fromString (toFilePath destDir) -installMsys2Windows :: HasConfig env +installMsys2Windows :: HasBuildConfig env => Text -- ^ OS Key -> SetupInfo -> Path Abs File @@ -1492,7 +1501,7 @@ installMsys2Windows osKey si archiveFile archiveType _tempDir destDir = do -- | Unpack a compressed tarball using 7zip. Expects a single directory in -- the unpacked results, which is renamed to the destination directory. -withUnpackedTarball7z :: HasConfig env +withUnpackedTarball7z :: HasBuildConfig env => String -- ^ Name of tool, used in error messages -> SetupInfo -> Path Abs File -- ^ Path to archive file @@ -1533,20 +1542,20 @@ expectSingleUnpackedDir archiveFile destDir = do -- | Download 7z as necessary, and get a function for unpacking things. -- -- Returned function takes an unpack directory and archive. -setup7z :: (HasConfig env, MonadIO m) +setup7z :: (HasBuildConfig env, MonadIO m) => SetupInfo -> RIO env (Path Abs Dir -> Path Abs File -> m ()) setup7z si = do dir <- view $ configL.to configLocalPrograms ensureDir dir - let exe = dir relFile7zexe - dll = dir relFile7zdll + let exeDestination = dir relFile7zexe + dllDestination = dir relFile7zdll case (siSevenzDll si, siSevenzExe si) of (Just sevenzDll, Just sevenzExe) -> do - chattyDownload "7z.dll" sevenzDll dll - chattyDownload "7z.exe" sevenzExe exe + _ <- downloadOrUseLocal "7z.dll" sevenzDll dllDestination + exePath <- downloadOrUseLocal "7z.exe" sevenzExe exeDestination withRunInIO $ \run -> return $ \outdir archive -> liftIO $ run $ do - let cmd = toFilePath exe + let cmd = toFilePath exePath args = [ "x" , "-o" ++ toFilePath outdir diff --git a/src/Stack/SetupCmd.hs b/src/Stack/SetupCmd.hs index bf010243ec..d4ad51b45d 100644 --- a/src/Stack/SetupCmd.hs +++ b/src/Stack/SetupCmd.hs @@ -27,25 +27,11 @@ import Stack.Types.Version data SetupCmdOpts = SetupCmdOpts { scoCompilerVersion :: !(Maybe WantedCompiler) , scoForceReinstall :: !Bool - , scoSetupInfoYaml :: !String , scoGHCBindistURL :: !(Maybe String) , scoGHCJSBootOpts :: ![String] , scoGHCJSBootClean :: !Bool } -setupYamlCompatParser :: OA.Parser String -setupYamlCompatParser = stackSetupYaml <|> setupInfoYaml - where stackSetupYaml = OA.strOption ( - OA.long "stack-setup-yaml" - <> OA.help "DEPRECATED: Use 'setup-info-yaml' instead" - <> OA.metavar "URL" - <> OA.hidden ) - setupInfoYaml = OA.strOption ( - OA.long "setup-info-yaml" - <> OA.help "Alternate URL or absolute path for stack dependencies" - <> OA.metavar "URL" - <> OA.value defaultSetupInfoYaml ) - setupParser :: OA.Parser SetupCmdOpts setupParser = SetupCmdOpts <$> OA.optional (OA.argument readVersion @@ -56,7 +42,6 @@ setupParser = SetupCmdOpts "reinstall" "reinstalling GHC, even if available (incompatible with --system-ghc)" OA.idm - <*> setupYamlCompatParser <*> OA.optional (OA.strOption (OA.long "ghc-bindist" <> OA.metavar "URL" @@ -80,7 +65,7 @@ setupParser = SetupCmdOpts Right x -> return x setup - :: (HasConfig env, HasGHCVariant env) + :: (HasBuildConfig env, HasGHCVariant env) => SetupCmdOpts -> WantedCompiler -> VersionCheck @@ -99,7 +84,6 @@ setup SetupCmdOpts{..} wantedCompiler compilerCheck mstack = do , soptsSkipGhcCheck = False , soptsSkipMsys = configSkipMsys , soptsResolveMissingGHC = Nothing - , soptsSetupInfoYaml = scoSetupInfoYaml , soptsGHCBindistURL = scoGHCBindistURL , soptsGHCJSBootOpts = scoGHCJSBootOpts ++ ["--clean" | scoGHCJSBootClean] } diff --git a/src/Stack/Types/Config.hs b/src/Stack/Types/Config.hs index 8ccdae83d7..bcc30c977b 100644 --- a/src/Stack/Types/Config.hs +++ b/src/Stack/Types/Config.hs @@ -140,7 +140,6 @@ module Stack.Types.Config ,VersionedDownloadInfo(..) ,GHCDownloadInfo(..) ,SetupInfo(..) - ,SetupInfoLocation(..) -- ** Docker entrypoint ,DockerEntrypoint(..) ,DockerUser(..) @@ -182,7 +181,7 @@ import Pantry.Internal.AesonExtended (ToJSON, toJSON, FromJSON, FromJSONKey (..), parseJSON, withText, object, (.=), (..:), (...:), (..:?), (..!=), Value(Bool), withObjectWarnings, WarningParser, Object, jsonSubWarnings, - jsonSubWarningsT, jsonSubWarningsTT, WithJSONWarnings(..), noJSONWarnings, + jsonSubWarningsT, jsonSubWarningsTT, WithJSONWarnings(..), FromJSONKeyFunction (FromJSONKeyTextParser)) import Data.Attoparsec.Args (parseArgs, EscapingMode (Escaping)) import qualified Data.ByteArray.Encoding as Mem (convertToBase, Base(Base16)) @@ -333,8 +332,11 @@ data Config = -- ^ Additional GHC options to apply to categories of packages ,configCabalConfigOpts :: !(Map CabalConfigKey [Text]) -- ^ Additional options to be passed to ./Setup.hs configure - ,configSetupInfoLocations :: ![SetupInfoLocation] - -- ^ Additional SetupInfo (inline or remote) to use to find tools. + ,configSetupInfoLocations :: ![String] + -- ^ URLs or paths to stack-setup.yaml files, for finding tools. + -- If none present, the default setup-info is used. + ,configSetupInfoInline :: !SetupInfo + -- ^ Additional SetupInfo to use to find tools. ,configPvpBounds :: !PvpBounds -- ^ How PVP upper bounds should be added to packages ,configModifyCodePage :: !Bool @@ -820,8 +822,10 @@ data ConfigMonoid = -- ^ See 'configCabalConfigOpts'. ,configMonoidExtraPath :: ![Path Abs Dir] -- ^ Additional paths to search for executables in - ,configMonoidSetupInfoLocations :: ![SetupInfoLocation] - -- ^ Additional setup info (inline or remote) to use for installing tools + ,configMonoidSetupInfoLocations :: ![String] + -- ^ See 'configSetupInfoLocations' + ,configMonoidSetupInfoInline :: !SetupInfo + -- ^ See 'configSetupInfoInline' ,configMonoidLocalProgramsBase :: !(First (Path Abs Dir)) -- ^ Override the default local programs dir, where e.g. GHC is installed. ,configMonoidPvpBounds :: !(First PvpBounds) @@ -947,8 +951,8 @@ parseConfigMonoidObject rootDir obj = do let configMonoidCabalConfigOpts = coerce (configMonoidCabalConfigOpts' :: Map CabalConfigKey [Text]) configMonoidExtraPath <- obj ..:? configMonoidExtraPathName ..!= [] - configMonoidSetupInfoLocations <- - maybeToList <$> jsonSubWarningsT (obj ..:? configMonoidSetupInfoLocationsName) + configMonoidSetupInfoLocations <- obj ..:? configMonoidSetupInfoLocationsName ..!= [] + configMonoidSetupInfoInline <- jsonSubWarningsT (obj ..:? configMonoidSetupInfoInlineName) ..!= mempty configMonoidLocalProgramsBase <- First <$> obj ..:? configMonoidLocalProgramsBaseName configMonoidPvpBounds <- First <$> obj ..:? configMonoidPvpBoundsName configMonoidModifyCodePage <- FirstTrue <$> obj ..:? configMonoidModifyCodePageName @@ -1080,7 +1084,10 @@ configMonoidExtraPathName :: Text configMonoidExtraPathName = "extra-path" configMonoidSetupInfoLocationsName :: Text -configMonoidSetupInfoLocationsName = "setup-info" +configMonoidSetupInfoLocationsName = "setup-info-locations" + +configMonoidSetupInfoInlineName :: Text +configMonoidSetupInfoInlineName = "setup-info" configMonoidLocalProgramsBaseName :: Text configMonoidLocalProgramsBaseName = "local-programs-path" @@ -1687,15 +1694,15 @@ instance FromJSON (WithJSONWarnings SetupInfo) where return SetupInfo {..} -- | For @siGHCs@ and @siGHCJSs@ fields maps are deeply merged. --- For all fields the values from the last @SetupInfo@ win. +-- For all fields the values from the first @SetupInfo@ win. instance Semigroup SetupInfo where l <> r = SetupInfo - { siSevenzExe = siSevenzExe r <|> siSevenzExe l - , siSevenzDll = siSevenzDll r <|> siSevenzDll l - , siMsys2 = siMsys2 r <> siMsys2 l - , siGHCs = Map.unionWith (<>) (siGHCs r) (siGHCs l) - , siGHCJSs = Map.unionWith (<>) (siGHCJSs r) (siGHCJSs l) + { siSevenzExe = siSevenzExe l <|> siSevenzExe r + , siSevenzDll = siSevenzDll l <|> siSevenzDll r + , siMsys2 = siMsys2 l <> siMsys2 r + , siGHCs = Map.unionWith (<>) (siGHCs l) (siGHCs r) + , siGHCJSs = Map.unionWith (<>) (siGHCJSs l) (siGHCJSs r) , siStack = Map.unionWith (<>) (siStack l) (siStack r) } instance Monoid SetupInfo where @@ -1710,22 +1717,6 @@ instance Monoid SetupInfo where } mappend = (<>) --- | Remote or inline 'SetupInfo' -data SetupInfoLocation - = SetupInfoFileOrURL String - | SetupInfoInline SetupInfo - deriving (Show) - -instance FromJSON (WithJSONWarnings SetupInfoLocation) where - parseJSON v = - (noJSONWarnings <$> - withText "SetupInfoFileOrURL" (pure . SetupInfoFileOrURL . T.unpack) v) <|> - inline - where - inline = do - WithJSONWarnings si w <- parseJSON v - return $ WithJSONWarnings (SetupInfoInline si) w - -- | How PVP bounds should be added to .cabal files data PvpBoundsType = PvpBoundsNone diff --git a/src/main/Main.hs b/src/main/Main.hs index 7c302b0baf..6c707bcb48 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -539,11 +539,11 @@ interpreterHandler currentDir args f = do return (a,(b,mempty)) setupCmd :: SetupCmdOpts -> RIO Runner () -setupCmd sco@SetupCmdOpts{..} = withConfig YesReexec $ do +setupCmd sco@SetupCmdOpts{..} = withConfig YesReexec $ withBuildConfig $ do (wantedCompiler, compilerCheck, mstack) <- case scoCompilerVersion of Just v -> return (v, MatchMinor, Nothing) - Nothing -> withBuildConfig $ (,,) + Nothing -> (,,) <$> view wantedCompilerVersionL <*> view (configL.to configCompilerCheck) <*> (Just <$> view stackYamlL)