{-# LANGUAGE CPP, OverloadedStrings, DataKinds #-}
module Distribution.Simple.UUAGC.UUAGC(uuagcUserHook,
uuagcUserHook',
uuagc,
uuagcLibUserHook,
uuagcFromString
) where
import Debug.Trace
import Distribution.Simple
import Distribution.Simple.PreProcess
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Utils
import Distribution.Simple.Setup
import Distribution.PackageDescription hiding (Flag)
import Distribution.Simple.UUAGC.AbsSyn( AGFileOption(..)
, AGFileOptions
, AGOptionsClass(..)
, lookupFileOptions
, fileClasses
)
import Distribution.Simple.UUAGC.Parser
import Options hiding (verbose)
import Distribution.Verbosity
import System.Process( readProcessWithExitCode )
import System.Directory(getModificationTime
,doesFileExist
,removeFile)
import System.FilePath(pathSeparators,
(</>),
takeFileName,
normalise,
joinPath,
dropFileName,
addExtension,
dropExtension,
replaceExtension,
splitDirectories)
import System.Exit (ExitCode(..))
import System.IO( openFile, IOMode(..),
hFileSize,
hSetFileSize,
hClose,
hGetContents,
hFlush,
Handle(..), stderr, hPutStr, hPutStrLn)
import System.Exit(exitFailure)
import Control.Exception (throwIO)
import Control.Monad (liftM, when, guard, forM_, forM)
import Control.Arrow ((&&&), second)
import Data.Maybe (maybeToList)
import Data.Either (partitionEithers)
import Data.List (nub,intersperse)
import Data.Map (Map)
import qualified Data.Map as Map
#if MIN_VERSION_Cabal(3,14,0)
import Distribution.Utils.Path (getSymbolicPath, Pkg, Source, SymbolicPath, FileOrDir (Dir), interpretSymbolicPathCWD)
#elif MIN_VERSION_Cabal(3,6,0)
import Distribution.Utils.Path (getSymbolicPath, PackageDir, SourceDir, SymbolicPath)
#endif
{-# DEPRECATED uuagcUserHook, uuagcUserHook', uuagc "Use uuagcLibUserHook instead" #-}
uuagcn :: [Char]
uuagcn = [Char]
"uuagc"
defUUAGCOptions :: String
defUUAGCOptions :: [Char]
defUUAGCOptions = [Char]
"uuagc_options"
agClassesFile :: String
agClassesFile :: [Char]
agClassesFile = [Char]
"ag_file_options"
agModule :: String
agModule :: [Char]
agModule = [Char]
"x-agmodule"
agClass :: String
agClass :: [Char]
agClass = [Char]
"x-agclass"
uuagcUserHook :: UserHooks
uuagcUserHook :: UserHooks
uuagcUserHook = [Char] -> UserHooks
uuagcUserHook' [Char]
uuagcn
uuagcUserHook' :: String -> UserHooks
uuagcUserHook' :: [Char] -> UserHooks
uuagcUserHook' [Char]
uuagcPath = ([[Char]] -> [Char] -> IO (ExitCode, [[Char]])) -> UserHooks
uuagcLibUserHook ([Char] -> [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
uuagcFromString [Char]
uuagcPath)
uuagcFromString :: String -> [String] -> FilePath -> IO (ExitCode, [FilePath])
uuagcFromString :: [Char] -> [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
uuagcFromString [Char]
uuagcPath [[Char]]
args [Char]
file = do
(ec,out,err) <- [Char] -> [[Char]] -> [Char] -> IO (ExitCode, [Char], [Char])
readProcessWithExitCode [Char]
uuagcPath ([[Char]]
args [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]
file]) [Char]
""
case ec of
ExitCode
ExitSuccess ->
do Handle -> [Char] -> IO ()
hPutStr Handle
stderr [Char]
err
(ExitCode, [[Char]]) -> IO (ExitCode, [[Char]])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ExitCode
ExitSuccess, [Char] -> [[Char]]
words [Char]
out)
(ExitFailure Int
exc) ->
do Handle -> [Char] -> IO ()
hPutStrLn Handle
stderr ([Char]
uuagcPath [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
exc)
Handle -> [Char] -> IO ()
hPutStr Handle
stderr [Char]
out
Handle -> [Char] -> IO ()
hPutStr Handle
stderr [Char]
err
(ExitCode, [[Char]]) -> IO (ExitCode, [[Char]])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> ExitCode
ExitFailure Int
exc, [])
uuagcLibUserHook :: ([String] -> FilePath -> IO (ExitCode, [FilePath])) -> UserHooks
uuagcLibUserHook :: ([[Char]] -> [Char] -> IO (ExitCode, [[Char]])) -> UserHooks
uuagcLibUserHook [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
uuagc = UserHooks
hooks where
hooks :: UserHooks
hooks = UserHooks
simpleUserHooks { hookedPreProcessors = ("ag", ag):("lag",ag):knownSuffixHandlers
, buildHook = uuagcBuildHook uuagc
}
ag :: BuildInfo
-> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
ag = ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
-> BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
uuagc' [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
uuagc
originalPreBuild :: [[Char]] -> BuildFlags -> IO HookedBuildInfo
originalPreBuild = UserHooks -> [[Char]] -> BuildFlags -> IO HookedBuildInfo
preBuild UserHooks
simpleUserHooks
originalBuildHook :: PackageDescription
-> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()
originalBuildHook = UserHooks
-> PackageDescription
-> LocalBuildInfo
-> UserHooks
-> BuildFlags
-> IO ()
buildHook UserHooks
simpleUserHooks
putErrorInfo :: Handle -> IO ()
putErrorInfo :: Handle -> IO ()
putErrorInfo Handle
h = Handle -> IO [Char]
hGetContents Handle
h IO [Char] -> ([Char] -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Handle -> [Char] -> IO ()
hPutStr Handle
stderr
updateAGFile :: ([String] -> FilePath -> IO (ExitCode, [FilePath]))
-> Map FilePath (Options, Maybe (FilePath, [String]))
-> (FilePath, (Options, Maybe (FilePath, [String])))
-> IO ()
updateAGFile :: ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
-> Map [Char] (Options, Maybe ([Char], [[Char]]))
-> ([Char], (Options, Maybe ([Char], [[Char]])))
-> IO ()
updateAGFile [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
_ Map [Char] (Options, Maybe ([Char], [[Char]]))
_ ([Char]
_,(Options
_,Maybe ([Char], [[Char]])
Nothing)) = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
updateAGFile [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
uuagc Map [Char] (Options, Maybe ([Char], [[Char]]))
newOptions ([Char]
file,(Options
opts,Just ([Char]
gen,[[Char]]
sp))) = do
hasGen <- [Char] -> IO Bool
doesFileExist [Char]
gen
when hasGen $ do
(ec, files) <- uuagc (optionsToString $ opts { genFileDeps = True, searchPath = sp }) file
case ec of
ExitCode
ExitSuccess -> do
let newOpts :: Options
newOpts :: Options
newOpts = Options
-> ((Options, Maybe ([Char], [[Char]])) -> Options)
-> Maybe (Options, Maybe ([Char], [[Char]]))
-> Options
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Options
noOptions (Options, Maybe ([Char], [[Char]])) -> Options
forall a b. (a, b) -> a
fst (Maybe (Options, Maybe ([Char], [[Char]])) -> Options)
-> Maybe (Options, Maybe ([Char], [[Char]])) -> Options
forall a b. (a -> b) -> a -> b
$ [Char]
-> Map [Char] (Options, Maybe ([Char], [[Char]]))
-> Maybe (Options, Maybe ([Char], [[Char]]))
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup [Char]
file Map [Char] (Options, Maybe ([Char], [[Char]]))
newOptions
optRebuild :: Bool
optRebuild = Options -> [[Char]]
optionsToString Options
newOpts [[Char]] -> [[Char]] -> Bool
forall a. Eq a => a -> a -> Bool
/= Options -> [[Char]]
optionsToString Options
opts
modRebuild <-
if [[Char]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
files
then Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
else do
flsmt <- ([Char] -> IO UTCTime) -> [[Char]] -> IO [UTCTime]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM [Char] -> IO UTCTime
getModificationTime [[Char]]
files
let maxModified = [UTCTime] -> UTCTime
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [UTCTime]
flsmt
fmt <- getModificationTime gen
return $ maxModified > fmt
when (optRebuild || modRebuild) $ removeFile gen
ex :: ExitCode
ex@(ExitFailure Int
_) -> ExitCode -> IO ()
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO ExitCode
ex
getAGFileOptions :: [(String, String)] -> IO AGFileOptions
getAGFileOptions :: [([Char], [Char])] -> IO AGFileOptions
getAGFileOptions [([Char], [Char])]
extra = do
cabalOpts <- (([Char], [Char]) -> IO AGFileOption)
-> [([Char], [Char])] -> IO AGFileOptions
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM ([Char] -> IO AGFileOption
parseOptionAG ([Char] -> IO AGFileOption)
-> (([Char], [Char]) -> [Char])
-> ([Char], [Char])
-> IO AGFileOption
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [Char]) -> [Char]
forall a b. (a, b) -> b
snd) ([([Char], [Char])] -> IO AGFileOptions)
-> [([Char], [Char])] -> IO AGFileOptions
forall a b. (a -> b) -> a -> b
$ (([Char], [Char]) -> Bool)
-> [([Char], [Char])] -> [([Char], [Char])]
forall a. (a -> Bool) -> [a] -> [a]
filter (([Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
agModule) ([Char] -> Bool)
-> (([Char], [Char]) -> [Char]) -> ([Char], [Char]) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [Char]) -> [Char]
forall a b. (a, b) -> a
fst) [([Char], [Char])]
extra
usesOptionsFile <- doesFileExist defUUAGCOptions
if usesOptionsFile
then do r <- parserAG' defUUAGCOptions
case r of
Left ParserError
e -> [Char] -> IO AGFileOptions
forall a. [Char] -> IO a
dieNoVerbosity (ParserError -> [Char]
forall a. Show a => a -> [Char]
show ParserError
e)
Right AGFileOptions
a -> AGFileOptions -> IO AGFileOptions
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (AGFileOptions -> IO AGFileOptions)
-> AGFileOptions -> IO AGFileOptions
forall a b. (a -> b) -> a -> b
$ AGFileOptions
cabalOpts AGFileOptions -> AGFileOptions -> AGFileOptions
forall a. [a] -> [a] -> [a]
++ AGFileOptions
a
else return cabalOpts
getAGClasses :: [(String, String)] -> IO [AGOptionsClass]
getAGClasses :: [([Char], [Char])] -> IO [AGOptionsClass]
getAGClasses = (([Char], [Char]) -> IO AGOptionsClass)
-> [([Char], [Char])] -> IO [AGOptionsClass]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM ([Char] -> IO AGOptionsClass
parseClassAG ([Char] -> IO AGOptionsClass)
-> (([Char], [Char]) -> [Char])
-> ([Char], [Char])
-> IO AGOptionsClass
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [Char]) -> [Char]
forall a b. (a, b) -> b
snd) ([([Char], [Char])] -> IO [AGOptionsClass])
-> ([([Char], [Char])] -> [([Char], [Char])])
-> [([Char], [Char])]
-> IO [AGOptionsClass]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Char], [Char]) -> Bool)
-> [([Char], [Char])] -> [([Char], [Char])]
forall a. (a -> Bool) -> [a] -> [a]
filter (([Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
agClass) ([Char] -> Bool)
-> (([Char], [Char]) -> [Char]) -> ([Char], [Char]) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [Char]) -> [Char]
forall a b. (a, b) -> a
fst)
writeFileOptions :: FilePath -> Map FilePath (Options, Maybe (FilePath,[String])) -> IO ()
writeFileOptions :: [Char] -> Map [Char] (Options, Maybe ([Char], [[Char]])) -> IO ()
writeFileOptions [Char]
classesPath Map [Char] (Options, Maybe ([Char], [[Char]]))
opts = do
hClasses <- [Char] -> IOMode -> IO Handle
openFile [Char]
classesPath IOMode
WriteMode
hPutStr hClasses $ show $ Map.map (\(Options
opt,Maybe ([Char], [[Char]])
gen) -> (Options -> [[Char]]
optionsToString Options
opt, Maybe ([Char], [[Char]])
gen)) opts
hFlush hClasses
hClose hClasses
readFileOptions :: FilePath -> IO (Map FilePath (Options, Maybe (FilePath,[String])))
readFileOptions :: [Char] -> IO (Map [Char] (Options, Maybe ([Char], [[Char]])))
readFileOptions [Char]
classesPath = do
isFile <- [Char] -> IO Bool
doesFileExist [Char]
classesPath
if isFile
then do hClasses <- openFile classesPath ReadMode
sClasses <- hGetContents hClasses
classes <- readIO sClasses :: IO (Map FilePath ([String], Maybe (FilePath,[String])))
hClose hClasses
return $ Map.map (\([[Char]]
opt,Maybe ([Char], [[Char]])
gen) -> let (Options
opt',[[Char]]
_,[[Char]]
_) = [[Char]] -> (Options, [[Char]], [[Char]])
getOptions [[Char]]
opt in (Options
opt', Maybe ([Char], [[Char]])
gen)) classes
else return Map.empty
getOptionsFromClass :: [(String, Options)] -> AGFileOption -> ([String], Options)
getOptionsFromClass :: [([Char], Options)] -> AGFileOption -> ([[Char]], Options)
getOptionsFromClass [([Char], Options)]
classes AGFileOption
fOpt =
([Options] -> Options)
-> ([[Char]], [Options]) -> ([[Char]], Options)
forall b c d. (b -> c) -> (d, b) -> (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second ((Options -> Options -> Options) -> Options -> [Options] -> Options
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Options -> Options -> Options
combineOptions (AGFileOption -> Options
opts AGFileOption
fOpt))
(([[Char]], [Options]) -> ([[Char]], Options))
-> ([Either [Char] Options] -> ([[Char]], [Options]))
-> [Either [Char] Options]
-> ([[Char]], Options)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Either [Char] Options] -> ([[Char]], [Options])
forall a b. [Either a b] -> ([a], [b])
partitionEithers ([Either [Char] Options] -> ([[Char]], Options))
-> [Either [Char] Options] -> ([[Char]], Options)
forall a b. (a -> b) -> a -> b
$ do
fClass <- AGFileOption -> [[Char]]
fileClasses AGFileOption
fOpt
case fClass `lookup` classes of
Just Options
x -> Either [Char] Options -> [Either [Char] Options]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Either [Char] Options -> [Either [Char] Options])
-> Either [Char] Options -> [Either [Char] Options]
forall a b. (a -> b) -> a -> b
$ Options -> Either [Char] Options
forall a b. b -> Either a b
Right Options
x
Maybe Options
Nothing -> Either [Char] Options -> [Either [Char] Options]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Either [Char] Options -> [Either [Char] Options])
-> Either [Char] Options -> [Either [Char] Options]
forall a b. (a -> b) -> a -> b
$ [Char] -> Either [Char] Options
forall a b. a -> Either a b
Left ([Char] -> Either [Char] Options)
-> [Char] -> Either [Char] Options
forall a b. (a -> b) -> a -> b
$ [Char]
"Warning: The class "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
forall a. Show a => a -> [Char]
show [Char]
fClass
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" is not defined."
#if MIN_VERSION_Cabal(3,14,0)
buildDir' :: LocalBuildInfo -> FilePath
buildDir' = interpretSymbolicPathCWD . buildDir
#else
buildDir' :: LocalBuildInfo -> [Char]
buildDir' = LocalBuildInfo -> [Char]
buildDir
#endif
uuagcBuildHook
:: ([String] -> FilePath -> IO (ExitCode, [FilePath]))
-> PackageDescription
-> LocalBuildInfo
-> UserHooks
-> BuildFlags
-> IO ()
uuagcBuildHook :: ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
-> PackageDescription
-> LocalBuildInfo
-> UserHooks
-> BuildFlags
-> IO ()
uuagcBuildHook [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
uuagc PackageDescription
pd LocalBuildInfo
lbi UserHooks
uh BuildFlags
bf = do
let classesPath :: [Char]
classesPath = LocalBuildInfo -> [Char]
buildDir' LocalBuildInfo
lbi [Char] -> [Char] -> [Char]
</> [Char]
agClassesFile
([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
-> [Char]
-> PackageDescription
-> LocalBuildInfo
-> Flag Verbosity
-> IO ()
commonHook [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
uuagc [Char]
classesPath PackageDescription
pd LocalBuildInfo
lbi (BuildFlags -> Flag Verbosity
buildVerbosity BuildFlags
bf)
PackageDescription
-> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()
originalBuildHook PackageDescription
pd LocalBuildInfo
lbi UserHooks
uh BuildFlags
bf
commonHook :: ([String] -> FilePath -> IO (ExitCode, [FilePath]))
-> FilePath
-> PackageDescription
-> LocalBuildInfo
-> Flag Verbosity
-> IO ()
commonHook :: ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
-> [Char]
-> PackageDescription
-> LocalBuildInfo
-> Flag Verbosity
-> IO ()
commonHook [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
uuagc [Char]
classesPath PackageDescription
pd LocalBuildInfo
lbi Flag Verbosity
fl = do
let verbosity :: Verbosity
verbosity = Verbosity -> Flag Verbosity -> Verbosity
forall a. a -> Flag a -> a
fromFlagOrDefault Verbosity
normal Flag Verbosity
fl
Verbosity -> [Char] -> IO ()
info Verbosity
verbosity ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"commonHook: Assuming AG classesPath: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
classesPath
Verbosity -> Bool -> [Char] -> IO ()
createDirectoryIfMissingVerbose Verbosity
verbosity Bool
True (LocalBuildInfo -> [Char]
buildDir' LocalBuildInfo
lbi)
oldOptions <- [Char] -> IO (Map [Char] (Options, Maybe ([Char], [[Char]])))
readFileOptions [Char]
classesPath
let lib = PackageDescription -> Maybe Library
library PackageDescription
pd
exes = PackageDescription -> [Executable]
executables PackageDescription
pd
bis = (Library -> BuildInfo) -> [Library] -> [BuildInfo]
forall a b. (a -> b) -> [a] -> [b]
map Library -> BuildInfo
libBuildInfo (Maybe Library -> [Library]
forall a. Maybe a -> [a]
maybeToList Maybe Library
lib) [BuildInfo] -> [BuildInfo] -> [BuildInfo]
forall a. [a] -> [a] -> [a]
++ (Executable -> BuildInfo) -> [Executable] -> [BuildInfo]
forall a b. (a -> b) -> [a] -> [b]
map Executable -> BuildInfo
buildInfo [Executable]
exes
classes <- map (className &&& opts') `fmap` (getAGClasses . customFieldsPD $ pd)
configOptions <- getAGFileOptions (bis >>= customFieldsBI)
newOptionsL <- forM configOptions (\ AGFileOption
opt ->
let ([[Char]]
notFound, Options
opts) = [([Char], Options)] -> AGFileOption -> ([[Char]], Options)
getOptionsFromClass [([Char], Options)]
classes (AGFileOption -> ([[Char]], Options))
-> AGFileOption -> ([[Char]], Options)
forall a b. (a -> b) -> a -> b
$ AGFileOption
opt
file :: [Char]
file = [Char] -> [Char]
normalise ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ AGFileOption -> [Char]
filename AGFileOption
opt
gen :: Maybe ([Char], [[Char]])
gen = Maybe ([Char], [[Char]])
-> ((Options, Maybe ([Char], [[Char]]))
-> Maybe ([Char], [[Char]]))
-> Maybe (Options, Maybe ([Char], [[Char]]))
-> Maybe ([Char], [[Char]])
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Maybe ([Char], [[Char]])
forall a. Maybe a
Nothing (Options, Maybe ([Char], [[Char]])) -> Maybe ([Char], [[Char]])
forall a b. (a, b) -> b
snd (Maybe (Options, Maybe ([Char], [[Char]]))
-> Maybe ([Char], [[Char]]))
-> Maybe (Options, Maybe ([Char], [[Char]]))
-> Maybe ([Char], [[Char]])
forall a b. (a -> b) -> a -> b
$ [Char]
-> Map [Char] (Options, Maybe ([Char], [[Char]]))
-> Maybe (Options, Maybe ([Char], [[Char]]))
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup [Char]
file Map [Char] (Options, Maybe ([Char], [[Char]]))
oldOptions
in do Verbosity -> [Char] -> IO ()
info Verbosity
verbosity ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"options for " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
file [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> [Char]
unwords (Options -> [[Char]]
optionsToString Options
opts)
[[Char]] -> ([Char] -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [[Char]]
notFound (Handle -> [Char] -> IO ()
hPutStrLn Handle
stderr)
([Char], (Options, Maybe ([Char], [[Char]])))
-> IO ([Char], (Options, Maybe ([Char], [[Char]])))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char]
file, (Options
opts, Maybe ([Char], [[Char]])
gen)))
let newOptions = [([Char], (Options, Maybe ([Char], [[Char]])))]
-> Map [Char] (Options, Maybe ([Char], [[Char]]))
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [([Char], (Options, Maybe ([Char], [[Char]])))]
newOptionsL
writeFileOptions classesPath newOptions
mapM_ (updateAGFile uuagc newOptions) $ Map.toList oldOptions
getAGFileList :: AGFileOptions -> [FilePath]
getAGFileList :: AGFileOptions -> [[Char]]
getAGFileList = (AGFileOption -> [Char]) -> AGFileOptions -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char] -> [Char]
normalise ([Char] -> [Char])
-> (AGFileOption -> [Char]) -> AGFileOption -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AGFileOption -> [Char]
filename)
uuagc :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
uuagc :: BuildInfo
-> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
uuagc = ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
-> BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
uuagc' ([Char] -> [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
uuagcFromString [Char]
uuagcn)
uuagc' :: ([String] -> FilePath -> IO (ExitCode, [FilePath]))
-> BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
uuagc' :: ([[Char]] -> [Char] -> IO (ExitCode, [[Char]]))
-> BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> PreProcessor
uuagc' [[Char]] -> [Char] -> IO (ExitCode, [[Char]])
uuagc BuildInfo
build LocalBuildInfo
lbi ComponentLocalBuildInfo
_ =
PreProcessor {
#if MIN_VERSION_Cabal(3,8,1)
ppOrdering :: Verbosity -> [[Char]] -> [ModuleName] -> IO [ModuleName]
ppOrdering = \Verbosity
_verbosity [[Char]]
_files [ModuleName]
modules -> [ModuleName] -> IO [ModuleName]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [ModuleName]
modules,
#endif
platformIndependent :: Bool
platformIndependent = Bool
True,
runPreProcessor :: ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ()
runPreProcessor = ([Char] -> [Char] -> Verbosity -> IO ())
-> ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ()
mkSimplePreProcessor (([Char] -> [Char] -> Verbosity -> IO ())
-> ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ())
-> ([Char] -> [Char] -> Verbosity -> IO ())
-> ([Char], [Char])
-> ([Char], [Char])
-> Verbosity
-> IO ()
forall a b. (a -> b) -> a -> b
$ \ [Char]
inFile [Char]
outFile Verbosity
verbosity ->
do Verbosity -> [Char] -> IO ()
notice Verbosity
verbosity ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"[UUAGC] processing: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
inFile [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" generating: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
outFile
let classesPath :: [Char]
classesPath = LocalBuildInfo -> [Char]
buildDir' LocalBuildInfo
lbi [Char] -> [Char] -> [Char]
</> [Char]
agClassesFile
Verbosity -> [Char] -> IO ()
info Verbosity
verbosity ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"uuagc-preprocessor: Assuming AG classesPath: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
classesPath
fileOpts <- [Char] -> IO (Map [Char] (Options, Maybe ([Char], [[Char]])))
readFileOptions [Char]
classesPath
opts <- case Map.lookup inFile fileOpts of
Maybe (Options, Maybe ([Char], [[Char]]))
Nothing -> do Verbosity -> [Char] -> IO ()
warn Verbosity
verbosity ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"No options found for " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
inFile
Options -> IO Options
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Options
noOptions
Just (Options
opt,Maybe ([Char], [[Char]])
gen) -> Options -> IO Options
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Options
opt
let search = [Char] -> [Char]
dropFileName [Char]
inFile
options = Options
opts { searchPath = search : hsSourceDirsFilePaths (hsSourceDirs build) ++ searchPath opts
, outputFiles = outFile : (outputFiles opts) }
(eCode,_) <- uuagc (optionsToString options) inFile
case eCode of
ExitCode
ExitSuccess -> [Char] -> Map [Char] (Options, Maybe ([Char], [[Char]])) -> IO ()
writeFileOptions [Char]
classesPath ([Char]
-> (Options, Maybe ([Char], [[Char]]))
-> Map [Char] (Options, Maybe ([Char], [[Char]]))
-> Map [Char] (Options, Maybe ([Char], [[Char]]))
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert [Char]
inFile (Options
opts, ([Char], [[Char]]) -> Maybe ([Char], [[Char]])
forall a. a -> Maybe a
Just ([Char]
outFile, Options -> [[Char]]
searchPath Options
options)) Map [Char] (Options, Maybe ([Char], [[Char]]))
fileOpts)
ex :: ExitCode
ex@(ExitFailure Int
_) -> ExitCode -> IO ()
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO ExitCode
ex
}
#if MIN_VERSION_Cabal(3,14,0)
hsSourceDirsFilePaths :: [SymbolicPath Pkg (Dir Source)] -> [FilePath]
hsSourceDirsFilePaths = map getSymbolicPath
#elif MIN_VERSION_Cabal(3,6,0)
hsSourceDirsFilePaths :: [SymbolicPath PackageDir SourceDir] -> [FilePath]
hsSourceDirsFilePaths :: [SymbolicPath PackageDir SourceDir] -> [[Char]]
hsSourceDirsFilePaths = (SymbolicPath PackageDir SourceDir -> [Char])
-> [SymbolicPath PackageDir SourceDir] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map SymbolicPath PackageDir SourceDir -> [Char]
forall from to. SymbolicPath from to -> [Char]
getSymbolicPath
#else
hsSourceDirsFilePaths :: [FilePath] -> [FilePath]
hsSourceDirsFilePaths = id
#endif
nouuagc :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
nouuagc :: BuildInfo
-> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
nouuagc BuildInfo
build LocalBuildInfo
lbi ComponentLocalBuildInfo
_ =
PreProcessor {
#if MIN_VERSION_Cabal(3,8,1)
ppOrdering :: Verbosity -> [[Char]] -> [ModuleName] -> IO [ModuleName]
ppOrdering = \Verbosity
_verbosity [[Char]]
_files [ModuleName]
modules -> [ModuleName] -> IO [ModuleName]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [ModuleName]
modules,
#endif
platformIndependent :: Bool
platformIndependent = Bool
True,
runPreProcessor :: ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ()
runPreProcessor = ([Char] -> [Char] -> Verbosity -> IO ())
-> ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ()
mkSimplePreProcessor (([Char] -> [Char] -> Verbosity -> IO ())
-> ([Char], [Char]) -> ([Char], [Char]) -> Verbosity -> IO ())
-> ([Char] -> [Char] -> Verbosity -> IO ())
-> ([Char], [Char])
-> ([Char], [Char])
-> Verbosity
-> IO ()
forall a b. (a -> b) -> a -> b
$ \[Char]
inFile [Char]
outFile Verbosity
verbosity -> do
Verbosity -> [Char] -> IO ()
info Verbosity
verbosity ([Char]
"skipping: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
outFile)
}