1import Distribution.Simple
2import Distribution.Simple.LocalBuildInfo
3import Distribution.Simple.Setup
4import Distribution.PackageDescription
13import qualified Data.Binary as Binary
14import qualified Data.ByteString.Lazy as BS
15import qualified Data.List as List
20-- We need to build elm-doc and run it because that generates the file "docs.json"
21-- needs by Libraries.hs which is part of the elm library and executable
22-- Unfort. there seems to be no way to tell cabal that:
23-- (a) elm-doc generates docs.json, and
24-- (b) elm (library) depends on docs.json
25-- Therefore, we either use make instead (or a script), or hack around in cabal
29-- Add a post-build callout.
30-- We need to build the runtime.js after we've built elm (because we use elm to generate some of the JavaScript),
31-- but before cabal does the install file copy step
34-- Elm.cabal expects the generated files to end up in dist/data
35-- git won't look in dist + cabal will clean it
36rtsDir :: LocalBuildInfo -> FilePath
39tempDir :: LocalBuildInfo -> FilePath
42-- The runtime is called:
43rts :: LocalBuildInfo -> FilePath
44rts lbi = rtsDir lbi </> "elm-runtime.js"
46-- The runtime is called:
47docs :: LocalBuildInfo -> FilePath
48docs lbi = rtsDir lbi </> "docs.json"
50-- The interfaces for the Standard Libraries live in:
51interfaces :: LocalBuildInfo -> FilePath
52interfaces lbi = rtsDir lbi </> "interfaces.data"
54elm :: LocalBuildInfo -> FilePath
55elm lbi = buildDir lbi </> "elm" </> "elm"
57document :: LocalBuildInfo -> FilePath
58document lbi = buildDir lbi </> "elm-doc" </> "elm-doc"
60-- Care! This appears to be based on an unstable API
61-- See: http://www.haskell.org/cabal/release/cabal-latest/doc/API/Cabal/Distribution-Simple.html#2
65main = defaultMainWithHooks simpleUserHooks { postBuild = myPostBuild }
70-- note(1): We use to include docs.json directly into LoadLibraries at compile time
71-- If docs.json is used in other (template) haskell files, they should be copied
72-- and compiled in a separate directory (eg, dist/copiedSrc).
73-- This is to make sure they are re-compiled on docs.json changes.
74-- Copying is a better solution than 'touch'ing the source files
75-- (touch is non-portable and confusing wrt RCS).
77-- In the PackageDescription, the list of stuff to build is held in library
78-- (in a Maybe) and the executables list. We want a PackageDescription that
79-- only mentions the executable 'name'
80filterExe :: String -> PackageDescription -> PackageDescription
81filterExe name pd = pd {
83 executables = filter (\x -> (exeName x == name)) (executables pd)
89myPostBuild :: Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
90myPostBuild as bfs pd lbi = do
91 putStrLn "Custom build step: compiling standard libraries"
92 (elmos, elmis) <- compileLibraries lbi
93 putStrLn "Custom build step: build interfaces.data"
94 buildInterfaces lbi elmis
95 putStrLn "Custom build step: build elm-runtime.js"
96 buildRuntime lbi elmos
97 putStrLn "Custom build step: build docs.json"
99 removeDirectoryRecursive (tempDir lbi)
100 removeDirectoryRecursive ("libraries" </> "docs")
101 postBuild simpleUserHooks as bfs pd lbi
104compileLibraries lbi = do
105 let temp = tempDir lbi -- temp
106 rts = rtsDir lbi -- data
107 createDirectoryIfMissing True temp
108 createDirectoryIfMissing True rts
109 out_c <- canonicalizePath temp -- temp (root folder)
110 elm_c <- canonicalizePath (elm lbi) -- dist/build/elm/elm
111 doc_c <- canonicalizePath (document lbi) -- dist/build/elm-doc/elm-doc
112 rtd_c <- canonicalizePath rts -- data
115 -- replace 'system' call with 'runProcess' which handles args better
116 -- and allows env variable "Elm_datadir" which is used by LoadLibraries
118 let args = [ "--only-js", "--make", "--no-prelude"
119 , "--cache-dir="++out_c, "--build-dir="++out_c, file ]
120 arg = Just [("Elm_datadir", rtd_c)]
121 handle <- runProcess elm_c args Nothing arg Nothing Nothing Nothing
122 exitCode <- waitForProcess handle
123 return ( out_c </> replaceExtension file "elmo"
124 , out_c </> replaceExtension file "elmi")
126 setCurrentDirectory "libraries"
127 paths <- getFiles ".elm" "."
128 files <- unzip `fmap` mapM make paths
129 mapM_ (\path -> rawSystem doc_c [path]) paths
130 setCurrentDirectory ".."
133buildInterfaces :: LocalBuildInfo -> [FilePath] -> IO ()
134buildInterfaces lbi elmis = do
135 createDirectoryIfMissing True (rtsDir lbi)
136 let ifaces = interfaces lbi
137 ifaceHandle <- openBinaryFile ifaces WriteMode
138 BS.hPut ifaceHandle (Binary.encode (length elmis))
140 handle <- openBinaryFile file ReadMode
141 bits <- hGetContents handle
142 length bits `seq` hPutStr ifaceHandle bits
147buildRuntime :: LocalBuildInfo -> [FilePath] -> IO ()
148buildRuntime lbi elmos = do
149 createDirectoryIfMissing True (rtsDir lbi)
151 writeFile rts' "var Elm = {}; Elm.Native = {}; Elm.Native.Graphics = {};\n\
152 \var ElmRuntime = {}; ElmRuntime.Render = {};\n"
153 mapM_ (appendTo rts') =<< getFiles ".js" "libraries"
154 mapM_ (appendTo rts') elmos
155 mapM_ (appendTo rts') =<< getFiles ".js" "runtime"
157buildDocs :: LocalBuildInfo -> IO ()
159 createDirectoryIfMissing True (rtsDir lbi)
161 writeFile docs' "[\n"
162 json <- getFiles ".json" ("libraries" </> "docs")
163 let appends = map (appendTo docs') json
164 addCommas = List.intersperse (appendFile docs' ",\n")
165 sequence_ (addCommas appends)
166 appendFile docs' "\n]"
169 contents <- map (dir </>) `fmap` getDirectoryContents dir
170 let files = filter (\f -> takeExtension f == ext) contents
171 dirs = filter (not . hasExtension) contents
172 filess <- mapM (getFiles ext) dirs
173 return (files ++ concat filess)
175appendTo :: FilePath -> FilePath -> IO ()
176appendTo destination source = do
177 str <- readFile source
178 length str `seq` return ()
179 appendFile destination str
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list