@@ -0,0 +1,128 @@
1+module Pkg.Package where
2+
3+import System.Process
4+import System.Directory
5+import System.Exit
6+import System.IO
7+
8+import Util.System
9+
10+import Control.Monad
11+import Data.List
12+
13+import Core.TT
14+import Idris.REPL
15+import Idris.AbsSyntax
16+
17+import Pkg.PParser
18+
19+import Paths_idris
20+
21+-- To build a package:
22+-- * read the package description
23+-- * check all the library dependencies exist
24+-- * invoke the makefile if there is one
25+-- * invoke idris on each module, with idris_opts
26+-- * install everything into datadir/pname, if install flag is set
27+
28+buildPkg :: Bool -> (Bool, FilePath) -> IO ()
29+buildPkg warnonly (install, fp)
30+ = do pkgdesc <- parseDesc fp
31+ ok <- mapM (testLib warnonly (pkgname pkgdesc)) (libdeps pkgdesc)
32+ when (and ok) $
33+ do make (makefile pkgdesc)
34+ dir <- getCurrentDirectory
35+ setCurrentDirectory $ dir ++ "/" ++ sourcedir pkgdesc
36+ case (execout pkgdesc) of
37+ Nothing -> buildMods (NoREPL : Verbose : idris_opts pkgdesc)
38+ (modules pkgdesc)
39+ Just o -> do let exec = dir ++ "/" ++ o
40+ buildMod
41+ (NoREPL : Verbose : Output exec : idris_opts pkgdesc)
42+ (idris_main pkgdesc)
43+ setCurrentDirectory dir
44+ when install $ installPkg pkgdesc
45+
46+cleanPkg :: FilePath -> IO ()
47+cleanPkg fp
48+ = do pkgdesc <- parseDesc fp
49+ clean (makefile pkgdesc)
50+ dir <- getCurrentDirectory
51+ setCurrentDirectory $ dir ++ "/" ++ sourcedir pkgdesc
52+ mapM_ rmIBC (modules pkgdesc)
53+ case execout pkgdesc of
54+ Nothing -> return ()
55+ Just s -> do let exec = dir ++ "/" ++ s
56+ putStrLn $ "Removing " ++ exec
57+ system $ "rm -f " ++ exec
58+ return ()
59+
60+installPkg :: PkgDesc -> IO ()
61+installPkg pkgdesc
62+ = do dir <- getCurrentDirectory
63+ setCurrentDirectory $ dir ++ "/" ++ sourcedir pkgdesc
64+ case (execout pkgdesc) of
65+ Nothing -> mapM_ (installIBC (pkgname pkgdesc)) (modules pkgdesc)
66+ Just o -> return () -- do nothing, keep executable locally, for noe
67+
68+buildMod :: [Opt] -> Name -> IO ()
69+buildMod opts n = do let f = map slash $ show n
70+ idris (Filename f : opts)
71+ return ()
72+ where slash '.' = '/'
73+ slash x = x
74+
75+buildMods :: [Opt] -> [Name] -> IO ()
76+buildMods opts ns = do let f = map ((map slash) . show) ns
77+ idris (map Filename f ++ opts)
78+ return ()
79+ where slash '.' = '/'
80+ slash x = x
81+
82+testLib :: Bool -> String -> String -> IO Bool
83+testLib warn p f
84+ = do d <- getDataDir
85+ gcc <- getCC
86+ (tmpf, tmph) <- tempfile
87+ hClose tmph
88+ e <- system $ gcc ++ " " ++ d ++ "/rts/libtest.c -l" ++ f ++ " -o " ++ tmpf
89+ case e of
90+ ExitSuccess -> return True
91+ _ -> do if warn
92+ then do putStrLn $ "Not building " ++ p ++
93+ " due to missing library " ++ f
94+ return False
95+ else fail $ "Missing library " ++ f
96+
97+rmIBC :: Name -> IO ()
98+rmIBC m = do let f = toIBCFile m
99+ putStrLn $ "Removing " ++ f
100+ system $ "rm -f " ++ f
101+ return ()
102+
103+toIBCFile (UN n) = n ++ ".ibc"
104+toIBCFile (NS n ns) = concat (intersperse "/" (reverse ns)) ++ "/" ++ toIBCFile n
105+
106+installIBC :: String -> Name -> IO ()
107+installIBC p m = do let f = toIBCFile m
108+ d <- getDataDir
109+ let destdir = d ++ "/" ++ p ++ "/" ++ getDest m
110+ putStrLn $ "Installing " ++ f ++ " to " ++ destdir
111+ system $ "mkdir -p " ++ destdir
112+ system $ "install " ++ f ++ " " ++ destdir
113+ return ()
114+ where getDest (UN n) = ""
115+ getDest (NS n ns) = concat (intersperse "/" (reverse ns)) ++ "/" ++ getDest n
116+
117+make :: Maybe String -> IO ()
118+make Nothing = return ()
119+make (Just s) = do system $ "make -f " ++ s
120+ return ()
121+
122+clean :: Maybe String -> IO ()
123+clean Nothing = return ()
124+clean (Just s) = do system $ "make -f " ++ s ++ " clean"
125+ return ()
126+
127+
128+