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)
86-- It's not enough to fix the PackageDescription, we also have to fix the
87-- LocalBuildInfo. This includes the component build order (data ComponentName)
88-- which is horribly internal.
89filterLBI :: String -> LocalBuildInfo -> LocalBuildInfo
90filterLBI name lbi = lbi {
91 libraryConfig = Nothing,
92 compBuildOrder = [CExeName name],
93 executableConfigs = filter (\a -> (fst a == name)) (executableConfigs lbi)
99myPostBuild :: Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
100myPostBuild as bfs pd lbi = do
101 putStrLn "Custom build step: compiling standard libraries"
102 (elmos, elmis) <- compileLibraries lbi
103 putStrLn "Custom build step: build interfaces.data"
104 buildInterfaces lbi elmis
105 putStrLn "Custom build step: build elm-runtime.js"
106 buildRuntime lbi elmos
107 putStrLn "Custom build step: build docs.json"
109 removeDirectoryRecursive (tempDir lbi)
110 removeDirectoryRecursive ("libraries" </> "docs")
111 postBuild simpleUserHooks as bfs pd lbi
114compileLibraries lbi = do
115 let temp = tempDir lbi -- temp
116 rts = rtsDir lbi -- data
117 createDirectoryIfMissing True temp
118 createDirectoryIfMissing True rts
119 out_c <- canonicalizePath temp -- temp (root folder)
120 elm_c <- canonicalizePath (elm lbi) -- dist/build/elm/elm
121 doc_c <- canonicalizePath (document lbi) -- dist/build/elm-doc/elm-doc
122 rtd_c <- canonicalizePath rts -- data
125 -- replace 'system' call with 'runProcess' which handles args better
126 -- and allows env variable "Elm_datadir" which is used by LoadLibraries
128 let args = [ "--only-js", "--make", "--no-prelude"
129 , "--cache-dir="++out_c, "--build-dir="++out_c, file ]
130 arg = Just [("Elm_datadir", rtd_c)]
131 handle <- runProcess elm_c args Nothing arg Nothing Nothing Nothing
132 exitCode <- waitForProcess handle
133 rawSystem doc_c [file]
134 return ( out_c </> replaceExtension file "elmo"
135 , out_c </> replaceExtension file "elmi")
137 setCurrentDirectory "libraries"
138 files <- getFiles ".elm" "."
139 files <- unzip `fmap` mapM make files
140 setCurrentDirectory ".."
143buildInterfaces :: LocalBuildInfo -> [FilePath] -> IO ()
144buildInterfaces lbi elmis = do
145 createDirectoryIfMissing True (rtsDir lbi)
146 let ifaces = interfaces lbi
147 ifaceHandle <- openBinaryFile ifaces WriteMode
148 BS.hPut ifaceHandle (Binary.encode (length elmis))
150 handle <- openBinaryFile file ReadMode
151 bits <- hGetContents handle
152 length bits `seq` hPutStr ifaceHandle bits
157buildRuntime :: LocalBuildInfo -> [FilePath] -> IO ()
158buildRuntime lbi elmos = do
159 createDirectoryIfMissing True (rtsDir lbi)
161 writeFile rts' "var Elm = {}; Elm.Native = {}; Elm.Native.Graphics = {};\n\
162 \var ElmRuntime = {}; ElmRuntime.Render = {};\n"
163 mapM_ (appendTo rts') =<< getFiles ".js" "libraries"
164 mapM_ (appendTo rts') elmos
165 mapM_ (appendTo rts') =<< getFiles ".js" "runtime"
167buildDocs :: LocalBuildInfo -> IO ()
169 createDirectoryIfMissing True (rtsDir lbi)
171 writeFile docs' "[\n"
172 json <- getFiles ".json" ("libraries" </> "docs")
173 let appends = map (appendTo docs') json
174 addCommas = List.intersperse (appendFile docs' ",\n")
175 sequence_ (addCommas appends)
176 appendFile docs' "\n]"
179 contents <- map (dir </>) `fmap` getDirectoryContents dir
180 let files = filter (\f -> takeExtension f == ext) contents
181 dirs = filter (not . hasExtension) contents
182 filess <- mapM (getFiles ext) dirs
183 return (files ++ concat filess)
185appendTo :: FilePath -> FilePath -> IO ()
186appendTo destination source = do
187 str <- readFile source
188 length str `seq` return ()
189 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