Install.hs 11.9 KB
Newer Older
1
{-# LANGUAGE FlexibleContexts #-}
Zhen Zhang's avatar
Zhen Zhang committed
2
3
module Rules.Install (installRules) where

4
import Hadrian.Oracles.DirectoryContents
5
import qualified System.Directory as IO
6

Zhen Zhang's avatar
Zhen Zhang committed
7
8
import Base
import Context
9
import Expression hiding (builder)
Zhen Zhang's avatar
Zhen Zhang committed
10
import GHC
11
import Oracles.Setting
Zhen Zhang's avatar
Zhen Zhang committed
12
13
import Rules
import Rules.Generate
14
15
import Rules.Libffi
import Rules.Wrappers
16
import Settings
Zhen Zhang's avatar
Zhen Zhang committed
17
import Settings.Packages.Rts
18
19
import Settings.Path
import Target
20
import Utilities
Zhen Zhang's avatar
Zhen Zhang committed
21
22
23

{- | Install the built binaries etc. to the @destDir ++ prefix@.

Andrey Mokhov's avatar
Andrey Mokhov committed
24
25
26
27
The installation prefix is usually @/usr/local@ on a Unix system.
The resulting tree structure is organized under @destDir ++ prefix@ as follows:

* @bin@: executable wrapper scripts, installed by 'installBins', e.g. @ghc@.
Zhen Zhang's avatar
Zhen Zhang committed
28
29

* @lib/ghc-<version>/bin@: executable binaries/scripts,
Andrey Mokhov's avatar
Andrey Mokhov committed
30
31
32
33
34
35
36
37
38
  installed by 'installLibExecs' and 'installLibExecScripts'.

* @lib/ghc-<version>/include@: headers etc., installed by 'installIncludes'.

* @lib/ghc-<version>/<pkg-name>@: built packages, e.g. @base@, installed
  by 'installPackages'.

* @lib/ghc-<version>/settings@ etc.: other files in @lib@ directory,
  installed by 'installCommonLibs'.
Zhen Zhang's avatar
Zhen Zhang committed
39
40
41
42
43
44
45

XXX (izgzhen): Do we need @INSTALL_OPTS@ in the make scripts?
-}
installRules :: Rules ()
installRules = do
    "install" ~> do
        installIncludes
46
        installPackageConf
Zhen Zhang's avatar
Zhen Zhang committed
47
48
49
50
51
52
        installCommonLibs
        installLibExecs
        installLibExecScripts
        installBins
        installPackages

Andrey Mokhov's avatar
Andrey Mokhov committed
53
54
55
56
-- | Binaries to install.
installBinPkgs :: [Package]
installBinPkgs = [ghc, ghcPkg, ghcSplit, hp2ps, hpc, hsc2hs, runGhc, unlit]

Zhen Zhang's avatar
Zhen Zhang committed
57
58
59
60
getLibExecDir :: Action FilePath
getLibExecDir = (-/- "bin") <$> installGhcLibDir

-- ref: ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
61
-- | Install executable scripts to @prefix/lib/bin@.
Zhen Zhang's avatar
Zhen Zhang committed
62
63
64
installLibExecScripts :: Action ()
installLibExecScripts = do
    libExecDir <- getLibExecDir
65
    installDirectory (destDir ++ libExecDir)
Zhen Zhang's avatar
Zhen Zhang committed
66
67
68
69
    forM_ libExecScripts $ \script -> do
        installScript script (destDir ++ libExecDir)
  where
    libExecScripts :: [FilePath]
Andrey Mokhov's avatar
Andrey Mokhov committed
70
    libExecScripts = [ghcSplitPath]
Zhen Zhang's avatar
Zhen Zhang committed
71
72

-- ref: ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
73
-- | Install executable binaries to @prefix/lib/bin@.
Zhen Zhang's avatar
Zhen Zhang committed
74
75
76
installLibExecs :: Action ()
installLibExecs = do
    libExecDir <- getLibExecDir
77
    installDirectory (destDir ++ libExecDir)
Zhen Zhang's avatar
Zhen Zhang committed
78
    forM_ installBinPkgs $ \pkg -> do
Andrey Mokhov's avatar
Andrey Mokhov committed
79
80
81
        withLatestBuildStage pkg $ \stage -> do
            let context = programContext stage pkg
                bin     = inplaceLibBinPath -/- programName context <.> exe
Zhen Zhang's avatar
Zhen Zhang committed
82
83
84
85
86
87
            installProgram bin (destDir ++ libExecDir)
            when (pkg == ghc) $ do
                moveFile (destDir ++ libExecDir -/- programName context <.> exe)
                         (destDir ++ libExecDir -/- "ghc" <.> exe)

-- ref: ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
88
-- | Install executable wrapper scripts to @prefix/bin@.
Zhen Zhang's avatar
Zhen Zhang committed
89
90
91
installBins :: Action ()
installBins = do
    binDir <- setting InstallBinDir
Andrey Mokhov's avatar
Andrey Mokhov committed
92
    libDir <- installGhcLibDir
93
    installDirectory (destDir ++ binDir)
Andrey Mokhov's avatar
Andrey Mokhov committed
94
95
96
97
98
99
    win <- windowsHost
    when win $
        copyDirectoryContents matchAll (destDir ++ libDir -/- "bin") (destDir ++ binDir)
    unless win $ forM_ installBinPkgs $ \pkg ->
        withLatestBuildStage pkg $ \stage -> do
            let context = programContext stage pkg
Zhen Zhang's avatar
Zhen Zhang committed
100
            version <- setting ProjectVersion
Andrey Mokhov's avatar
Andrey Mokhov committed
101
            -- Name of the binary file
Zhen Zhang's avatar
Zhen Zhang committed
102
103
104
            let binName = if pkg == ghc
                          then "ghc-" ++ version <.> exe
                          else programName context ++ "-" ++ version <.> exe
Andrey Mokhov's avatar
Andrey Mokhov committed
105
            -- Name of the symbolic link
Zhen Zhang's avatar
Zhen Zhang committed
106
107
108
109
110
111
112
            let symName = if pkg == ghc
                          then "ghc" <.> exe
                          else programName context <.> exe
            case lookup context installWrappers of
                Nothing -> return ()
                Just wrapper -> do
                    contents <- interpretInContext context $
Andrey Mokhov's avatar
Andrey Mokhov committed
113
                        wrapper (WrappedBinary (destDir ++ libDir) symName)
114
115
116
                    let wrapperPath = destDir ++ binDir -/- binName
                    writeFileChanged wrapperPath contents
                    makeExecutable wrapperPath
Zhen Zhang's avatar
Zhen Zhang committed
117
118
119
120
121
122
                    unlessM windowsHost $
                        linkSymbolic (destDir ++ binDir -/- binName)
                                     (destDir ++ binDir -/- symName)

withLatestBuildStage :: Package -> (Stage -> Action ()) -> Action ()
withLatestBuildStage pkg m = do
Andrey Mokhov's avatar
Andrey Mokhov committed
123
124
125
126
  maybeStage <- latestBuildStage pkg
  case maybeStage of
      Just stage -> m stage
      Nothing    -> return ()
Zhen Zhang's avatar
Zhen Zhang committed
127
128

-- ref: rules/manual-package-conf.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
129
-- TODO: Should we use a temporary file instead of pkgConfInstallPath?
Andrey Mokhov's avatar
Andrey Mokhov committed
130
131
-- | Install @package.conf.install@ for each package. Note that it will be
-- recreated each time.
Zhen Zhang's avatar
Zhen Zhang committed
132
installPackageConf :: Action ()
133
installPackageConf = do
Zhen Zhang's avatar
Zhen Zhang committed
134
    let context = vanillaContext Stage0 rts
135
    liftIO $ IO.createDirectoryIfMissing True (takeDirectory pkgConfInstallPath)
136
    build $ target context HsCpp [ pkgPath rts -/- "package.conf.in" ]
Zhen Zhang's avatar
Zhen Zhang committed
137
                                 [ pkgConfInstallPath <.> "raw" ]
138
139
    Stdout content <- cmd "grep" [ "-v", "^#pragma GCC"
                                 , pkgConfInstallPath <.> "raw" ]
Zhen Zhang's avatar
Zhen Zhang committed
140
    withTempFile $ \tmp -> do
141
        liftIO $ writeFile tmp content
Andrey Mokhov's avatar
Andrey Mokhov committed
142
143
        Stdout result <- cmd "sed" [ "-e", "s/\"\"//g", "-e", "s/:[   ]*,/: /g", tmp ]
        liftIO $ writeFile pkgConfInstallPath result
Zhen Zhang's avatar
Zhen Zhang committed
144
145

-- ref: ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
146
-- | Install packages to @prefix/lib@.
Zhen Zhang's avatar
Zhen Zhang committed
147
148
installPackages :: Action ()
installPackages = do
Andrey Mokhov's avatar
Andrey Mokhov committed
149
    need [pkgConfInstallPath]
Zhen Zhang's avatar
Zhen Zhang committed
150
151

    ghcLibDir <- installGhcLibDir
Andrey Mokhov's avatar
Andrey Mokhov committed
152
    binDir    <- setting InstallBinDir
Zhen Zhang's avatar
Zhen Zhang committed
153
154
155

    -- Install package.conf
    let installedPackageConf = destDir ++ ghcLibDir -/- "package.conf.d"
156
    installDirectory (destDir ++ ghcLibDir)
Zhen Zhang's avatar
Zhen Zhang committed
157
    removeDirectory installedPackageConf
158
    installDirectory installedPackageConf
Zhen Zhang's avatar
Zhen Zhang committed
159
160
161

    -- Install RTS
    let rtsDir = destDir ++ ghcLibDir -/- "rts"
162
    installDirectory rtsDir
Andrey Mokhov's avatar
Andrey Mokhov committed
163
    ways    <- interpretInContext (vanillaContext Stage1 rts) getRtsWays
Zhen Zhang's avatar
Zhen Zhang committed
164
165
166
167
168
169
170
171
    rtsLibs <- mapM pkgLibraryFile $ map (Context Stage1 rts) ways
    ffiLibs <- sequence $ map rtsLibffiLibrary ways

    -- TODO: Add dynamic ones
    forM_ (rtsLibs ++ ffiLibs) $ \lib -> installData [lib] rtsDir

    -- HACK (issue #327)
    let ghcBootPlatformHeader =
Andrey Mokhov's avatar
Andrey Mokhov committed
172
            buildPath (vanillaContext Stage1 compiler) -/- "ghc_boot_platform.h"
Zhen Zhang's avatar
Zhen Zhang committed
173
174
175

    copyFile ghcBootPlatformHeader (pkgPath compiler -/- "ghc_boot_platform.h")

176
177
178
    activePackages <- filterM ((isJust <$>) . latestBuildStage)
                              (knownPackages \\ [rts, libffi])

179
    installLibPkgs <- topsortPackages (filter isLibrary activePackages)
Zhen Zhang's avatar
Zhen Zhang committed
180
181
182

    forM_ installLibPkgs $ \pkg@Package{..} -> do
        when (isLibrary pkg) $
Andrey Mokhov's avatar
Andrey Mokhov committed
183
184
            withLatestBuildStage pkg $ \stage -> do
                let context = vanillaContext stage pkg
Andrey Mokhov's avatar
Andrey Mokhov committed
185
                top <- topDirectory
Zhen Zhang's avatar
Zhen Zhang committed
186
                let installDistDir = top -/- buildPath context
187
                need =<< packageTargets stage pkg
Zhen Zhang's avatar
Zhen Zhang committed
188
189
                docDir <- installDocDir
                ghclibDir <- installGhcLibDir
190

Zhen Zhang's avatar
Zhen Zhang committed
191
                -- Copy over packages
Andrey Mokhov's avatar
Andrey Mokhov committed
192
                strip <- stripCmdPath
Andrey Mokhov's avatar
Andrey Mokhov committed
193
194
195
                ways  <- interpretInContext context getLibraryWays
                let ghcCabalInplace = inplaceBinPath -/- "ghc-cabal" <.> exe -- HACK?
                need [ghcCabalInplace]
Zhen Zhang's avatar
Zhen Zhang committed
196

Zhen Zhang's avatar
Zhen Zhang committed
197
198
199
                let cabalFile = pkgCabalFile pkg

                pkgConf <- pkgConfFile context
Andrey Mokhov's avatar
Andrey Mokhov committed
200
                need [cabalFile, pkgConf] -- TODO: check if need pkgConf
Zhen Zhang's avatar
Zhen Zhang committed
201

Zhen Zhang's avatar
Zhen Zhang committed
202
203
                -- HACK (#318): copy stuff back to the place favored by ghc-cabal
                quietly $ copyDirectoryContents (Not excluded)
Andrey Mokhov's avatar
Andrey Mokhov committed
204
                    installDistDir (installDistDir -/- "build")
Zhen Zhang's avatar
Zhen Zhang committed
205
206

                whenM (isSpecified HsColour) $
207
                    build $ target context GhcCabalHsColour [cabalFile] []
Zhen Zhang's avatar
Zhen Zhang committed
208

Zhen Zhang's avatar
Zhen Zhang committed
209
                pref <- setting InstallPrefix
Andrey Mokhov's avatar
Andrey Mokhov committed
210
211
212
213
214
215
216
217
218
                unit $ cmd ghcCabalInplace [ "copy"
                                           , pkgPath
                                           , installDistDir
                                           , strip
                                           , destDir
                                           , pref
                                           , ghclibDir
                                           , docDir -/- "html/libraries"
                                           , intercalate " " (map show ways) ]
Zhen Zhang's avatar
Zhen Zhang committed
219
220
221

    -- Register packages
    let installedGhcPkgReal = destDir ++ binDir -/- "ghc-pkg" <.> exe
Andrey Mokhov's avatar
Andrey Mokhov committed
222
        installedGhcReal    = destDir ++ binDir -/- "ghc"     <.> exe
Zhen Zhang's avatar
Zhen Zhang committed
223
    -- TODO: Extend GhcPkg builder args to support --global-package-db
Andrey Mokhov's avatar
Andrey Mokhov committed
224
225
226
    unit $ cmd installedGhcPkgReal [ "--force", "--global-package-db"
                                   , installedPackageConf, "update"
                                   , pkgConfInstallPath ]
Zhen Zhang's avatar
Zhen Zhang committed
227
228
229

    forM_ installLibPkgs $ \pkg@Package{..} -> do
        when (isLibrary pkg) $
Andrey Mokhov's avatar
Andrey Mokhov committed
230
231
            withLatestBuildStage pkg $ \stage -> do
                let context = vanillaContext stage pkg
Andrey Mokhov's avatar
Andrey Mokhov committed
232
                top <- topDirectory
Zhen Zhang's avatar
Zhen Zhang committed
233
234
235
                let installDistDir = top -/- buildPath context
                -- TODO: better reference to the built inplace binary path
                let ghcCabalInplace = inplaceBinPath -/- "ghc-cabal"
Andrey Mokhov's avatar
Andrey Mokhov committed
236
                pref   <- setting InstallPrefix
Zhen Zhang's avatar
Zhen Zhang committed
237
                docDir <- installDocDir
Andrey Mokhov's avatar
Andrey Mokhov committed
238
                r      <- relocatableBuild
Zhen Zhang's avatar
Zhen Zhang committed
239
                unit $ cmd ghcCabalInplace
Andrey Mokhov's avatar
Andrey Mokhov committed
240
241
242
243
244
245
246
247
248
249
250
                    [ "register"
                    , pkgPath
                    , installDistDir
                    , installedGhcReal
                    , installedGhcPkgReal
                    , destDir ++ ghcLibDir
                    , destDir
                    , destDir ++ pref
                    , destDir ++ ghcLibDir
                    , destDir ++ docDir -/- "html/libraries"
                    , if r then "YES" else "NO" ]
Zhen Zhang's avatar
Zhen Zhang committed
251
252
253

    confs <- getDirectoryContents installedPackageConf
    forM_ confs (\f -> createData $ installedPackageConf -/- f)
Andrey Mokhov's avatar
Andrey Mokhov committed
254
255
    unit $ cmd installedGhcPkgReal [ "--force", "--global-package-db"
                                   , installedPackageConf, "recache" ]
Zhen Zhang's avatar
Zhen Zhang committed
256
  where
257
    createData f = unit $ cmd "chmod" [ "644", f ]
Andrey Mokhov's avatar
Andrey Mokhov committed
258
259
260
261
262
263
    excluded = Or [ Test "//haddock-prologue.txt"
                  , Test "//package-data.mk"
                  , Test "//setup-config"
                  , Test "//inplace-pkg-config"
                  , Test "//build" ]

Zhen Zhang's avatar
Zhen Zhang committed
264
-- ref: ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
265
-- | Install settings etc. files to @prefix/lib@.
Zhen Zhang's avatar
Zhen Zhang committed
266
267
268
269
270
271
installCommonLibs :: Action ()
installCommonLibs = do
    ghcLibDir <- installGhcLibDir
    installLibsTo inplaceLibCopyTargets (destDir ++ ghcLibDir)

-- ref: ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
272
-- | Install library files to some path.
Zhen Zhang's avatar
Zhen Zhang committed
273
274
installLibsTo :: [FilePath] -> FilePath -> Action ()
installLibsTo libs dir = do
275
    installDirectory dir
Zhen Zhang's avatar
Zhen Zhang committed
276
277
278
279
280
281
282
    forM_ libs $ \lib -> do
       case takeExtension lib of
           ".a" -> do
               let out = dir -/- takeFileName lib
               installData [out] dir
               let context = vanillaContext Stage0 $ topLevel (PackageName "")
               -- TODO: Get rid of meaningless context for certain builder like ranlib
283
               build $ target context Ranlib [out] [out]
Zhen Zhang's avatar
Zhen Zhang committed
284
285
286
           _ -> installData [lib] dir

-- ref: includes/ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
287
-- | All header files are in includes/{one of these subdirectories}.
Zhen Zhang's avatar
Zhen Zhang committed
288
includeHSubdirs :: [FilePath]
Andrey Mokhov's avatar
Andrey Mokhov committed
289
includeHSubdirs = [".", "rts", "rts/prof", "rts/storage", "stg"]
Zhen Zhang's avatar
Zhen Zhang committed
290
291

-- ref: includes/ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
292
-- | Install header files to @prefix/lib/ghc-<version>/include@.
Zhen Zhang's avatar
Zhen Zhang committed
293
294
295
296
installIncludes ::Action ()
installIncludes = do
    ghclibDir <- installGhcLibDir
    let ghcheaderDir = ghclibDir -/- "include"
297
    installDirectory (destDir ++ ghcheaderDir)
Andrey Mokhov's avatar
Andrey Mokhov committed
298
299
300
301
302
    forM_ includeHSubdirs $ \dir -> do
        installDirectory (destDir ++ ghcheaderDir -/- dir)
        headers <- getDirectoryFiles ("includes" -/- dir) ["*.h"]
        installHeader (map (("includes" -/- dir) -/-) headers)
                      (destDir ++ ghcheaderDir -/- dir ++ "/")
Zhen Zhang's avatar
Zhen Zhang committed
303
304
305
306
307
308
    installHeader (includesDependencies ++
                   [generatedPath -/- "DerivedConstants.h"] ++
                   libffiDependencies)
                  (destDir ++ ghcheaderDir ++ "/")
  where
    installHeader = installData -- they share same arguments