{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} module GHC.Check.Internal 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 import GHC.Exts (IsList (fromList), toList) import qualified GHC.Paths import Language.Haskell.TH import Language.Haskell.TH.Syntax as TH (TExp(TExp), lift) import Maybes (MaybeT (MaybeT), runMaybeT) import Module (componentIdToInstalledUnitId) import PackageConfig (PackageName (PackageName)) import Packages (lookupInstalledPackage, lookupPackageName) import Packages (InstalledPackageInfo (packageVersion)) import System.Environment (lookupEnv) -- | Look up the GHC lib dir in the NIX environment, then in the 'GHC.Paths' guessLibdir :: IO FilePath guessLibdir = fromMaybe GHC.Paths.libdir <$> lookupEnv "NIX_GHC_LIBDIR" -- | @getPackageVersion p@ returns the version of package @p@ in -- the package database getPackageVersion :: String -> Ghc (Maybe Version) getPackageVersion packageName = runMaybeT $ do dflags <- Monad.lift getSessionDynFlags component <- MaybeT $ return $ lookupPackageName dflags $ PackageName $ fromString packageName p <- MaybeT $ return $ lookupInstalledPackage dflags (componentIdToInstalledUnitId component) return $ packageVersion p -- | Returns the version of the @ghc@ package in the environment package database getGhcVersion :: Ghc (Maybe Version) getGhcVersion = getPackageVersion "ghc" -- | @getPackageVersionIO ghc-libdir p@ returns the version of package @p@ -- in the default package database getPackageVersionIO :: FilePath -> String -> IO Version getPackageVersionIO libdir package = runGhc (Just libdir) $ do -- initialize the Ghc session -- there's probably a beteter way to do this. dflags <- getSessionDynFlags _ <- setSessionDynFlags dflags ver <- getPackageVersion package case ver of Just v -> return v Nothing -> error $ "Cannot find " <> package <> " in the package database at " <> libdir -- | @compileTimeVersion get-libdir p@ returns the version of package @p@ in -- the compile-time package database. compileTimeVersion :: IO FilePath -> String -> TExpQ Version compileTimeVersion getLibdir package = do ver <- runIO $ do libdir <- getLibdir v <- getPackageVersionIO libdir package return (toList v) verLifted <- TH.lift (toList ver) [|| fromList $$(pure $ TExp verLifted) ||]