module Main where
import System.FilePath
import System.Directory
import Monad
import Data.List
import Distribution.Simple
import Distribution.Simple.Setup
import Distribution.Simple.Program
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.PreProcess
import Distribution.PackageDescription
import Distribution.Verbosity
import Distribution.ModuleName hiding (main)
import Curry.Files.CymakePath
import Curry.Files.KiCSPath
import Curry.Files.ProphecyPath
withLibs :: Bool
withLibs = False
kics, cymake, prophecy :: IO Program
kics = mkProg getKiCS
cymake = mkProg getCymake
prophecy = mkProg getProphecy
mkProg getProg = do
call <- getProg
return (simpleProgram (takeBaseName call))
{programFindLocation = \_-> return (Just call)}
mkstrict :: Program
mkstrict = simpleProgram "mkstrict"
main :: IO ()
main = do
cymakeProg <- cymake
kicsProg <- kics
prophecyProg <- prophecy
defaultMainWithHooks simpleUserHooks
{hookedPrograms=mkstrict:kicsProg:cymakeProg:prophecyProg:
hookedPrograms simpleUserHooks
,confHook=myConfHook
,postConf=myPostConf
,hookedPreProcessors=[("curry",mkModule),
("lcurry",mkModule),
("fcy",mkOracleModule)]
}
-- what a hack! something was forgotten in Distribution.ModuleName
modName :: [String] -> ModuleName
modName xs = read $ "ModuleName " ++ show xs
myConfHook ::
(Either GenericPackageDescription PackageDescription, HookedBuildInfo)
-> ConfigFlags -> IO LocalBuildInfo
myConfHook info flags = do
lbi <- confHook simpleUserHooks info flags
if not withLibs
then return lbi
else do
print 13
libPath <- getKiCSLibDir
allFiles <- getDirectoryContents libPath
let stdfiles = filter (isSuffixOf ".fcy") allFiles
goodfiles = filter (not . (`elem` badlibs) . takeBaseName) stdfiles
stdlibs = map takeBaseName stdfiles
goodlibs = map takeBaseName goodfiles
libs = map (\ l -> modName ("Curry":"Module":["Oracle" ++ l])) stdlibs
++map (\ l -> modName ("Curry":"DebugModule":[l])) goodlibs
let dbgPath = "Curry" </> "DebugModule"
mapM_ (putStrLn . (" "++) . foldr (<.>) "" . components) libs
mapM_ (\ lib -> mayCopyFile (libPath </> lib) (dbgPath </> lib)) goodfiles
let require = requireProg flags lbi
prop <- require prophecy
mapM_ (mkOracleLib (unflag $ configVerbosity flags) prop) stdlibs
dataPath <- getKiCSDataDir
let package = localPkgDescr lbi
Just lib = library package
ex = exposedModules lib
llbi = libBuildInfo lib
hsdirs = hsSourceDirs llbi
llbi' = llbi{hsSourceDirs=dataPath:hsdirs}
lib' = Just lib{exposedModules=ex ++ libs,
libBuildInfo=llbi'}
return (lbi{localPkgDescr=package{library=lib'}})
mayCopyFile :: FilePath -> FilePath -> IO ()
mayCopyFile src dest = do
ex <- doesFileExist dest
if ex then return () else copyFile src dest
unflag = fromFlagOrDefault silent
requireProg :: ConfigFlags -> LocalBuildInfo -> IO Program
-> IO ConfiguredProgram
requireProg verb lbi prog = do
p <- prog
(cp,_) <- requireProgram (unflag $ configVerbosity verb) p AnyVersion
(withPrograms lbi)
return cp
callProg :: Verbosity -> LocalBuildInfo -> IO Program -> Args -> IO ()
callProg verb lbi prog args = do
p <- prog
rawSystemProgramConf verb p (withPrograms lbi) args
mkOracleLib :: Verbosity -> ConfiguredProgram -> FilePath -> IO ()
mkOracleLib verb prop stdlib = do
rawSystemProgram verb prop ["-o","Curry/Module/",stdlib]
return ()
myPostConf ::
Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()
myPostConf args confFlags descrs lbi = do
let require = requireProg confFlags lbi
require cymake
require kics
require prophecy
postConf simpleUserHooks args confFlags descrs lbi
badlibs =
[
-- mkstrict fails
"Traversal"
,"FlatCurry"
,"AbstractCurry"
,"SetRBT"
,"TableRBT"
,"Pretty"
,"CurryStringClassifier"
,"FiniteMap"
,"Parser"
,"EventOracle"
,"CurrySyntax"
,"EasyCheck"
-- consequence of FlatCurry failing
,"FlexRigid","FlatCurryTools","FlatCurryShow","FlatCurryRead"
,"FlatCurryXML","PrettyFlat","CompactFlatCurry","FlatCurryGoodies"
-- consequence of FiniteMap failing
,"GraphInductive"
-- consequence of AbstractCurry failing
,"AbstractCurryPrinter"
-- consequence of Pretty failing
,"StyledText"
-- resulting haskell incorrect
,"RedBlackTree"
,"IO"
,"Global"
,"Array"
,"Meta"
-- consequence of incorrect IO
, "Assertion"
, "Oracle"
, "Distribution"
, "CEventOracle"
, "IOExts"
, "PropertyFile"
, "Socket"
-- consequence of incorrect Meta
, "Unsafe"
-- consequence of incorrect Global
, "System"
, "Random"
]
mkModule :: BuildInfo -> LocalBuildInfo -> PreProcessor
mkModule _ lbi = PreProcessor
{platformIndependent = True
,runPreProcessor = mkSimplePreProcessor $ \ inf outf verb -> do
datadir <- getKiCSLibDir
runKics datadir lbi inf outf verb}
runKics :: FilePath -> LocalBuildInfo
-> FilePath -> FilePath -> Verbosity -> IO ()
runKics datadir lbi infile outfile verb
| isPrefixOf "Curry/Module" infile
= do callCymake ["-iCurry/Module","--no-hidden-subdir"]
callKics ["-userlibpath","Curry/Module"]
| isPrefixOf "prophecy" infile
= do callCymake ["-iprophecy/Curry/Module"]
callKics $ ["-userlibpath","prophecy/Curry/Module"] ++
if isSuffixOf "Transform.curry" infile
then ["-executable","prophecy"]
else []
| isPrefixOf "biosphere" infile
= do callCymake ["-iprophecy/Curry/Module","-ibiosphere/src/Curry/Module"]
callKics $ ["-userlibpath",
"prophecy/Curry/Module:biosphere/src/Curry/Module"] ++
if isSuffixOf "TransformationDependencies.lcurry" infile
then ["-executable","mkstrict"]
else []
| otherwise = error $ "runKics, unexpected infile: " ++ infile
where
call = callProg verb lbi
callCymake args =
call cymake $ args ++ ["-i"++datadir,"-e","--flat",infile]
callKics args =
call kics $ args ++ ["-nomake","-o",outfile,infile]
mkOracleModule :: BuildInfo -> LocalBuildInfo -> PreProcessor
mkOracleModule buildInfo lbi = PreProcessor
{platformIndependent = True
,runPreProcessor = mkSimplePreProcessor (runKicsFcy lbi)}
runKicsFcy :: LocalBuildInfo -> FilePath -> FilePath -> Verbosity -> IO ()
runKicsFcy lbi infile outfile verb
| isPrefixOf "Curry/Module" infile
= do
libPath <- getOracleLibBaseDir
callKics ["-userlibpath",libPath ++ pathSeparator:"Curry/Module"]
| isPrefixOf "Curry/DebugModule" infile
= do
let dir = addTrailingPathSeparator $
joinPath $
reverse $ drop 2 $ reverse $
splitDirectories (takeDirectory outfile)
call (return mkstrict) ["-o",dir,dropExtension infile]
where
call = callProg verb lbi
callKics args =
call kics $ args ++ ["-nomake","--no-interfaces","-o",outfile,infile]