fix building with GHC API
This commit is contained in:
parent
2ba9828295
commit
2f5628d254
224
yesod/Devel.hs
224
yesod/Devel.hs
@ -3,6 +3,7 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
module Devel
|
module Devel
|
||||||
( devel
|
( devel
|
||||||
|
, DevelOpts(..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
|
||||||
@ -11,9 +12,17 @@ import qualified Distribution.Verbosity as D
|
|||||||
import qualified Distribution.PackageDescription.Parse as D
|
import qualified Distribution.PackageDescription.Parse as D
|
||||||
import qualified Distribution.PackageDescription as D
|
import qualified Distribution.PackageDescription as D
|
||||||
import qualified Distribution.ModuleName as D
|
import qualified Distribution.ModuleName as D
|
||||||
|
import qualified Distribution.Simple.Setup as DSS
|
||||||
import qualified Distribution.Simple.Configure as D
|
import qualified Distribution.Simple.Configure as D
|
||||||
import qualified Distribution.Simple.Program as D
|
import qualified Distribution.Simple.Program as D
|
||||||
|
import qualified Distribution.Simple.Build as D
|
||||||
|
import qualified Distribution.Simple.Register as D
|
||||||
import qualified Distribution.Compiler as D
|
import qualified Distribution.Compiler as D
|
||||||
|
-- import qualified Distribution.InstalledPackageInfo as D
|
||||||
|
import qualified Distribution.InstalledPackageInfo as IPI
|
||||||
|
import qualified Distribution.Simple.LocalBuildInfo as D
|
||||||
|
import qualified Distribution.Package as D
|
||||||
|
import qualified Distribution.Verbosity as D
|
||||||
|
|
||||||
import Control.Applicative ((<$>), (<*>))
|
import Control.Applicative ((<$>), (<*>))
|
||||||
import Control.Concurrent (forkIO, threadDelay)
|
import Control.Concurrent (forkIO, threadDelay)
|
||||||
@ -24,6 +33,7 @@ import Data.Char (isUpper, isNumber)
|
|||||||
import qualified Data.List as L
|
import qualified Data.List as L
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
|
|
||||||
import System.Directory
|
import System.Directory
|
||||||
import System.Exit (exitFailure, exitSuccess, ExitCode (..))
|
import System.Exit (exitFailure, exitSuccess, ExitCode (..))
|
||||||
@ -33,6 +43,7 @@ import System.PosixCompat.Files (modificationTime, getFileStatus)
|
|||||||
import System.Process (createProcess, proc, terminateProcess, readProcess, ProcessHandle,
|
import System.Process (createProcess, proc, terminateProcess, readProcess, ProcessHandle,
|
||||||
getProcessExitCode,waitForProcess, rawSystem, runInteractiveProcess)
|
getProcessExitCode,waitForProcess, rawSystem, runInteractiveProcess)
|
||||||
import System.IO (hClose, hIsEOF, hGetLine, stdout, stderr, hPutStrLn)
|
import System.IO (hClose, hIsEOF, hGetLine, stdout, stderr, hPutStrLn)
|
||||||
|
import System.IO.Error (isDoesNotExistError)
|
||||||
|
|
||||||
import Build (recompDeps, getDeps, isNewerThan)
|
import Build (recompDeps, getDeps, isNewerThan)
|
||||||
import GhcBuild (getBuildFlags, buildPackage)
|
import GhcBuild (getBuildFlags, buildPackage)
|
||||||
@ -49,10 +60,22 @@ writeLock = do
|
|||||||
writeFile lockFile ""
|
writeFile lockFile ""
|
||||||
|
|
||||||
removeLock :: IO ()
|
removeLock :: IO ()
|
||||||
removeLock = try_ (removeFile lockFile)
|
removeLock = removeFileIfExists lockFile
|
||||||
|
|
||||||
devel :: Bool -> Bool -> [String] -> IO ()
|
data DevelOpts = DevelOpts
|
||||||
devel isCabalDev forceCabal passThroughArgs = do
|
{ isCabalDev :: Bool
|
||||||
|
, forceCabal :: Bool
|
||||||
|
, verbose :: Bool
|
||||||
|
} deriving (Show, Eq)
|
||||||
|
|
||||||
|
cabalCommand :: DevelOpts -> FilePath
|
||||||
|
cabalCommand opts | isCabalDev opts = "cabal-dev"
|
||||||
|
| otherwise = "cabal"
|
||||||
|
|
||||||
|
defaultDevelOpts = DevelOpts False False False
|
||||||
|
|
||||||
|
devel :: DevelOpts -> [String] -> IO ()
|
||||||
|
devel opts passThroughArgs = do
|
||||||
checkDevelFile
|
checkDevelFile
|
||||||
writeLock
|
writeLock
|
||||||
|
|
||||||
@ -62,54 +85,35 @@ devel isCabalDev forceCabal passThroughArgs = do
|
|||||||
gpd <- D.readPackageDescription D.normal cabal
|
gpd <- D.readPackageDescription D.normal cabal
|
||||||
|
|
||||||
ldar <- lookupLdAr
|
ldar <- lookupLdAr
|
||||||
hsSourceDirs <- checkCabalFile gpd
|
(hsSourceDirs, lib) <- checkCabalFile gpd
|
||||||
|
|
||||||
_<- rawSystem cmd args
|
removeFileIfExists "dist/setup-config"
|
||||||
|
configure cabal gpd opts
|
||||||
mainLoop hsSourceDirs cabal ldar
|
removeFileIfExists "dist/ghcargs.txt" -- these files contain the wrong data after
|
||||||
|
removeFileIfExists "dist/arargs.txt" -- the configure step, remove them to force
|
||||||
|
removeFileIfExists "dist/ldargs.txt" -- a cabal build first
|
||||||
|
mainLoop hsSourceDirs cabal gpd lib ldar
|
||||||
|
|
||||||
_ <- getLine
|
_ <- getLine
|
||||||
writeLock
|
writeLock
|
||||||
exitSuccess
|
exitSuccess
|
||||||
where
|
where
|
||||||
cmd | isCabalDev = "cabal-dev"
|
mainLoop :: [FilePath] -> FilePath -> D.GenericPackageDescription -> D.Library -> (FilePath, FilePath) -> IO ()
|
||||||
| otherwise = "cabal"
|
mainLoop hsSourceDirs cabal gpd lib ldar = do
|
||||||
|
|
||||||
diffArgs | isCabalDev = [
|
|
||||||
"--cabal-install-arg=--with-compiler=yesod-ghc-wrapper"
|
|
||||||
, "--cabal-install-arg=--with-hc-pkg=ghc-pkg"
|
|
||||||
, "--cabal-install-arg=--with-ld=yesod-ld-wrapper"
|
|
||||||
, "--cabal-install-arg=--with-ar=yesod-ar-wrapper"
|
|
||||||
, "--cabal-install-arg=-fdevel" -- legacy
|
|
||||||
, "--cabal-install-arg=-flibrary-only"
|
|
||||||
]
|
|
||||||
| otherwise = [
|
|
||||||
"--with-compiler=yesod-ghc-wrapper"
|
|
||||||
, "--with-hc-pkg=ghc-pkg"
|
|
||||||
, "--with-ld=yesod-ld-wrapper"
|
|
||||||
, "--with-ar=yesod-ar-wrapper"
|
|
||||||
, "-fdevel" -- legacy
|
|
||||||
, "-flibrary-only"
|
|
||||||
]
|
|
||||||
args = "configure":diffArgs ++ ["--disable-library-profiling" ]
|
|
||||||
|
|
||||||
mainLoop :: [FilePath] -> FilePath -> (FilePath, FilePath) -> IO ()
|
|
||||||
mainLoop hsSourceDirs cabal ldar = do
|
|
||||||
ghcVer <- ghcVersion
|
ghcVer <- ghcVersion
|
||||||
_ <- rebuildCabal cmd
|
rebuild <- mkRebuild gpd ghcVer cabal opts ldar
|
||||||
pkgArgs <- ghcPackageArgs isCabalDev ghcVer
|
|
||||||
rebuild <- mkRebuild ghcVer cabal cmd forceCabal ldar
|
|
||||||
let devArgs = pkgArgs ++ ["devel.hs"] ++ passThroughArgs
|
|
||||||
forever $ do
|
forever $ do
|
||||||
recompDeps hsSourceDirs
|
recompDeps hsSourceDirs
|
||||||
|
|
||||||
list <- getFileList hsSourceDirs [cabal]
|
list <- getFileList hsSourceDirs [cabal]
|
||||||
success <- rebuild
|
success <- rebuild
|
||||||
|
pkgArgs <- ghcPackageArgs opts ghcVer (D.packageDescription gpd) lib
|
||||||
|
let devArgs = pkgArgs ++ ["devel.hs"] ++ passThroughArgs
|
||||||
if not success
|
if not success
|
||||||
then putStrLn "Build failure, pausing..."
|
then putStrLn "Build failure, pausing..."
|
||||||
else do
|
else do
|
||||||
removeLock
|
removeLock
|
||||||
putStrLn $ "Starting development server: runghc " ++ L.unwords devArgs
|
putStrLn $ if verbose opts then "Starting development server: runghc " ++ L.unwords devArgs
|
||||||
|
else "Starting development server..."
|
||||||
(_,_,_,ph) <- createProcess $ proc "runghc" devArgs
|
(_,_,_,ph) <- createProcess $ proc "runghc" devArgs
|
||||||
watchTid <- forkIO . try_ $ do
|
watchTid <- forkIO . try_ $ do
|
||||||
watchForChanges hsSourceDirs [cabal] list
|
watchForChanges hsSourceDirs [cabal] list
|
||||||
@ -123,34 +127,107 @@ devel isCabalDev forceCabal passThroughArgs = do
|
|||||||
Ex.throwTo watchTid (userError "process finished")
|
Ex.throwTo watchTid (userError "process finished")
|
||||||
watchForChanges hsSourceDirs [cabal] list
|
watchForChanges hsSourceDirs [cabal] list
|
||||||
|
|
||||||
mkRebuild :: String -> FilePath -> String -> Bool -> (FilePath, FilePath) -> IO (IO Bool)
|
|
||||||
mkRebuild ghcVer cabalFile cabalCmd forceCabal (ldPath, arPath)
|
{-
|
||||||
| forceCabal = return (rebuildCabal cabalCmd)
|
configure with the built-in Cabal lib for non-cabal-dev, since
|
||||||
| GHC.cProjectVersion == ghcVer = do
|
otherwise we cannot read the configuration later
|
||||||
bf <- getBuildFlags
|
|
||||||
|
cabal-dev uses the command-line tool, we can fall back to
|
||||||
|
cabal-dev buildopts if required
|
||||||
|
-}
|
||||||
|
configure :: FilePath -> D.GenericPackageDescription -> DevelOpts -> IO ()
|
||||||
|
configure cabal gpd opts
|
||||||
|
| isCabalDev opts = rawSystem (cabalCommand opts) args >> return ()
|
||||||
|
| otherwise = do
|
||||||
|
lbi <- D.configure (gpd, hookedBuildInfo) configFlags
|
||||||
|
D.writePersistBuildConfig "dist" lbi -- fixme we could keep this in memory instead of file
|
||||||
|
where
|
||||||
|
hookedBuildInfo = (Nothing, [])
|
||||||
|
configFlags | forceCabal opts = config
|
||||||
|
| otherwise = config
|
||||||
|
{ DSS.configProgramPaths =
|
||||||
|
[ ("ar", "yesod-ar-wrapper")
|
||||||
|
, ("ld", "yesod-ld-wrapper")
|
||||||
|
, ("ghc", "yesod-ghc-wrapper")
|
||||||
|
]
|
||||||
|
, DSS.configHcPkg = DSS.Flag "ghc-pkg"
|
||||||
|
}
|
||||||
|
|
||||||
|
config = (DSS.defaultConfigFlags D.defaultProgramConfiguration)
|
||||||
|
{ DSS.configConfigurationsFlags =
|
||||||
|
[ (D.FlagName "devel", True) -- legaxy
|
||||||
|
, (D.FlagName "library-only", True)
|
||||||
|
]
|
||||||
|
, DSS.configProfLib = DSS.Flag False
|
||||||
|
, DSS.configUserInstall = DSS.Flag True
|
||||||
|
}
|
||||||
|
cabalArgs
|
||||||
|
| isCabalDev opts = map ("--cabal-install-arg=" ++) args
|
||||||
|
| otherwise = args
|
||||||
|
where
|
||||||
|
args =
|
||||||
|
[ "-fdevel" -- legacy
|
||||||
|
, "-flibrary-only"
|
||||||
|
] ++ wrapperArgs
|
||||||
|
wrapperArgs
|
||||||
|
| forceCabal opts = []
|
||||||
|
| otherwise =
|
||||||
|
[ "--with-compiler=yesod-ghc-wrapper"
|
||||||
|
, "--with-hc-pkg=ghc-pkg"
|
||||||
|
, "--with-ld=yesod-ld-wrapper"
|
||||||
|
, "--with-ar=yesod-ar-wrapper"
|
||||||
|
]
|
||||||
|
args :: [String]
|
||||||
|
args = "configure":cabalArgs ++ ["--disable-library-profiling" ]
|
||||||
|
|
||||||
|
|
||||||
|
removeFileIfExists :: FilePath -> IO ()
|
||||||
|
removeFileIfExists file = removeFile file `Ex.catch` handler
|
||||||
|
where
|
||||||
|
handler :: IOError -> IO ()
|
||||||
|
handler e | isDoesNotExistError e = return ()
|
||||||
|
| otherwise = Ex.throw e
|
||||||
|
|
||||||
|
mkRebuild :: D.GenericPackageDescription -> String -> FilePath -> DevelOpts -> (FilePath, FilePath) -> IO (IO Bool)
|
||||||
|
mkRebuild gpd ghcVer cabalFile opts (ldPath, arPath)
|
||||||
|
| GHC.cProjectVersion /= ghcVer = failWith "yesod has been compiled with a different GHC version, please reinstall"
|
||||||
|
| forceCabal opts = return (rebuildCabal gpd opts)
|
||||||
|
| otherwise = do
|
||||||
return $ do
|
return $ do
|
||||||
n1 <- cabalFile `isNewerThan` "dist/ghcargs.txt"
|
n1 <- cabalFile `isNewerThan` "dist/ghcargs.txt"
|
||||||
n2 <- cabalFile `isNewerThan` "dist/arargs.txt"
|
n2 <- cabalFile `isNewerThan` "dist/arargs.txt"
|
||||||
n3 <- cabalFile `isNewerThan` "dist/ldargs.txt"
|
n3 <- cabalFile `isNewerThan` "dist/ldargs.txt"
|
||||||
if n1 || n2 || n3
|
if n1 || n2 || n3
|
||||||
then rebuildCabal cabalCmd
|
then rebuildCabal gpd opts
|
||||||
else rebuildGhc bf ldPath arPath
|
else do
|
||||||
| otherwise = return $ do
|
bf <- getBuildFlags
|
||||||
putStrLn "WARNING: yesod is compiled with a different ghc version, falling back to cabal"
|
rebuildGhc bf ldPath arPath
|
||||||
rebuildCabal cabalCmd
|
|
||||||
|
|
||||||
rebuildGhc :: [Located String] -> FilePath -> FilePath -> IO Bool
|
rebuildGhc :: [Located String] -> FilePath -> FilePath -> IO Bool
|
||||||
rebuildGhc bf ld ar = do
|
rebuildGhc bf ld ar = do
|
||||||
putStrLn "Rebuilding application... (GHC API)"
|
putStrLn "Rebuilding application... (GHC API)"
|
||||||
buildPackage bf ld ar
|
buildPackage bf ld ar
|
||||||
|
|
||||||
rebuildCabal :: String -> IO Bool
|
rebuildCabal :: D.GenericPackageDescription -> DevelOpts -> IO Bool
|
||||||
rebuildCabal cmd = do
|
rebuildCabal gpd opts
|
||||||
putStrLn $ "Rebuilding application... (" ++ cmd ++ ")"
|
| isCabalDev opts = do
|
||||||
exit <- rawSystemFilter cmd ["build"]
|
let cmd = cabalCommand opts
|
||||||
return $ case exit of
|
putStrLn $ "Rebuilding application... (" ++ cmd ++ ")"
|
||||||
|
exit <- (if verbose opts then rawSystem else rawSystemFilter) cmd ["build"]
|
||||||
|
return $ case exit of
|
||||||
ExitSuccess -> True
|
ExitSuccess -> True
|
||||||
_ -> False
|
_ -> False
|
||||||
|
| otherwise = do
|
||||||
|
putStrLn $ "Rebuilding application... (Cabal library)"
|
||||||
|
lbi <- getPersistBuildConfig "dist" -- fixme we could cache this from the configure step
|
||||||
|
let buildFlags | verbose opts = DSS.defaultBuildFlags
|
||||||
|
| otherwise = DSS.defaultBuildFlags { DSS.buildVerbosity = DSS.Flag D.silent }
|
||||||
|
tryBool $ D.build (D.localPkgDescr lbi) lbi buildFlags []
|
||||||
|
|
||||||
|
tryBool a = (a >> return True) `Ex.catch` \(e::Ex.SomeException) -> do
|
||||||
|
putStrLn $ "Exception: " ++ show e
|
||||||
|
return False
|
||||||
|
|
||||||
try_ :: forall a. IO a -> IO ()
|
try_ :: forall a. IO a -> IO ()
|
||||||
try_ x = (Ex.try x :: IO (Either Ex.SomeException a)) >> return ()
|
try_ x = (Ex.try x :: IO (Either Ex.SomeException a)) >> return ()
|
||||||
@ -179,7 +256,7 @@ checkDevelFile = do
|
|||||||
e <- doesFileExist "devel.hs"
|
e <- doesFileExist "devel.hs"
|
||||||
unless e $ failWith "file devel.hs not found"
|
unless e $ failWith "file devel.hs not found"
|
||||||
|
|
||||||
checkCabalFile :: D.GenericPackageDescription -> IO [FilePath]
|
checkCabalFile :: D.GenericPackageDescription -> IO ([FilePath], D.Library)
|
||||||
checkCabalFile gpd = case D.condLibrary gpd of
|
checkCabalFile gpd = case D.condLibrary gpd of
|
||||||
Nothing -> failWith "incorrect cabal file, no library"
|
Nothing -> failWith "incorrect cabal file, no library"
|
||||||
Just ct ->
|
Just ct ->
|
||||||
@ -195,7 +272,7 @@ checkCabalFile gpd = case D.condLibrary gpd of
|
|||||||
mapM_ putStrLn unlisted
|
mapM_ putStrLn unlisted
|
||||||
when (D.fromString "Application" `notElem` D.exposedModules dLib) $
|
when (D.fromString "Application" `notElem` D.exposedModules dLib) $
|
||||||
putStrLn "WARNING: no exposed module Application"
|
putStrLn "WARNING: no exposed module Application"
|
||||||
return hsSourceDirs
|
return (hsSourceDirs, dLib)
|
||||||
|
|
||||||
failWith :: String -> IO a
|
failWith :: String -> IO a
|
||||||
failWith msg = do
|
failWith msg = do
|
||||||
@ -223,22 +300,33 @@ ghcVersion = fmap getNumber $ readProcess "runghc" ["--numeric-version", "0"] []
|
|||||||
where
|
where
|
||||||
getNumber = filter (\x -> isNumber x || x == '.')
|
getNumber = filter (\x -> isNumber x || x == '.')
|
||||||
|
|
||||||
ghcPackageArgs :: Bool -> String -> IO [String]
|
ghcPackageArgs :: DevelOpts -> String -> D.PackageDescription -> D.Library -> IO [String]
|
||||||
ghcPackageArgs isCabalDev ghcVer
|
ghcPackageArgs opts ghcVer cabal lib = do
|
||||||
| isCabalDev = do
|
lbi <- getPersistBuildConfig "dist"
|
||||||
r <- readProcess "cabal-dev" ["buildopts"] []
|
cbi <- fromMaybeErr errCbi (D.libraryConfig lbi)
|
||||||
let opts = L.lines r
|
if isCabalDev opts
|
||||||
return $ "-hide-all-packages" : "-no-user-package-conf" : inplacePkg : cabaldevConf : pkgid opts : depPkgIds opts
|
then return ("-hide-all-packages" : "-no-user-package-conf" : inplaceConf : selfPkgArg lbi : cabalDevConf : depArgs lbi cbi)
|
||||||
| otherwise = return [inplacePkg]
|
else return ("-hide-all-packages" : inplaceConf : selfPkgArg lbi : depArgs lbi cbi)
|
||||||
where
|
where
|
||||||
pkgid opts = let (_,p) = head (selectOpts ["-package-name"] opts) in "-package-id" ++ p ++ "-inplace"
|
selfPkgArg lbi = pkgArg . D.inplacePackageId . D.package . D.localPkgDescr $ lbi
|
||||||
depPkgIds opts = map (uncurry (++)) (selectOpts ["-package-id"] opts)
|
pkgArg (D.InstalledPackageId id) = "-package-id" ++ id
|
||||||
inplacePkg = "-package-confdist/package.conf.inplace"
|
depArgs lbi cbi = map pkgArg (deps lbi cbi)
|
||||||
cabaldevConf = "-package-confcabal-dev/packages-" ++ ghcVer ++ ".conf"
|
deps lbi cbi = let pkgInfo = D.inplaceInstalledPackageInfo "." "dist" cabal lib lbi cbi
|
||||||
selectOpts opts (x1:x2:xs)
|
in IPI.depends $ pkgInfo
|
||||||
| x1 `elem` opts = (x1,x2):selectOpts opts xs
|
errCbi = "No library ComponentBuildInfo"
|
||||||
| otherwise = selectOpts opts (x2:xs)
|
cabalDevConf = "-package-confcabal-dev/packages-" ++ ghcVer ++ ".conf"
|
||||||
selectOpts _ _ = []
|
inplaceConf = "-package-confdist/package.conf.inplace"
|
||||||
|
|
||||||
|
getPersistBuildConfig :: FilePath ->IO D.LocalBuildInfo
|
||||||
|
getPersistBuildConfig path = fromMaybeErr errLbi =<< D.maybeGetPersistBuildConfig path
|
||||||
|
where
|
||||||
|
errLbi = "Could not read BuildInfo file: " ++ D.localBuildInfoFile "dist" ++
|
||||||
|
"\nMake sure that cabal-install has been compiled with the same GHC version as yesod."
|
||||||
|
|
||||||
|
|
||||||
|
fromMaybeErr :: String -> Maybe b -> IO b
|
||||||
|
fromMaybeErr err Nothing = failWith err
|
||||||
|
fromMaybeErr _ (Just x) = return x
|
||||||
|
|
||||||
lookupDevelLib :: D.CondTree D.ConfVar c a -> Maybe a
|
lookupDevelLib :: D.CondTree D.ConfVar c a -> Maybe a
|
||||||
lookupDevelLib ct | found = Just (D.condTreeData ct)
|
lookupDevelLib ct | found = Just (D.condTreeData ct)
|
||||||
|
|||||||
@ -19,6 +19,7 @@ module GhcBuild (getBuildFlags, buildPackage) where
|
|||||||
import qualified Control.Exception as Ex
|
import qualified Control.Exception as Ex
|
||||||
import System.Process (rawSystem)
|
import System.Process (rawSystem)
|
||||||
import Control.Monad (when)
|
import Control.Monad (when)
|
||||||
|
import Data.IORef
|
||||||
|
|
||||||
import qualified GHC
|
import qualified GHC
|
||||||
import DriverPhases ( Phase(..), isSourceFilename, anyHsc, startPhase, isHaskellSrcFilename )
|
import DriverPhases ( Phase(..), isSourceFilename, anyHsc, startPhase, isHaskellSrcFilename )
|
||||||
@ -37,7 +38,15 @@ import Data.Maybe (fromMaybe)
|
|||||||
import Panic (panic, ghcError)
|
import Panic (panic, ghcError)
|
||||||
import Data.List (partition, isPrefixOf)
|
import Data.List (partition, isPrefixOf)
|
||||||
import qualified DynFlags
|
import qualified DynFlags
|
||||||
|
import qualified StaticFlags
|
||||||
|
|
||||||
|
{-
|
||||||
|
This contains a huge hack:
|
||||||
|
GHC only accepts setting static flags once per process, however it has no way to
|
||||||
|
get the remaining options from the command line, without setting the static flags.
|
||||||
|
This code overwrites the IORef to disable the check. This will likely cause
|
||||||
|
problems if the flags are modified, but fortunately that's relatively uncommon.
|
||||||
|
-}
|
||||||
getBuildFlags :: IO [Located String]
|
getBuildFlags :: IO [Located String]
|
||||||
getBuildFlags = do
|
getBuildFlags = do
|
||||||
argv0 <- fmap read $ readFile "dist/ghcargs.txt" -- generated by yesod-ghc-wrapper
|
argv0 <- fmap read $ readFile "dist/ghcargs.txt" -- generated by yesod-ghc-wrapper
|
||||||
@ -45,6 +54,7 @@ getBuildFlags = do
|
|||||||
mbMinusB | null minusB_args = Nothing
|
mbMinusB | null minusB_args = Nothing
|
||||||
| otherwise = Just (drop 2 (last minusB_args))
|
| otherwise = Just (drop 2 (last minusB_args))
|
||||||
let argv1' = map (mkGeneralLocated "on the commandline") argv1
|
let argv1' = map (mkGeneralLocated "on the commandline") argv1
|
||||||
|
writeIORef StaticFlags.v_opt_C_ready False -- the huge hack
|
||||||
(argv2, staticFlagWarnings) <- GHC.parseStaticFlags argv1'
|
(argv2, staticFlagWarnings) <- GHC.parseStaticFlags argv1'
|
||||||
return argv2
|
return argv2
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@ module Types where
|
|||||||
|
|
||||||
import Options
|
import Options
|
||||||
|
|
||||||
|
|
||||||
mkOptCabalDev name = option name (\o -> o
|
mkOptCabalDev name = option name (\o -> o
|
||||||
{ optionLongFlags = ["dev", "use-cabal-dev"]
|
{ optionLongFlags = ["dev", "use-cabal-dev"]
|
||||||
, optionShortFlags = ['d']
|
, optionShortFlags = ['d']
|
||||||
@ -21,4 +20,19 @@ mkOptNoApi name = option name (\o -> o
|
|||||||
, optionDescription = "do not use the GHC API to build, use `cabal build' instead"
|
, optionDescription = "do not use the GHC API to build, use `cabal build' instead"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
mkOptApi name = option name (\o -> o
|
||||||
|
{ optionLongFlags = ["ghc-api"]
|
||||||
|
, optionShortFlags = ['a']
|
||||||
|
, optionType = optionTypeBool
|
||||||
|
, optionDefault = "false"
|
||||||
|
, optionDescription = "use the GHC API to build (faster, but experimental)"
|
||||||
|
})
|
||||||
|
|
||||||
|
mkOptVerbose name = option name (\o -> o
|
||||||
|
{ optionLongFlags = ["verbose"]
|
||||||
|
, optionShortFlags = ['v']
|
||||||
|
, optionType = optionTypeBool
|
||||||
|
, optionDefault = "false"
|
||||||
|
, optionDescription = "more verbose output"
|
||||||
|
})
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import Options
|
|||||||
import Types
|
import Types
|
||||||
|
|
||||||
import Build (touch)
|
import Build (touch)
|
||||||
import Devel (devel)
|
import Devel (devel, DevelOpts(..))
|
||||||
import System.IO (stdout, stderr, hPutStr, hPutStrLn)
|
import System.IO (stdout, stderr, hPutStr, hPutStrLn)
|
||||||
import System.Exit (exitSuccess, exitFailure)
|
import System.Exit (exitSuccess, exitFailure)
|
||||||
import Control.Monad.IO.Class (MonadIO, liftIO)
|
import Control.Monad.IO.Class (MonadIO, liftIO)
|
||||||
@ -18,10 +18,12 @@ import Control.Monad.IO.Class (MonadIO, liftIO)
|
|||||||
defineOptions "NoOptions" (return ())
|
defineOptions "NoOptions" (return ())
|
||||||
|
|
||||||
defineOptions "DevelOptions" $ do
|
defineOptions "DevelOptions" $ do
|
||||||
mkOptNoApi "develOptNoApi"
|
mkOptApi "develOptApi"
|
||||||
|
-- mkOptNoApi "develOptNoApi" -- use this later when flag is enabled by default
|
||||||
|
|
||||||
defineOptions "MainOptions" $ do
|
defineOptions "MainOptions" $ do
|
||||||
mkOptCabalDev "optCabalDev"
|
mkOptCabalDev "optCabalDev"
|
||||||
|
mkOptVerbose "optVerbose"
|
||||||
|
|
||||||
type InitOptions = NoOptions
|
type InitOptions = NoOptions
|
||||||
type ConfigureOptions = NoOptions
|
type ConfigureOptions = NoOptions
|
||||||
@ -50,10 +52,10 @@ cmdInit :: MainOptions -> InitOptions -> [String] -> IO ()
|
|||||||
cmdInit _ _ _ = scaffold
|
cmdInit _ _ _ = scaffold
|
||||||
|
|
||||||
cmdConfigure :: MainOptions -> ConfigureOptions -> [String] -> IO ()
|
cmdConfigure :: MainOptions -> ConfigureOptions -> [String] -> IO ()
|
||||||
cmdConfigure mopt opts args = exitWith =<< rawSystem (cabalCommand mopt) ("configure":args)
|
cmdConfigure mopt _ args = exitWith =<< rawSystem (cabalCommand mopt) ("configure":args)
|
||||||
|
|
||||||
cmdBuild :: MainOptions -> BuildOptions -> [String] -> IO ()
|
cmdBuild :: MainOptions -> BuildOptions -> [String] -> IO ()
|
||||||
cmdBuild mopt opts args = do
|
cmdBuild mopt _ args = do
|
||||||
touch
|
touch
|
||||||
exitWith =<< rawSystem (cabalCommand mopt) ("build":args)
|
exitWith =<< rawSystem (cabalCommand mopt) ("build":args)
|
||||||
|
|
||||||
@ -61,9 +63,11 @@ cmdTouch :: MainOptions -> TouchOptions -> [String] -> IO ()
|
|||||||
cmdTouch _ _ _ = touch
|
cmdTouch _ _ _ = touch
|
||||||
|
|
||||||
cmdDevel :: MainOptions -> DevelOptions -> [String] -> IO ()
|
cmdDevel :: MainOptions -> DevelOptions -> [String] -> IO ()
|
||||||
cmdDevel mopt opts args = devel (optCabalDev mopt) forceCabal args
|
cmdDevel mopt opts args = devel dopts args
|
||||||
where
|
where
|
||||||
forceCabal = develOptNoApi opts
|
dopts = DevelOpts (optCabalDev mopt) forceCabal (optVerbose mopt)
|
||||||
|
forceCabal = not (develOptApi opts)
|
||||||
|
-- forceCabal = develOptNoApi opts
|
||||||
|
|
||||||
cmdVersion :: MainOptions -> VersionOptions -> [String] -> IO ()
|
cmdVersion :: MainOptions -> VersionOptions -> [String] -> IO ()
|
||||||
cmdVersion _ _ _ = putStrLn $ "yesod-core version: " ++ yesodVersion
|
cmdVersion _ _ _ = putStrLn $ "yesod-core version: " ++ yesodVersion
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user