on 564cf4e help sign in
elk/Setup.hs
147 lines 4.7 kB history raw
1{-# OPTIONS_GHC -W #-}
2import Distribution.Simple
3import Distribution.Simple.LocalBuildInfo
4import Distribution.Simple.Setup
5import Distribution.PackageDescription
7import System.Directory
8import System.FilePath
9import System.IO
10import System.Process
12import qualified Data.Binary as Binary
13import qualified Data.ByteString.Lazy as BS
14import qualified Data.List as List
16-- OVERVIEW
17-- --------
18-- Add a post-build callout that compiles the standard libraries with the new
19-- compiler before cabal copies static files to actually install things.
21assetsDir :: FilePath
22assetsDir = "data"
24tempDir :: FilePath
25tempDir = "temp"
27-- The runtime is called:
28runtime :: FilePath
29runtime = assetsDir </> "elm-runtime.js"
31-- The runtime is called:
32docs :: FilePath
33docs = assetsDir </> "docs.json"
35-- The interfaces for the Standard Libraries live in:
36interfaces :: FilePath
37interfaces = assetsDir </> "interfaces.data"
39elm :: LocalBuildInfo -> FilePath
40elm lbi = buildDir lbi </> "elm" </> "elm"
42document :: LocalBuildInfo -> FilePath
43document lbi = buildDir lbi </> "elm-doc" </> "elm-doc"
45-- Care! This appears to be based on an unstable API
46-- See: http://www.haskell.org/cabal/release/cabal-latest/doc/API/Cabal/Distribution-Simple.html#2
49main :: IO ()
50main = defaultMainWithHooks simpleUserHooks { postBuild = myPostBuild }
54-- Post Build
56myPostBuild :: Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
57myPostBuild args flags packageDescription lbi = do
58 putStrLn "Custom build step: compiling standard libraries"
59 (elmos, elmis) <- compileLibraries lbi
60 putStrLn "Custom build step: build interfaces.data"
61 buildInterfaces elmis
62 putStrLn "Custom build step: build elm-runtime.js"
63 buildRuntime elmos
64 putStrLn "Custom build step: build docs.json"
65 buildDocs
66 removeDirectoryRecursive tempDir
67 removeDirectoryRecursive ("libraries" </> "docs")
68 postBuild simpleUserHooks args flags packageDescription lbi
71compileLibraries lbi = do
72 createDirectoryIfMissing True tempDir
73 createDirectoryIfMissing True assetsDir
74 out_c <- canonicalizePath tempDir -- temp (root folder)
75 elm_c <- canonicalizePath (elm lbi) -- dist/build/elm/elm
76 doc_c <- canonicalizePath (document lbi) -- dist/build/elm-doc/elm-doc
77 rtd_c <- canonicalizePath assetsDir -- data
79 let make file = do
80 let args =
81 [ "--only-js"
82 , "--make"
83 , "--no-prelude"
84 , "--cache-dir=" ++ out_c
85 , "--build-dir=" ++ out_c
86 , file
87 ]
88 let arg = Just [("Elm_datadir", rtd_c)]
89 handle <- runProcess elm_c args Nothing arg Nothing Nothing Nothing
90 _exitCode <- waitForProcess handle
91 return ( out_c </> replaceExtension file "elmo"
92 , out_c </> replaceExtension file "elmi"
93 )
95 setCurrentDirectory "libraries"
96 paths <- getFiles ".elm" "."
97 files <- unzip `fmap` mapM make paths
98 mapM_ (\path -> rawSystem doc_c [path]) paths
99 setCurrentDirectory ".."
100 return files
102buildInterfaces :: [FilePath] -> IO ()
103buildInterfaces elmis = do
104 createDirectoryIfMissing True assetsDir
105 ifaceHandle <- openBinaryFile interfaces WriteMode
106 BS.hPut ifaceHandle (Binary.encode (length elmis))
107 let append file = do
108 handle <- openBinaryFile file ReadMode
109 bits <- hGetContents handle
110 length bits `seq` hPutStr ifaceHandle bits
111 hClose handle
112 mapM_ append elmis
113 hClose ifaceHandle
115buildRuntime :: [FilePath] -> IO ()
116buildRuntime elmos = do
117 createDirectoryIfMissing True assetsDir
118 writeFile runtime
119 "'use strict';\n\
120 \var Elm = {}; Elm.Native = {}; Elm.Native.Graphics = {};\n\
121 \var ElmRuntime = {}; ElmRuntime.Render = {};\n"
122 mapM_ (appendTo runtime) =<< getFiles ".js" "libraries"
123 mapM_ (appendTo runtime) elmos
124 mapM_ (appendTo runtime) =<< getFiles ".js" "runtime"
126buildDocs :: IO ()
127buildDocs = do
128 createDirectoryIfMissing True assetsDir
129 writeFile docs "[\n"
130 json <- getFiles ".json" ("libraries" </> "docs")
131 let appends = map (appendTo docs) json
132 addCommas = List.intersperse (appendFile docs ",\n")
133 sequence_ (addCommas appends)
134 appendFile docs "\n]"
136getFiles ext dir = do
137 contents <- map (dir </>) `fmap` getDirectoryContents dir
138 let files = filter (\f -> takeExtension f == ext) contents
139 dirs = filter (not . hasExtension) contents
140 filess <- mapM (getFiles ext) dirs
141 return (files ++ concat filess)
143appendTo :: FilePath -> FilePath -> IO ()
144appendTo destination source = do
145 str <- readFile source
146 length str `seq` return ()
147 appendFile destination str