From f0fb4b76106fb7d41c333cad5f99e63101e2ed09 Mon Sep 17 00:00:00 2001 From: Mike Pilgrem Date: Sat, 9 Sep 2023 00:55:34 +0100 Subject: [PATCH] Drop Cabal < 1.24.0.0 --- CONTRIBUTING.md | 10 ++--- ChangeLog.md | 3 ++ src/Stack/Build.hs | 8 ++-- src/Stack/Coverage.hs | 96 +++++++++++++++++++++---------------------- src/Stack/Setup.hs | 6 +-- 5 files changed, 61 insertions(+), 62 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f47ec6ec15..10b6c9b550 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -295,11 +295,11 @@ executable that it compiles from Haskell source code. The executable compiles that code with a dependency on the version of Cabal that ships with the specified GHC compiler. Each release of Stack will aim to support all versions of GHC and the Cabal package in Stackage snapshots published within seven years -of the release. For example, snapshot LTS Haskell 7.0, published on -14 September 2016, was the first LTS Haskell snapshot to provide GHC 8.0.1 which -comes with `base-4.9.0.0` and `Cabal-1.24.0.0`. Until, at least, -13 September 2023, Stack releases would aim to support the immediate -predecessor, GHC 7.10.3 and `base-4.8.2.0` and `Cabal-1.22.5.0`. +of the release. For example, snapshot LTS Haskell 8.0, published on +12 February 2017, was the first LTS Haskell snapshot to provide GHC 8.0.2 which +comes with `base-4.9.1.0` and `Cabal-1.24.2.0`. Until, at least, +13 February 2024, Stack releases would aim to support the immediate +predecessor, GHC 8.0.1 and `base-4.9.0.0` and `Cabal-1.24.0.0`. When a version of the Stack executable actually ceases to support a version of GHC and `Cabal`, that should be recorded in Stack's diff --git a/ChangeLog.md b/ChangeLog.md index 79a37563cc..67679f438d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -27,6 +27,9 @@ Behavior changes: * When auto-detecting `--ghc-build` on Linux, the `musl` GHC build only is considered a possible GHC build if `libc.musl-x86_64.so.1` is found in `\lib` or `\lib64`. +* No longer supports Cabal versions older than `1.24.0.0`. This means projects + using snapshots earlier than `lts-7.0` or `nightly-2016-05-26` will no longer + build. Other enhancements: diff --git a/src/Stack/Build.hs b/src/Stack/Build.hs index 6d44aae208..79314a364c 100644 --- a/src/Stack/Build.hs +++ b/src/Stack/Build.hs @@ -77,13 +77,13 @@ instance Pretty CabalVersionPrettyException where "[S-5973]" <> line <> fillSep - [ flow "Stack does not support Cabal versions before 1.22, but \ + [ flow "Stack does not support Cabal versions before 1.24, but \ \version" , fromString $ versionString cabalVer , flow "was found. To fix this, consider updating the snapshot to" - , style Shell "lts-3.0" + , style Shell "lts-7.0" , flow "or later or to" - , style Shell "nightly-2015-05-05" + , style Shell "nightly-2016-05-26" , flow "or later." ] @@ -206,7 +206,7 @@ justLocals = checkCabalVersion :: HasEnvConfig env => RIO env () checkCabalVersion = do cabalVer <- view cabalVersionL - when (cabalVer < mkVersion [1, 22]) $ + when (cabalVer < mkVersion [1, 24]) $ prettyThrowM $ CabalVersionNotSupported cabalVer -- | See https://github.com/commercialhaskell/stack/issues/1198. diff --git a/src/Stack/Coverage.hs b/src/Stack/Coverage.hs index 19db0eb79c..94bbe41714 100644 --- a/src/Stack/Coverage.hs +++ b/src/Stack/Coverage.hs @@ -45,7 +45,6 @@ import Stack.Runners ( ShouldReexec (..), withConfig, withEnvConfig ) import Stack.Types.BuildConfig ( BuildConfig (..), HasBuildConfig (..) ) import Stack.Types.Compiler ( getGhcVersion ) -import Stack.Types.CompilerPaths ( cabalVersionL ) import Stack.Types.BuildOpts ( BuildOptsCLI (..), defaultBuildOptsCLI ) import Stack.Types.EnvConfig ( EnvConfig (..), HasEnvConfig (..), actualCompilerVersionL @@ -590,60 +589,57 @@ findPackageFieldForBuiltPackage pkgDir pkgId internalLibs field = do distDir <- distDirFromDir pkgDir let inplaceDir = distDir relDirPackageConfInplace pkgIdStr = packageIdentifierString pkgId - notFoundErr = pure $ Left $ "Failed to find package key for " <> T.pack pkgIdStr + notFoundErr = pure $ + Left $ "Failed to find package key for " <> T.pack pkgIdStr extractField path = do contents <- readFileUtf8 (toFilePath path) case asum (map (T.stripPrefix (field <> ": ")) (T.lines contents)) of Just result -> pure $ Right $ T.strip result Nothing -> notFoundErr - cabalVer <- view cabalVersionL - if cabalVer < mkVersion [1, 24] - then do - -- here we don't need to handle internal libs - path <- (inplaceDir ) <$> parseRelFile (pkgIdStr ++ "-inplace.conf") - logDebug $ - "Parsing config in Cabal < 1.24 location: " - <> fromString (toFilePath path) - exists <- doesFileExist path - if exists then fmap (:[]) <$> extractField path else notFoundErr - else do - -- With Cabal-1.24, it's in a different location. - logDebug $ "Scanning " <> fromString (toFilePath inplaceDir) <> " for files matching " <> fromString pkgIdStr - (_, files) <- handleIO (const $ pure ([], [])) $ listDir inplaceDir - logDebug $ displayShow files - -- From all the files obtained from the scanning process above, we - -- need to identify which are .conf files and then ensure that - -- there is at most one .conf file for each library and internal - -- library (some might be missing if that component has not been - -- built yet). We should error if there are more than one .conf - -- file for a component or if there are no .conf files at all in - -- the searched location. - let toFilename = T.pack . toFilePath . filename - -- strip known prefix and suffix from the found files to determine only the conf files - stripKnown = T.stripSuffix ".conf" <=< T.stripPrefix (T.pack (pkgIdStr ++ "-")) - stripped = mapMaybe (\file -> fmap (,file) . stripKnown . toFilename $ file) files - -- which component could have generated each of these conf files - stripHash n = let z = T.dropWhile (/= '-') n in if T.null z then "" else T.tail z - matchedComponents = map (\(n, f) -> (stripHash n, [f])) stripped - byComponents = Map.restrictKeys (Map.fromListWith (++) matchedComponents) $ Set.insert "" internalLibs - logDebug $ displayShow byComponents - if Map.null $ Map.filter (\fs -> length fs > 1) byComponents - then case concat $ Map.elems byComponents of - [] -> notFoundErr - -- for each of these files, we need to extract the requested field - paths -> do - (errors, keys) <- partitionEithers <$> traverse extractField paths - case errors of - (a:_) -> pure $ Left a -- the first error only, since they're repeated anyway - [] -> pure $ Right keys - else - pure - $ Left - $ "Multiple files matching " - <> T.pack (pkgIdStr ++ "-*.conf") - <> " found in " - <> T.pack (toFilePath inplaceDir) - <> ". Maybe try 'stack clean' on this package?" + logDebug $ + "Scanning " + <> fromString (toFilePath inplaceDir) + <> " for files matching " + <> fromString pkgIdStr + (_, files) <- handleIO (const $ pure ([], [])) $ listDir inplaceDir + logDebug $ displayShow files + -- From all the files obtained from the scanning process above, we need to + -- identify which are .conf files and then ensure that there is at most one + -- .conf file for each library and internal library (some might be missing if + -- that component has not been built yet). We should error if there are more + -- than one .conf file for a component or if there are no .conf files at all + -- in the searched location. + let toFilename = T.pack . toFilePath . filename + -- strip known prefix and suffix from the found files to determine only the conf files + stripKnown = + T.stripSuffix ".conf" <=< T.stripPrefix (T.pack (pkgIdStr ++ "-")) + stripped = + mapMaybe (\file -> fmap (,file) . stripKnown . toFilename $ file) files + -- which component could have generated each of these conf files + stripHash n = + let z = T.dropWhile (/= '-') n + in if T.null z then "" else T.tail z + matchedComponents = map (\(n, f) -> (stripHash n, [f])) stripped + byComponents = + Map.restrictKeys (Map.fromListWith (++) matchedComponents) $ Set.insert "" internalLibs + logDebug $ displayShow byComponents + if Map.null $ Map.filter (\fs -> length fs > 1) byComponents + then case concat $ Map.elems byComponents of + [] -> notFoundErr + -- for each of these files, we need to extract the requested field + paths -> do + (errors, keys) <- partitionEithers <$> traverse extractField paths + case errors of + (a:_) -> pure $ Left a -- the first error only, since they're repeated anyway + [] -> pure $ Right keys + else + pure + $ Left + $ "Multiple files matching " + <> T.pack (pkgIdStr ++ "-*.conf") + <> " found in " + <> T.pack (toFilePath inplaceDir) + <> ". Maybe try 'stack clean' on this package?" displayReportPath :: HasTerm env diff --git a/src/Stack/Setup.hs b/src/Stack/Setup.hs index b0586ada74..b0ebb21971 100644 --- a/src/Stack/Setup.hs +++ b/src/Stack/Setup.hs @@ -1028,14 +1028,14 @@ warnUnsupportedCompilerCabal cp didWarn = do let cabalVersion = cpCabalVersion cp if - | cabalVersion < mkVersion [1, 19, 2] -> do + | cabalVersion < mkVersion [1, 24, 0] -> do prettyWarnL - [ flow "Stack no longer supports Cabal versions below 1.19.2, but \ + [ flow "Stack no longer supports Cabal versions below 1.24.0.0, but \ \version" , fromString (versionString cabalVersion) , flow "was found. This invocation will most likely fail. To fix \ \this, either use an older version of Stack or a newer \ - \resolver. Acceptable resolvers: lts-3.0/nightly-2015-05-05 \ + \resolver. Acceptable resolvers: lts-7.0/nightly-2016-05-26 \ \or later." ] | cabalVersion >= mkVersion [3, 11] ->