Skip to content

Commit 07f79dc

Browse files
committed
More install
1 parent 2f6eb53 commit 07f79dc

1 file changed

Lines changed: 163 additions & 91 deletions

File tree

Tools/Install.hs

Lines changed: 163 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,115 @@
11
module Install where
22
import Control.Monad
3+
import Data.List
34
import Data.Maybe
45
import Data.Word
56
import Foreign.Storable
67
import Foreign.Marshal.Utils
78
import Foreign.Ptr
89
import System.Directory
9-
import System.Envirinment
10+
import System.Environment
1011
import System.FilePath
1112
import System.Process
1213
import MicroHs.Config
1314

1415
type CConf = [(Key, Value)]
1516

16-
theConfig :: String
17-
theConfig | _isWindows = "windows"
18-
| otherwise = "unix"
19-
20-
rts :: String
21-
rts = "src" </> "runtime"
22-
23-
doIt :: Bool
24-
doIt = False
2517

2618
main :: IO ()
2719
main = do
2820
args <- getArgs
2921
let flags = decodeArgs defaultFlags args
22+
confText <- macroExpand flags <$> readFile (confFile flags)
3023
home <- getHomeDirectory
31-
confText <- readFile (confFile flags)
3224
let conf = either (\ s -> error $ "cannot parse config " ++ s) id $
33-
parseConfig confFile confText
34-
cconf = fromMaybe (error $ "Cannot locate section " ++ theConfig) $
35-
lookup theConfig conf
36-
mcabal = home </> ".mcabal"
37-
mcabalBin = mcabal </> "bin"
25+
parseConfig (confFile flags) confText
26+
cc = fromMaybe (error $ "Cannot locate section " ++ target flags) $
27+
lookup (target flags) conf
28+
exe | target flags == "windows" = "exe"
29+
| otherwise = ""
30+
inst = fromMaybe (home </> ".mcabal") (instDirM flags)
31+
flags' = flags { exeSuffix = exe, cconf = cc, instDir = inst, conf = confText }
32+
33+
install flags
34+
35+
install :: Flags -> IO ()
36+
install flags = do
37+
instBin flags
38+
vers <- init <$> mhsOut flags ["--numeric-version"]
39+
let flags' = flags { version = vers }
40+
mkMachdep flags'
41+
mkConf flags
42+
copyRTS flags'
43+
copyBase flags'
44+
checkPath flags'
45+
46+
instBin :: Flags -> IO ()
47+
instBin flags = do
48+
let mCabal = instDir flags
49+
mcabalBin = mCabal </> "bin"
3850
exes = ["mhs", "cpphs", "mcabal"]
39-
--
40-
mkdir "bin"
41-
mapM_ (buildBin cconf) exes
42-
machdep $ rts </> "MachDeps.h"
43-
mkdir mcabalBin
44-
let cpbin pgm = let exe = pgm <.> exeSuffix in copy ("bin" </> exe) (mcabalBin </> exe)
51+
mkdir flags "bin"
52+
mapM_ (buildBin flags) exes
53+
mkdir flags mcabalBin
54+
let cpbin pgm = do
55+
let exe = pgm <.> exeSuffix flags
56+
copy flags ("bin" </> exe) (mcabalBin </> exe)
4557
mapM_ cpbin exes
46-
version <- init <$> mhsOut ["--numeric-version"]
47-
let mCabalMhs = mcabal </> ("mhs-" ++ version)
48-
mData = mCabalMhs </> "packages" </> ("mhs-" ++ version) </> "data"
49-
mkdir mData
50-
copy "mhs.conf" (mData </> "mhs.conf")
51-
copyDir rts (mData </> rts)
52-
53-
{-
54-
MCABALMHS=$(MCABAL)/mhs-$(VERSION)
55-
MDATA=$(MCABALMHS)/packages/mhs-$(VERSION)/data
56-
MRUNTIME=$(MDATA)/$(RTS)
57-
cp -r $(RTS)/* $(MRUNTIME)
58-
@mkdir -p $(MCABALMHS)
59-
bin/mhs -Q generated/base.pkg $(MCABALMHS)
60-
@echo $$PATH | tr ':' '\012' | grep -q $(MCABALBIN) || echo '***' Add $(MCABALBIN) to the PATH
61-
-}
62-
63-
buildBin :: CConf -> String -> IO ()
64-
buildBin cconf pgm = do
58+
59+
mkMachdep :: Flags -> IO ()
60+
mkMachdep flags =
61+
machdep flags $ "src" </> "runtime" </> "MachDeps.h"
62+
63+
mkConf :: Flags -> IO ()
64+
mkConf flags = do
65+
msg flags $ "create mhs.conf"
66+
unless (dryRun flags) $
67+
writeFile "mhs.conf" (conf flags)
68+
69+
copyRTS :: Flags -> IO ()
70+
copyRTS flags = do
71+
let mCabalMhs = instDir flags </> ("mhs-" ++ version flags)
72+
let mData = mCabalMhs </> "packages" </> ("mhs-" ++ version flags) </> "data"
73+
rts = "src" </> "runtime"
74+
mkdir flags mData
75+
copy flags "mhs.conf" (mData </> "mhs.conf")
76+
copyDir flags rts (mData </> rts)
77+
78+
copyBase :: Flags -> IO ()
79+
copyBase flags = do
80+
let mCabalMhs = instDir flags </> ("mhs-" ++ version flags)
81+
mkdir flags mCabalMhs
82+
out <- mhsOut flags ["-Q", "generated" </> "base.pkg", mCabalMhs]
83+
msg flags out
84+
85+
checkPath :: Flags -> IO ()
86+
checkPath flags = do
87+
path <- fromMaybe "" <$> lookupEnv "PATH"
88+
let paths = splitOn pathSep path
89+
pathSep | target flags == "windows" = ";"
90+
| otherwise = ":"
91+
bin = instDir flags </> bin
92+
when (bin `notElem` paths) $
93+
putStrLn $ "Please add " ++ bin ++ " to your PATH"
94+
95+
buildBin :: Flags -> String -> IO ()
96+
buildBin flags pgm = do
6597
let src = "generated" </> pgm <.> ".c"
66-
dst = "bin" </> pgm <.> exeSuffix
67-
cc cconf [get cconf "ccflags", "-I" ++ rts, "-I" ++ (rts </> get cconf "conf"),
98+
dst = "bin" </> pgm <.> exeSuffix flags
99+
ccf = cconf flags
100+
rts = "src" </> "runtime"
101+
cc flags [get ccf "ccflags", "-I" ++ rts, "-I" ++ (rts </> get ccf "conf"),
68102
rts </> "main.c", rts </> "eval.c",
69-
src, get cconf "cclibs", getD cconf "-o" "cout" ++ dst]
103+
src, get ccf "cclibs", getD ccf "-o" "cout" ++ dst]
70104

71-
mhsOut :: [String] -> IO String
72-
mhsOut args =
73-
readProcess ("bin" </> "mhs" <.> exeSuffix) args ""
105+
mhsOut :: Flags -> [String] -> IO String
106+
mhsOut flags args = do
107+
let exe = "bin" </> "mhs" <.> exeSuffix flags
108+
msg flags $ unwords (exe:args)
109+
if dryRun flags then
110+
return "MHSOUT"
111+
else
112+
readProcess exe args ""
74113

75114
-----
76115

@@ -82,33 +121,30 @@ get cconf key = getD cconf (error $ "Cannot find " ++ key) key
82121

83122
-----
84123

85-
cc :: CConf -> [String] -> IO ()
86-
cc cconf args = do
87-
let c = get cconf "cc"
88-
msg $ unwords (c : args)
89-
when doIt $
124+
cc :: Flags -> [String] -> IO ()
125+
cc flags args = do
126+
let c = get (cconf flags) "cc"
127+
msg flags $ unwords (c : args)
128+
unless (dryRun flags) $
90129
callProcess c args
91130

92-
exeSuffix :: String
93-
exeSuffix | _isWindows = "exe"
94-
| otherwise = ""
95-
96-
msg :: String -> IO ()
97-
msg s = putStrLn s
131+
msg :: Flags -> String -> IO ()
132+
msg flags s | not (quiet flags) = putStrLn s
133+
| otherwise = return ()
98134

99135
-----
100136

101-
mkdir :: FilePath -> IO ()
102-
mkdir dir = do
103-
msg $ "mkdir " ++ dir
104-
when doIt $
137+
mkdir :: Flags -> FilePath -> IO ()
138+
mkdir flags dir = do
139+
msg flags $ "mkdir " ++ dir
140+
unless (dryRun flags) $
105141
createDirectoryIfMissing True dir
106142

107-
machdep :: FilePath -> IO ()
108-
machdep name = do
109-
msg $ "create " ++ name
143+
machdep :: Flags -> FilePath -> IO ()
144+
machdep flags name = do
145+
msg flags $ "create " ++ name
110146
big <- isBigEndian
111-
when doIt $
147+
unless (dryRun flags) $
112148
writeFile name $ unlines
113149
[ "#define WORD_SIZE_IN_BITS " ++ show _wordSize
114150
, (if big then "#define" else "#undef") ++ " WORDS_BIGENDIAN"
@@ -122,54 +158,90 @@ isBigEndian = do
122158
b <- peek (castPtr p :: Ptr Word8)
123159
return (b == 1)
124160

125-
copy :: FilePath -> FilePath -> IO ()
126-
copy src dst = do
127-
msg $ unwords ["cp", src, dst]
128-
when doIt $ do
161+
copy :: Flags -> FilePath -> FilePath -> IO ()
162+
copy flags src dst = do
163+
msg flags $ unwords ["cp", src, dst]
164+
unless (dryRun flags) $ do
129165
copyFile src dst
130166
copyPermissions src dst
131167

132-
copyDir :: FilePath -> FilePath -> IO ()
133-
copyDir src dst = do
134-
mkdir dst
168+
copyDir :: Flags -> FilePath -> FilePath -> IO ()
169+
copyDir flags src dst = do
170+
mkdir flags dst
135171
let one file = do
136172
d <- doesDirectoryExist file
137-
(if d then copyDir else copy) (src </> d) (dst </> d)
173+
(if d then copyDir else copy) flags (src </> file) (dst </> file)
138174
mapM_ one =<< listDirectory src
139175

176+
splitOn :: String -> String -> [String]
177+
splitOn d = loop []
178+
where loop [] [] = []
179+
loop r [] = [reverse r]
180+
loop r s@(c:cs) | Just s' <- stripPrefix d s = reverse r : loop [] s'
181+
| otherwise = loop (c:r) cs
182+
183+
macroExpand :: Flags -> String -> String
184+
macroExpand flags = loop
185+
where loop [] = []
186+
loop ('$':cs) = p ++ loop r where (p, r) = expnd (macros flags) cs
187+
loop (c:cs) = c : loop cs
188+
expnd [] s = ("", s)
189+
expnd ((m,e):ms) s | Just r <- stripPrefix m s = (e, r)
190+
| otherwise = expnd ms s
191+
140192
-----
141193

142194
data Flags = Flags
143-
{ target :: String
144-
, dryRun :: Bool
145-
, verbose :: Bool
146-
, macros :: [String]
147-
, goals :: [String]
148-
, confFile :: FilePath
195+
{ target :: String
196+
, dryRun :: Bool
197+
, verbose :: Bool
198+
, quiet :: Bool
199+
, macros :: [(String, String)]
200+
, goals :: [String]
201+
, confFile :: FilePath
202+
, instDirM :: Maybe FilePath
203+
-- The rest are for internal use
204+
, exeSuffix :: String
205+
, instDir :: FilePath
206+
, cconf :: CConf
207+
, version :: String
208+
, conf :: String
149209
}
150210
deriving (Show)
151211

152212
defaultFlags :: Flags
153-
defaultFlags = Flags
154-
{ target = if _isWindows then "windows" else "unix"
155-
, dryRun = False
156-
, verbose = False
157-
, macros = []
158-
, goals = []
159-
, confFile = "mhs.conf"
160-
}
213+
defaultFlags =
214+
Flags
215+
{ target = if _isWindows then "windows" else "unix"
216+
, dryRun = False
217+
, verbose = False
218+
, quiet = False
219+
, macros = []
220+
, goals = []
221+
, confFile = "mhs.conf.in"
222+
, instDirM = Nothing
223+
--
224+
, exeSuffix = undefined
225+
, instDir = undefined
226+
, cconf = undefined
227+
, version = undefined
228+
, conf = undefined
229+
}
161230

162231
decodeArgs :: Flags -> [String] -> Flags
163232
decodeArgs f [] = f
164233
decodeArgs f (arg:args) =
165234
case arg of
166235
"--help" -> error usage
167236
"-v" -> decodeArgs f{verbose = True} args
237+
"-q" -> decodeArgs f{quiet = True} args
168238
"--dryrun" -> decodeArgs f{dryRun = True} args
169-
'-':'t':s -> decodeArgs f{target = s} mdls args
239+
'-':'t':s -> decodeArgs f{target = s} args
240+
'-':'i':s -> decodeArgs f{instDirM = Just s} args
170241
'-':_ -> error $ "Unknown flag: " ++ arg ++ "\n" ++ usage
171-
_ | '=' `elem` arg -> decodeArgs f{macros = macros f ++ [arg]} args
242+
_ | (m, '=':e) <- span (/= '=') arg
243+
-> decodeArgs f{macros = macros f ++ [(m, e)]} args
172244
| otherwise -> decodeArgs f{goals = goals f ++ [arg]} args
173245

174246
usage :: String
175-
usage = "\ninstall [--help] [-v] [--dryrun] [-tTARGET] [NAME=MACRO] [GOAL]\n"
247+
usage = "\ninstall [--help] [-v] [--dryrun] [-tTARGET] [-iDIR] [NAME=MACRO] [GOAL]\n"

0 commit comments

Comments
 (0)