ghc-check 0.5.0.1 → 0.5.0.2
raw patch · 5 files changed
+57/−39 lines, 5 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ GHC.Check.PackageDb: fromVersionString :: HasCallStack => String -> PackageVersion
Files
- ghc-check.cabal +8/−1
- src/GHC/Check.hs +31/−20
- src/GHC/Check/Executable.hs +1/−1
- src/GHC/Check/PackageDb.hs +11/−11
- src/GHC/Check/Util.hs +6/−6
ghc-check.cabal view
@@ -1,7 +1,7 @@ cabal-version: 1.20 build-type: Simple name: ghc-check-version: 0.5.0.1+version: 0.5.0.2 synopsis: detect mismatches between compile-time and run-time versions of the ghc api description: detect mismatches between compile-time and run-time versions of the ghc api bug-reports: https://github.com/pepeiborra/ghc-check/issues@@ -12,6 +12,11 @@ category: Development extra-source-files: README.md +flag ghc-check-use-package-abis+ description: record package abis at compile time for improved precision (requires compile-time TH)+ default: True+ manual: True+ library exposed-modules: GHC.Check, GHC.Check.Executable@@ -30,3 +35,5 @@ transformers hs-source-dirs: src default-language: Haskell2010+ if flag(ghc-check-use-package-abis)+ cpp-options: -DUSE_PACKAGE_ABIS
src/GHC/Check.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE RecordWildCards #-}@@ -26,22 +27,23 @@ import Control.Applicative (Alternative ((<|>))) import Control.Exception import Control.Monad (filterM, unless)-import Data.Function (on)-import Data.List (find, intersectBy)+import Data.List (find) import qualified Data.List.NonEmpty as NonEmpty import Data.List.NonEmpty (NonEmpty, nonEmpty) import qualified Data.Map.Strict as Map import Data.Maybe-import Data.Monoid (First (First), getFirst)-import Data.Version (Version, showVersion)-import GHC (Ghc, getSessionDynFlags, runGhc, setSessionDynFlags)+import Data.Version (Version)+import GHC (Ghc) import GHC.Check.Executable (getGhcVersion, guessExecutablePathFromLibdir)-import GHC.Check.PackageDb (PackageVersion (..), getPackageVersion, version)+import GHC.Check.PackageDb (fromVersionString, PackageVersion (..), getPackageVersion, version) import GHC.Check.Util (gcatchSafe, liftTyped) import Language.Haskell.TH (TExpQ, runIO)-import Language.Haskell.TH.Syntax (Lift (lift)) import System.Directory (doesDirectoryExist, doesFileExist) +#if USE_PACKAGE_ABIS+import GHC (getSessionDynFlags, runGhc, setSessionDynFlags)+#endif+ -- | Given a run-time libdir, checks the ghc installation and returns -- a 'Ghc' action to check the package database type GhcVersionChecker = String -> IO InstallationCheck@@ -83,11 +85,14 @@ comparePackageVersions :: PackageVersion -> PackageVersion -> PackageCheck comparePackageVersions compile run- | compile == run = VersionMatch compile- | version compile == version run =- AbiMismatch (abi compile) (abi run) (version compile)- | otherwise =+ | version compile /= version run = VersionMismatch (version compile) (version run)+ | Just abiCompile <- abi compile+ , Just abiRun <- abi run+ , abiCompile /= abiRun+ = AbiMismatch abiCompile abiRun (version compile)+ | otherwise+ = VersionMatch compile collectPackageVersions :: [String] -> Ghc [(String, PackageVersion)] collectPackageVersions =@@ -147,19 +152,19 @@ -- > case guessCompatibility result of ... makeGhcVersionChecker :: IO FilePath -> TExpQ GhcVersionChecker makeGhcVersionChecker getLibdir = do- libdir <- runIO getLibdir- libdirExists <- runIO $ doesDirectoryExist libdir+ compileTimeVersions <- runIO $ compileTimeVersions getLibdir+ [||checkGhcVersion $$(liftTyped compileTimeVersions)||]++compileTimeVersions :: IO FilePath -> IO [(String, PackageVersion)]+compileTimeVersions getLibdir = do+#if USE_PACKAGE_ABIS+ libdir <- getLibdir+ libdirExists <- doesDirectoryExist libdir unless libdirExists $ error $ "I could not find a GHC installation at " <> libdir <> ". Please do a clean rebuild and/or reinstall GHC."- compileTimeVersions <-- runIO- $ runGhcPkg libdir- $ collectPackageVersions trackedPackages- [||checkGhcVersion $$(liftTyped compileTimeVersions)||]- where- trackedPackages = ["ghc", "base"]+ runGhcPkg libdir $ collectPackageVersions ["ghc", "base"] runGhcPkg :: FilePath -> Ghc a -> IO a runGhcPkg libdir action = runGhc (Just libdir) $ do@@ -168,6 +173,12 @@ dflags <- getSessionDynFlags _ <- setSessionDynFlags dflags action+#else+ return+ [ ("ghc", fromVersionString VERSION_ghc)+ , ("base", fromVersionString VERSION_base)+ ]+#endif -- | A GHC version retrieved from the GHC installation in the given libdir ghcRunTimeVersion :: String -> IO Version
src/GHC/Check/Executable.hs view
@@ -4,7 +4,6 @@ module GHC.Check.Executable where import Data.Version-import GHC.Check.Util import System.FilePath import System.Process import Text.ParserCombinators.ReadP@@ -30,5 +29,6 @@ guessExecutablePathFromLibdir :: FilePath -> NonEmpty FilePath guessExecutablePathFromLibdir fp = NonEmpty.fromList [ fp </> "bin" </> "ghc" -- Linux+ , fp </> ".." </> "bin" </> "ghc" -- Linux (Relocatable GHC build) , fp </> ".." </> "bin" </> "ghc.exe" -- Windows ]
src/GHC/Check/PackageDb.hs view
@@ -8,40 +8,37 @@ module GHC.Check.PackageDb ( PackageVersion(abi), version, getPackageVersion,- )+ fromVersionString+ ) where import Control.Monad.Trans.Class as Monad (MonadTrans (lift))-import Data.Maybe (fromMaybe) import Data.String (IsString (fromString)) import Data.Version (Version) import GHC (pkgState, Ghc, getSessionDynFlags,- runGhc,- setSessionDynFlags, ) import GHC.Check.Util-import GHC.Exts (IsList (fromList), toList) import Maybes (MaybeT (MaybeT), runMaybeT) import Module (componentIdToInstalledUnitId) import PackageConfig (PackageName (PackageName)) import Packages- (lookupPackage, getPackageDetails, explicitPackages, lookupInstalledPackage,+ (lookupPackage, explicitPackages, lookupInstalledPackage, lookupPackageName ) import Packages (InstalledPackageInfo (..)) import Packages (PackageConfig) import Language.Haskell.TH.Syntax (Lift)-import Language.Haskell.TH (TExpQ) import Data.Foldable (find) import Packages (packageNameString) import Control.Applicative (Alternative((<|>)))+import GHC.Stack (HasCallStack) data PackageVersion = PackageVersion { myVersion :: !MyVersion,- abi :: !String+ abi :: Maybe String } deriving (Eq, Lift, Show) @@ -65,7 +62,10 @@ p <- explicit <|> notExplicit - return $ mkPackageVersion p+ return $ fromPackageConfig p -mkPackageVersion :: PackageConfig -> PackageVersion-mkPackageVersion p = PackageVersion (MyVersion $ packageVersion p) (abiHash p)+fromPackageConfig :: PackageConfig -> PackageVersion+fromPackageConfig p = PackageVersion (MyVersion $ packageVersion p) (Just $ abiHash p)++fromVersionString :: HasCallStack => String -> PackageVersion+fromVersionString v = PackageVersion (MyVersion $ read v) Nothing
src/GHC/Check/Util.hs view
@@ -4,17 +4,14 @@ {-# LANGUAGE CPP, TemplateHaskell #-} module GHC.Check.Util (MyVersion(..), liftTyped, gcatchSafe) where -import Control.Monad ((>=>)) import Control.Exception.Safe import Control.Monad.IO.Class (MonadIO(liftIO))-import Data.Maybe-import Data.Version+import Data.Version ( Version, parseVersion ) import GHC (Ghc, gcatch) import GHC.Exts (IsList (fromList), toList)-import qualified GHC.Paths-import Language.Haskell.TH+import Language.Haskell.TH ( TExpQ ) import Language.Haskell.TH.Syntax as TH-import System.Environment (lookupEnv)+import qualified Text.Read as Read -- | A wrapper around 'Version' with TH lifting newtype MyVersion = MyVersion Version@@ -25,6 +22,9 @@ liftTyped = liftMyVersion #endif lift = unTypeQ . liftMyVersion++instance Read MyVersion where+ readPrec = Read.lift $ MyVersion <$> parseVersion liftMyVersion :: MyVersion -> TExpQ MyVersion liftMyVersion ver = do