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
19-- We need to build elm-doc and run it because that generates the file "docs.json"
20-- needs by Libraries.hs which is part of the elm library and executable
21-- Unfort. there seems to be no way to tell cabal that:
22-- (a) elm-doc generates docs.json, and
23-- (b) elm (library) depends on docs.json
24-- Therefore, we either use make instead (or a script), or hack around in cabal
28-- Add a post-build callout.
29-- We need to build the runtime.js after we've built elm (because we use elm to generate some of the JavaScript),
30-- but before cabal does the install file copy step
33-- Elm.cabal expects the generated files to end up in dist/data
34-- git won't look in dist + cabal will clean it
35rtsDir :: LocalBuildInfo -> FilePath
38tempDir :: LocalBuildInfo -> FilePath
41-- The runtime is called:
42rts :: LocalBuildInfo -> FilePath
43rts lbi = rtsDir lbi </> "elm-runtime.js"
45-- The interfaces for the Standard Libraries live in:
46interfaces :: LocalBuildInfo -> FilePath
47interfaces lbi = rtsDir lbi </> "interfaces.data"
49-- buildDir with LocalBuildInfo points to "dist/build" (usually)
50elm lbi = buildDir lbi </> "elm" </> "elm"
52-- Care! This appears to be based on an unstable API
53-- See: http://www.haskell.org/cabal/release/cabal-latest/doc/API/Cabal/Distribution-Simple.html#2
57main = defaultMainWithHooks simpleUserHooks { postBuild = myPostBuild }
62-- note(1): We use to include docs.json directly into LoadLibraries at compile time
63-- If docs.json is used in other (template) haskell files, they should be copied
64-- and compiled in a separate directory (eg, dist/copiedSrc).
65-- This is to make sure they are re-compiled on docs.json changes.
66-- Copying is a better solution than 'touch'ing the source files
67-- (touch is non-portable and confusing wrt RCS).
69-- In the PackageDescription, the list of stuff to build is held in library
70-- (in a Maybe) and the executables list. We want a PackageDescription that
71-- only mentions the executable 'name'
72filterExe :: String -> PackageDescription -> PackageDescription
73filterExe name pd = pd {
75 executables = filter (\x -> (exeName x == name)) (executables pd)
78-- It's not enough to fix the PackageDescription, we also have to fix the
79-- LocalBuildInfo. This includes the component build order (data ComponentName)
80-- which is horribly internal.
81filterLBI :: String -> LocalBuildInfo -> LocalBuildInfo
82filterLBI name lbi = lbi {
83 libraryConfig = Nothing,
84 compBuildOrder = [CExeName name],
85 executableConfigs = filter (\a -> (fst a == name)) (executableConfigs lbi)
91myPostBuild :: Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
92myPostBuild as bfs pd lbi = do
93 putStrLn "Custom build step: compiling standard libraries"
94 (elmos, elmis) <- compileLibraries lbi
95 putStrLn "Custom build step: build interfaces.data"
96 buildInterfaces lbi elmis
97 putStrLn "Custom build step: build elm-runtime.js"
98 buildRuntime lbi elmos
99 removeDirectoryRecursive (tempDir lbi)
100 postBuild simpleUserHooks as bfs pd lbi
103compileLibraries lbi = do
104 let temp = tempDir lbi -- temp
105 rts = rtsDir lbi -- data
106 createDirectoryIfMissing True temp
107 createDirectoryIfMissing True rts
108 out_c <- canonicalizePath temp -- temp (root folder)
109 elm_c <- canonicalizePath (elm lbi) -- dist/build/elm/elm
110 rtd_c <- canonicalizePath rts -- data
113 -- replace 'system' call with 'runProcess' which handles args better
114 -- and allows env variable "Elm_datadir" which is used by LoadLibraries
116 let args = [ "--only-js", "--make", "--no-prelude"
117 , "--cache-dir="++out_c, "--build-dir="++out_c, file ]
118 arg = Just [("Elm_datadir", rtd_c)]
119 handle <- runProcess elm_c args Nothing arg Nothing Nothing Nothing
120 exitCode <- waitForProcess handle
121 return ( out_c </> replaceExtension file "elmo"
122 , out_c </> replaceExtension file "elmi")
124 setCurrentDirectory "libraries"
125 print =<< getCurrentDirectory
126 files <- getFiles ".elm" "."
127 files <- unzip `fmap` mapM make files
128 setCurrentDirectory ".."
131buildInterfaces :: LocalBuildInfo -> [FilePath] -> IO ()
132buildInterfaces lbi elmis = do
133 createDirectoryIfMissing True (rtsDir lbi)
134 let ifaces = interfaces lbi
135 ifaceHandle <- openBinaryFile ifaces WriteMode
136 BS.hPut ifaceHandle (Binary.encode (length elmis))
138 handle <- openBinaryFile file ReadMode
139 bits <- hGetContents handle
140 length bits `seq` hPutStr ifaceHandle bits
145buildRuntime :: LocalBuildInfo -> [FilePath] -> IO ()
146buildRuntime lbi elmos = do
147 createDirectoryIfMissing True (rtsDir lbi)
148 writeFile (rts lbi) "var Elm = {}; Elm.Native = {}; Elm.Native.Graphics = {};\n\
149 \var ElmRuntime = {}; ElmRuntime.Render = {};\n"
150 mapM_ (appendJS lbi) =<< getFiles ".js" "libraries"
151 mapM_ (appendJS lbi) elmos
152 mapM_ (appendJS lbi) =<< getFiles ".js" "runtime"
155 contents <- map (dir </>) `fmap` getDirectoryContents dir
156 let files = filter (\f -> takeExtension f == ext) contents
157 dirs = filter (not . hasExtension) contents
158 filess <- mapM (getFiles ext) dirs
159 return (files ++ concat filess)
161appendJS lbi file = do
162 putStrLn (dropExtension file)
164 length str `seq` return ()
165 appendFile (rts lbi) 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