@@ -46,13 +46,23 @@ import Debug.Trace (trace)
4646import Distribution.Compiler (CompilerFlavor(..))
4747import Distribution.PackageDescription.Parsec (parseGenericPackageDescription)
4848import Distribution.Parsec.ParseResult (runParseResult)
49+import Distribution.Pretty (prettyShow)
50+import Distribution.Simple.Compiler (PackageDB (GlobalPackageDB))
51+import Distribution.Simple.Configure (configCompilerEx, getInstalledPackages)
52+import Distribution.Simple.PackageIndex (InstalledPackageIndex, lookupDependency)
53+import Distribution.Simple.Program.Db (defaultProgramDb)
4954import qualified Distribution.System as Dist
50−import Distribution.Types.BuildInfo (buildable, cppOptions, defaultExtensions, defaultLanguage, hsSourceDirs, options)
55+import Distribution.Types.BuildInfo (buildable, cppOptions, defaultExtensions, defaultLanguage, hsSourceDirs, options, targetBuildDepends)
5156import Distribution.Types.CondTree (simplifyCondTree)
57+import Distribution.Types.Dependency (Dependency (..), depPkgName)
5258import Distribution.Types.GenericPackageDescription (ConfVar (Arch, Impl, OS), condLibrary)
59+import Distribution.Types.InstalledPackageInfo (compatPackageKey)
5360import Distribution.Types.Library (libBuildInfo)
61+import Distribution.Types.PackageName (mkPackageName)
62+import Distribution.Types.VersionRange (anyVersion)
5463import Distribution.Utils.Generic (toUTF8BS, readUTF8File)
5564import qualified Distribution.Parsec.Common as Dist
65+import qualified Distribution.Verbosity as Verbosity (silent)
5666import qualified Hpack.Config as Hpack
5767import qualified Hpack.Render as Hpack
5868import qualified Hpack.Yaml as Hpack
@@ -62,12 +72,16 @@ import System.Directory
6272import System.Environment (getExecutablePath)
6373import System.FilePath
6474import qualified System.Info
75+import System.IO (hClose, hGetLine)
6576import System.IO.Temp (withSystemTempDirectory)
77+import System.Process (CreateProcess (..), StdStream (..))
6678
6779import Obelisk.App (MonadObelisk, getObelisk, runObelisk)
6880import Obelisk.CliApp (
6981 Severity (..),
82+ createProcess_,
7083 failWith,
84+ overCreateProcess,
7185 proc,
7286 putLog,
7387 readCreateProcessWithExitCode,
@@ -97,6 +111,8 @@ data CabalPackageInfo = CabalPackageInfo
97111 -- ^ List of compiler-specific options (e.g., the "ghc-options" field of the cabal file)
98112 , _cabalPackageInfo_cppOptions :: [String]
99113 -- ^ List of CPP (C Preprocessor) options (e.g. the "cpp-options" field of the cabal file)
114+ , _cabalPackageInfo_buildDepends :: [Dependency]
115+ -- ^ List of build dependencies listed in the cabal file
100116 }
101117
102118-- | 'Bool' with a better name for its purpose.
@@ -367,6 +383,7 @@ parseCabalPackage' pkg = runExceptT $ do
367383 defaultLanguage $ libBuildInfo lib
368384 , _cabalPackageInfo_compilerOptions = options $ libBuildInfo lib
369385 , _cabalPackageInfo_cppOptions = cppOptions $ libBuildInfo lib
386+ , _cabalPackageInfo_buildDepends = targetBuildDepends $ libBuildInfo lib
370387 }
371388 Right Nothing -> pure Nothing
372389 Left (_, errors) ->
@@ -464,6 +481,7 @@ getGhciSessionSettings (toList -> packageInfos) pathBase useRelativePaths = do
464481 -- all paths to 'pathBase'.
465482 selfExe <- liftIO $ canonicalizePath =<< getExecutablePath
466483 canonicalPathBase <- liftIO $ canonicalizePath pathBase
484+ installedPackageIndex <- loadPackageIndex pathBase
467485
468486 (pkgFiles, pkgSrcPaths :: [NonEmpty FilePath]) <- fmap unzip $ liftIO $ for packageInfos $ \pkg -> do
469487 canonicalSrcDirs <- traverse canonicalizePath $ (_cabalPackageInfo_packageRoot pkg </>) <$> _cabalPackageInfo_sourceDirs pkg
@@ -476,13 +494,48 @@ getGhciSessionSettings (toList -> packageInfos) pathBase useRelativePaths = do
476494 <> ["-F", "-pgmF", selfExe, "-optF", preprocessorIdentifier]
477495 <> concatMap (\p -> ["-optF", p]) pkgFiles
478496 <> [ "-i" <> intercalate ":" (concatMap toList pkgSrcPaths) ]
497+ <> concatMap (\packageId -> ["-package-id", packageId ])
498+ (packageIds installedPackageIndex)
479499 where
480500 relativeTo' = if useRelativePaths then relativeTo else const
501+ -- Package names we're building and not needed from the package DB
502+ packageNames =
503+ map (mkPackageName . T.unpack . _cabalPackageInfo_packageName)
504+ packageInfos
505+ packageIds installedPackageIndex =
506+ map (dependencyPackageId installedPackageIndex) $
507+ filter ((`notElem` packageNames) . depPkgName) $
508+ concatMap _cabalPackageInfo_buildDepends packageInfos <>
509+ [Dependency (mkPackageName "obelisk-run") anyVersion]
510+ dependencyPackageId installedPackageIndex dep =
511+ case lookupDependency installedPackageIndex dep of
512+ ((_version,installedPackageInfo:_) :_) ->
513+ compatPackageKey installedPackageInfo
514+ _ -> error $ "Couldn't resolve dependency for " <> prettyShow dep
515+
516+-- Load the package index used by the GHC in this path's nix project
517+loadPackageIndex :: (MonadObelisk m) => FilePath -> m InstalledPackageIndex
518+loadPackageIndex root = do
519+ ghcPath <- getPathInNixEnvironment "bash -c 'type -p ghc'"
520+ ghcPkgPath <- getPathInNixEnvironment "bash -c 'type -p ghc-pkg'"
521+ (compiler, _platform, programDb) <- liftIO
522+ $ configCompilerEx (Just GHC) (Just ghcPath) (Just ghcPkgPath) defaultProgramDb Verbosity.silent
523+ liftIO $ getInstalledPackages Verbosity.silent compiler [GlobalPackageDB] programDb
524+ where
525+ getPathInNixEnvironment cmd = do
526+ procSpec <- runProc <$> nixShellRunConfig root True (Just cmd)
527+ (_,Just h,_,_) <- createProcess_ "loadPackageIndex" procSpec
528+ path <- liftIO $ hGetLine h >>= canonicalizePath
529+ liftIO $ hClose h
530+ pure path
531+ runProc =
532+ overCreateProcess (\cs -> cs { std_out = CreatePipe }) . nixShellRunProc
481533
482534baseGhciOptions :: [String]
483535baseGhciOptions =
484536 [ "-ignore-dot-ghci"
485537 , "-no-user-package-db"
538+ , "-hide-all-packages"
486539 , "-package-env", "-"
487540 ]
488541