-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSetup.hs
executable file
·110 lines (95 loc) · 4.3 KB
/
Setup.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#! /usr/bin/env runhaskell
module Main (main) where
import Control.Monad (liftM, when)
import Data.List (intersperse)
import Distribution.Simple
import Distribution.Simple.Setup
import Distribution.Simple.LocalBuildInfo
import Distribution.PackageDescription
import System.Process
import System.Exit
import System.Directory
import System.FilePath
main :: IO ()
main = defaultMainWithHooks simpleUserHooks{postInst=forsydePostInst,
postCopy=forsydePostCopy}
forsydePostInst :: Args -> InstallFlags -> PackageDescription ->
LocalBuildInfo -> IO ()
forsydePostInst _ _ = compile_forsyde_vhd NoCopyDest
forsydePostCopy :: Args -> CopyFlags -> PackageDescription ->
LocalBuildInfo -> IO ()
forsydePostCopy _ cf = compile_forsyde_vhd $ removeFlag $ (copyDest cf) where
removeFlag c = case c of
Distribution.Simple.Setup.Flag x -> x
_ -> error "Not a Flag"
-- NOTE: Most of this code is duplicated from ForSyDe.Backend.VHDL.Modelsim,
-- however, it allows Setup.hs to be selfcontained
-- Compile forsyde.vhd if possible, showing what's going on to the end user
compile_forsyde_vhd :: CopyDest -> PackageDescription -> LocalBuildInfo
-> IO ()
compile_forsyde_vhd cd pd lbi = do
putStrLn "Compiling ForSyDe's VHDL library with Modelsim ..."
(ifNot isModelsimInstalled
(modelsimError "Modelsim executables could not be found.")) <&&>
(ifNot (do_compile_forsyde_vhd forsyde_vhd_dir)
( modelsimError "Compilation failed.")) <&&>
(putStrLn "Compilation succeded." >> return True)
return ()
where
forsyde_vhd_dir = (datadir $ absoluteInstallDirs pd lbi cd) </>
"lib"
modelsimError err = putStrLn $
"Warning: " ++ err ++ "\n" ++
" ForSyDe will work, but you will not be able to automatically\n" ++
" compile or simulate the ForSyDe-generated VHDL models with Modelsim\n\n" ++
" In order to fix this, make sure that the Modelsim executables\n" ++
" can be found in PATH and reinstall ForSyDe"
-- Look for modelsim executables
isModelsimInstalled :: IO Bool
isModelsimInstalled = executablePresent "vlib" <&&>
executablePresent "vmap" <&&>
executablePresent "vcom"
where executablePresent = (liftM (maybe False (\_-> True))) .findExecutable
-- Create a modelsim library for forsyde.vhd
-- in the same directory in which forsyde.vhd was copied
do_compile_forsyde_vhd :: FilePath -- ^ absolute directory which
-- forsyde.vhd was copied into
-> IO Bool
do_compile_forsyde_vhd dir =
(runCommandMsg "vlib" [dir </> "modelsim"]) <&&>
(runCommandMsg
"vcom" ["-93", "-quiet", "-nologo", "-work", dir </> "modelsim",
dir </> "forsyde.vhd"])
where runWait :: String -> FilePath -> [String] -> IO Bool
runWait msg proc args = do
putStrLn msg
h <- runProcess proc args (Just dir) Nothing Nothing Nothing Nothing
code <- waitForProcess h
return $ code == ExitSuccess
-- | run a command showing what's being run
runCommandMsg :: String -- ^ Command to execute
-> [String] -- ^ Command arguments
-> IO Bool
runCommandMsg command args = runWait msg command args
where msg = "Running: " ++ command ++ " " ++ (concat $ intersperse " " args)
-- | Run a process, previously announcing a message and waiting for it
-- to finnish its execution.
runWait :: String -- ^ message to show
-> FilePath -- ^ command to execute
-> [String] -- ^ command arguments
-> IO Bool -- ^ Did the execution end succesfully?
runWait msg proc args = do
putStrLn msg
h <- runProcess proc args Nothing Nothing Nothing Nothing Nothing
code <- waitForProcess h
return $ code == ExitSuccess
-- | short-circuit and for monads
(<&&>) :: Monad m => m Bool -> m Bool -> m Bool
x <&&> y = do p <- x
if p then y else return False
-- | execute an action when the argument is False
-- and return the boolean value
ifNot :: Monad m => m Bool -> m () -> m Bool
ifNot x a = do p <- x
when (not p) a
return p