Install rule: copy gmp header (#398)
[ghc.git] / src / Rules / Install.hs
1 module Rules.Install (installRules) where
2
3 import Hadrian.Oracles.DirectoryContents
4 import qualified System.Directory as IO
5
6 import Base
7 import Context
8 import Expression
9 import GHC
10 import Oracles.Setting
11 import Rules
12 import Rules.Generate
13 import Rules.Libffi
14 import Rules.Wrappers
15 import Settings
16 import Settings.Packages.Rts
17 import Target
18 import Utilities
19
20 {- | Install the built binaries etc. to the @destDir ++ prefix@.
21
22 The installation prefix is usually @/usr/local@ on a Unix system.
23 The resulting tree structure is organized under @destDir ++ prefix@ as follows:
24
25 * @bin@: executable wrapper scripts, installed by 'installBins', e.g. @ghc@.
26
27 * @lib/ghc-<version>/bin@: executable binaries/scripts,
28 installed by 'installLibExecs' and 'installLibExecScripts'.
29
30 * @lib/ghc-<version>/include@: headers etc., installed by 'installIncludes'.
31
32 * @lib/ghc-<version>/<pkg-name>@: built packages, e.g. @base@, installed
33 by 'installPackages'.
34
35 * @lib/ghc-<version>/settings@ etc.: other files in @lib@ directory,
36 installed by 'installCommonLibs'.
37
38 XXX (izgzhen): Do we need @INSTALL_OPTS@ in the make scripts?
39 -}
40 installRules :: Rules ()
41 installRules = do
42 "install" ~> do
43 installIncludes
44 installPackageConf
45 installCommonLibs
46 installLibExecs
47 installLibExecScripts
48 installBins
49 installPackages
50
51 -- | Binaries to install.
52 installBinPkgs :: [Package]
53 installBinPkgs = [ghc, ghcPkg, ghcSplit, hp2ps, hpc, hsc2hs, runGhc, unlit]
54
55 getLibExecDir :: Action FilePath
56 getLibExecDir = (-/- "bin") <$> installGhcLibDir
57
58 -- ref: ghc.mk
59 -- | Install executable scripts to @prefix/lib/bin@.
60 installLibExecScripts :: Action ()
61 installLibExecScripts = do
62 libExecDir <- getLibExecDir
63 destDir <- getDestDir
64 installDirectory (destDir ++ libExecDir)
65 forM_ libExecScripts $ \script -> do
66 installScript script (destDir ++ libExecDir)
67 where
68 libExecScripts :: [FilePath]
69 libExecScripts = [ghcSplitPath]
70
71 -- ref: ghc.mk
72 -- | Install executable binaries to @prefix/lib/bin@.
73 installLibExecs :: Action ()
74 installLibExecs = do
75 libExecDir <- getLibExecDir
76 destDir <- getDestDir
77 installDirectory (destDir ++ libExecDir)
78 forM_ installBinPkgs $ \pkg -> do
79 withLatestBuildStage pkg $ \stage -> do
80 context <- programContext stage pkg
81 let bin = inplaceLibBinPath -/- programName context <.> exe
82 installProgram bin (destDir ++ libExecDir)
83 when (pkg == ghc) $ do
84 moveFile (destDir ++ libExecDir -/- programName context <.> exe)
85 (destDir ++ libExecDir -/- "ghc" <.> exe)
86
87 -- ref: ghc.mk
88 -- | Install executable wrapper scripts to @prefix/bin@.
89 installBins :: Action ()
90 installBins = do
91 binDir <- setting InstallBinDir
92 libDir <- installGhcLibDir
93 destDir <- getDestDir
94 installDirectory (destDir ++ binDir)
95 win <- windowsHost
96 when win $
97 copyDirectoryContents matchAll (destDir ++ libDir -/- "bin") (destDir ++ binDir)
98 unless win $ forM_ installBinPkgs $ \pkg ->
99 withLatestBuildStage pkg $ \stage -> do
100 context <- programContext stage pkg
101 version <- setting ProjectVersion
102 -- Name of the binary file
103 let binName = if pkg == ghc
104 then "ghc-" ++ version <.> exe
105 else programName context ++ "-" ++ version <.> exe
106 -- Name of the symbolic link
107 let symName = if pkg == ghc
108 then "ghc" <.> exe
109 else programName context <.> exe
110 case lookup context installWrappers of
111 Nothing -> return ()
112 Just wrapper -> do
113 contents <- interpretInContext context $
114 wrapper (WrappedBinary (destDir ++ libDir) symName)
115 let wrapperPath = destDir ++ binDir -/- binName
116 writeFileChanged wrapperPath contents
117 makeExecutable wrapperPath
118 unlessM windowsHost $
119 linkSymbolic (destDir ++ binDir -/- binName)
120 (destDir ++ binDir -/- symName)
121
122 withLatestBuildStage :: Package -> (Stage -> Action ()) -> Action ()
123 withLatestBuildStage pkg m = do
124 maybeStage <- latestBuildStage pkg
125 case maybeStage of
126 Just stage -> m stage
127 Nothing -> return ()
128
129 pkgConfInstallPath :: Action FilePath
130 pkgConfInstallPath = buildPath (vanillaContext Stage0 rts) <&> (-/- "package.conf.install")
131
132 -- ref: rules/manual-package-conf.mk
133 -- TODO: Should we use a temporary file instead of pkgConfInstallPath?
134 -- | Install @package.conf.install@ for each package. Note that it will be
135 -- recreated each time.
136 installPackageConf :: Action ()
137 installPackageConf = do
138 let context = vanillaContext Stage0 rts
139 confPath <- pkgConfInstallPath
140 liftIO $ IO.createDirectoryIfMissing True (takeDirectory confPath)
141 build $ target context HsCpp [ pkgPath rts -/- "package.conf.in" ]
142 [ confPath <.> "raw" ]
143 Stdout content <- cmd "grep" [ "-v", "^#pragma GCC"
144 , confPath <.> "raw" ]
145 withTempFile $ \tmp -> do
146 liftIO $ writeFile tmp content
147 Stdout result <- cmd "sed" [ "-e", "s/\"\"//g", "-e", "s/:[ ]*,/: /g", tmp ]
148 liftIO $ writeFile confPath result
149
150 -- ref: ghc.mk
151 -- | Install packages to @prefix/lib@.
152 installPackages :: Action ()
153 installPackages = do
154 confPath <- pkgConfInstallPath
155 need [confPath]
156
157 ghcLibDir <- installGhcLibDir
158 binDir <- setting InstallBinDir
159 destDir <- getDestDir
160
161 -- Install package.conf
162 let installedPackageConf = destDir ++ ghcLibDir -/- "package.conf.d"
163 installDirectory (destDir ++ ghcLibDir)
164 removeDirectory installedPackageConf
165 installDirectory installedPackageConf
166
167 -- Install RTS
168 let rtsDir = destDir ++ ghcLibDir -/- "rts"
169 installDirectory rtsDir
170 ways <- interpretInContext (vanillaContext Stage1 rts) getRtsWays
171 rtsLibs <- mapM pkgLibraryFile $ map (Context Stage1 rts) ways
172 ffiLibs <- sequence $ map rtsLibffiLibrary ways
173
174 -- TODO: Add dynamic ones
175 forM_ (rtsLibs ++ ffiLibs) $ \lib -> installData [lib] rtsDir
176
177 -- HACK (issue #327)
178 ghcBootPlatformHeader <-
179 buildPath (vanillaContext Stage1 compiler) <&> (-/- "ghc_boot_platform.h")
180
181 copyFile ghcBootPlatformHeader (pkgPath compiler -/- "ghc_boot_platform.h")
182
183 activePackages <- filterM ((isJust <$>) . latestBuildStage)
184 (knownPackages \\ [rts, libffi])
185
186 installLibPkgs <- topsortPackages (filter isLibrary activePackages)
187
188 -- TODO (izgzhen): figure out what is the root cause of the missing ghc-gmp.h error
189 copyFile (pkgPath integerGmp -/- "gmp/ghc-gmp.h") (pkgPath integerGmp -/- "ghc-gmp.h")
190
191 forM_ installLibPkgs $ \pkg -> do
192 when (isLibrary pkg) $
193 withLatestBuildStage pkg $ \stage -> do
194 let context = vanillaContext stage pkg
195 top <- topDirectory
196 installDistDir <- buildPath context
197 let absInstallDistDir = top -/- installDistDir
198
199 need =<< packageTargets True stage pkg
200 docDir <- installDocDir
201 ghclibDir <- installGhcLibDir
202
203 -- Copy over packages
204 strip <- stripCmdPath
205 ways <- interpretInContext context getLibraryWays
206 let ghcCabalInplace = inplaceBinPath -/- "ghc-cabal" <.> exe -- HACK?
207 need [ghcCabalInplace]
208
209 let cabalFile = pkgCabalFile pkg
210
211 pkgConf <- pkgConfFile context
212 need [cabalFile, pkgConf] -- TODO: check if need pkgConf
213
214 -- HACK (#318): copy stuff back to the place favored by ghc-cabal
215 quietly $ copyDirectoryContentsUntracked (Not excluded)
216 installDistDir (installDistDir -/- "build")
217
218 whenM (isSpecified HsColour) $
219 build $ target context GhcCabalHsColour [cabalFile] []
220
221 pref <- setting InstallPrefix
222 unit $ cmd ghcCabalInplace [ "copy"
223 , pkgPath pkg
224 , absInstallDistDir
225 , strip
226 , destDir
227 , pref
228 , ghclibDir
229 , docDir -/- "html/libraries"
230 , intercalate " " (map show ways) ]
231
232 -- Register packages
233 let installedGhcPkgReal = destDir ++ binDir -/- "ghc-pkg" <.> exe
234 installedGhcReal = destDir ++ binDir -/- "ghc" <.> exe
235 -- TODO: Extend GhcPkg builder args to support --global-package-db
236 unit $ cmd installedGhcPkgReal [ "--force", "--global-package-db"
237 , installedPackageConf, "update"
238 , confPath ]
239
240 forM_ installLibPkgs $ \pkg -> do
241 when (isLibrary pkg) $
242 withLatestBuildStage pkg $ \stage -> do
243 let context = vanillaContext stage pkg
244 top <- topDirectory
245 installDistDir <- (top -/-) <$> buildPath context
246 -- TODO: better reference to the built inplace binary path
247 let ghcCabalInplace = inplaceBinPath -/- "ghc-cabal"
248 pref <- setting InstallPrefix
249 docDir <- installDocDir
250 r <- relocatableBuild
251 unit $ cmd ghcCabalInplace
252 [ "register"
253 , pkgPath pkg
254 , installDistDir
255 , installedGhcReal
256 , installedGhcPkgReal
257 , destDir ++ ghcLibDir
258 , destDir
259 , destDir ++ pref
260 , destDir ++ ghcLibDir
261 , destDir ++ docDir -/- "html/libraries"
262 , if r then "YES" else "NO" ]
263
264 confs <- getDirectoryContents installedPackageConf
265 forM_ confs (\f -> createData $ installedPackageConf -/- f)
266 unit $ cmd installedGhcPkgReal [ "--force", "--global-package-db"
267 , installedPackageConf, "recache" ]
268 where
269 createData f = unit $ cmd "chmod" [ "644", f ]
270 excluded = Or [ Test "//haddock-prologue.txt"
271 , Test "//package-data.mk"
272 , Test "//setup-config"
273 , Test "//inplace-pkg-config"
274 , Test "//build" ]
275
276 -- ref: ghc.mk
277 -- | Install settings etc. files to @prefix/lib@.
278 installCommonLibs :: Action ()
279 installCommonLibs = do
280 ghcLibDir <- installGhcLibDir
281 destDir <- getDestDir
282 installLibsTo inplaceLibCopyTargets (destDir ++ ghcLibDir)
283
284 -- ref: ghc.mk
285 -- | Install library files to some path.
286 installLibsTo :: [FilePath] -> FilePath -> Action ()
287 installLibsTo libs dir = do
288 installDirectory dir
289 forM_ libs $ \lib -> do
290 case takeExtension lib of
291 ".a" -> do
292 let out = dir -/- takeFileName lib
293 installData [out] dir
294 runBuilder Ranlib [out]
295 _ -> installData [lib] dir
296
297 -- ref: includes/ghc.mk
298 -- | All header files are in includes/{one of these subdirectories}.
299 includeHSubdirs :: [FilePath]
300 includeHSubdirs = [".", "rts", "rts/prof", "rts/storage", "stg"]
301
302 -- ref: includes/ghc.mk
303 -- | Install header files to @prefix/lib/ghc-<version>/include@.
304 installIncludes :: Action ()
305 installIncludes = do
306 ghclibDir <- installGhcLibDir
307 destDir <- getDestDir
308 let ghcheaderDir = ghclibDir -/- "include"
309 installDirectory (destDir ++ ghcheaderDir)
310 forM_ includeHSubdirs $ \dir -> do
311 installDirectory (destDir ++ ghcheaderDir -/- dir)
312 headers <- getDirectoryFiles ("includes" -/- dir) ["*.h"]
313 installHeader (map (("includes" -/- dir) -/-) headers)
314 (destDir ++ ghcheaderDir -/- dir ++ "/")
315 root <- buildRoot
316 rtsPath <- rtsBuildPath
317 installHeader (fmap (root -/-) includesDependencies ++
318 [root -/- generatedDir -/- "DerivedConstants.h"] ++
319 fmap (rtsPath -/-) libffiDependencies)
320 (destDir ++ ghcheaderDir ++ "/")
321 where
322 installHeader = installData -- they share same arguments