Cabal.hs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. {-# LANGUAGE OverloadedStrings, RecordWildCards #-}
  2. module Cabal (initializeGHC, getDirs, fromCabal) where
  3. import CabalApi (cabalParseFile, cabalBuildInfo, cabalDependPackages)
  4. import Control.Applicative
  5. import Control.Exception
  6. import Control.Monad
  7. import CoreMonad
  8. import Data.List
  9. import Distribution.PackageDescription (BuildInfo(..), usedExtensions)
  10. import Distribution.Text (display)
  11. import ErrMsg
  12. import GHC
  13. import GHCApi
  14. import GHCChoice
  15. import System.Directory
  16. import System.FilePath
  17. import Types
  18. ----------------------------------------------------------------
  19. importDirs :: [String]
  20. importDirs = [".","..","../..","../../..","../../../..","../../../../.."]
  21. initializeGHC :: Options -> FilePath -> [String] -> Bool -> Ghc (FilePath,LogReader)
  22. initializeGHC opt fileName ghcOptions logging = withCabal ||> withoutCabal
  23. where
  24. withoutCabal = do
  25. logReader <- initSession opt ghcOptions importDirs Nothing logging
  26. return (fileName,logReader)
  27. withCabal = do
  28. (gopts,idirs,depPkgs) <- liftIO $ fromCabal ghcOptions
  29. logReader <- initSession opt gopts idirs (Just depPkgs) logging
  30. return (fileName,logReader)
  31. fromCabal :: [String] -> IO ([String], [FilePath], [String])
  32. fromCabal ghcOptions = do
  33. (owdir,cdir,cfile) <- getDirs
  34. cabal <- cabalParseFile cfile
  35. binfo@BuildInfo{..} <- cabalBuildInfo cabal
  36. let exts = map (("-X" ++) . display) $ usedExtensions binfo
  37. lang = maybe "-XHaskell98" (("-X" ++) . display) defaultLanguage
  38. libs = map ("-l" ++) extraLibs
  39. libDirs = map ("-L" ++) extraLibDirs
  40. gopts = ghcOptions ++ exts ++ [lang] ++ libs ++ libDirs
  41. idirs = case hsSourceDirs of
  42. [] -> [cdir,owdir]
  43. dirs -> map (cdir </>) dirs ++ [owdir]
  44. depPkgs <- removeMe cfile <$> cabalDependPackages cabal
  45. return (gopts,idirs,depPkgs)
  46. removeMe :: FilePath -> [String] -> [String]
  47. removeMe cabalfile depPkgs = filter (/= me) depPkgs
  48. where
  49. me = dropExtension $ takeFileName cabalfile
  50. ----------------------------------------------------------------
  51. -- CurrentWorkingDir, CabalDir, CabalFile
  52. getDirs :: IO (FilePath,FilePath,FilePath)
  53. getDirs = do
  54. wdir <- getCurrentDirectory
  55. (cdir,cfile) <- cabalDir wdir
  56. return (wdir,cdir,cfile)
  57. -- Causes error, catched in the upper function.
  58. -- CabalDir, CabalFile
  59. cabalDir :: FilePath -> IO (FilePath,FilePath)
  60. cabalDir dir = do
  61. cnts <- (filter isCabal <$> getDirectoryContents dir)
  62. >>= filterM (\file -> doesFileExist (dir </> file))
  63. let dir' = takeDirectory dir
  64. case cnts of
  65. [] | dir' == dir -> throwIO $ userError "No cabal file"
  66. | otherwise -> cabalDir dir'
  67. cfile:_ -> return (dir,dir </> cfile)
  68. where
  69. isCabal name = ".cabal" `isSuffixOf` name && length name > 6