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

4 5
import Hadrian.Oracles.DirectoryContents

Zhen Zhang's avatar
Zhen Zhang committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19
import Base
import Target
import Context
import Predicate hiding (builder)
import Settings
import Settings.Path
import Util
import GHC
import Rules
import Rules.Wrappers (WrappedBinary(..), installWrappers)
import Rules.Libffi
import Rules.Generate
import Settings.Packages.Rts
import Oracles.Config.Setting
20
import Oracles.Dependencies
Zhen Zhang's avatar
Zhen Zhang committed
21 22
import Oracles.Path

23
import qualified System.Directory as IO
Zhen Zhang's avatar
Zhen Zhang committed
24 25 26

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

Andrey Mokhov's avatar
Andrey Mokhov committed
27 28 29 30
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
31 32

* @lib/ghc-<version>/bin@: executable binaries/scripts,
Andrey Mokhov's avatar
Andrey Mokhov committed
33 34 35 36 37 38 39 40 41
  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
42 43 44 45 46 47 48

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

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

Zhen Zhang's avatar
Zhen Zhang committed
60 61 62 63
getLibExecDir :: Action FilePath
getLibExecDir = (-/- "bin") <$> installGhcLibDir

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

-- ref: ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
76
-- | Install executable binaries to @prefix/lib/bin@.
Zhen Zhang's avatar
Zhen Zhang committed
77 78 79
installLibExecs :: Action ()
installLibExecs = do
    libExecDir <- getLibExecDir
80
    installDirectory (destDir ++ libExecDir)
Zhen Zhang's avatar
Zhen Zhang committed
81
    forM_ installBinPkgs $ \pkg -> do
Andrey Mokhov's avatar
Andrey Mokhov committed
82 83 84
        withLatestBuildStage pkg $ \stage -> do
            let context = programContext stage pkg
                bin     = inplaceLibBinPath -/- programName context <.> exe
Zhen Zhang's avatar
Zhen Zhang committed
85 86 87 88 89 90
            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
91
-- | Install executable wrapper scripts to @prefix/bin@.
Zhen Zhang's avatar
Zhen Zhang committed
92 93 94
installBins :: Action ()
installBins = do
    binDir <- setting InstallBinDir
Andrey Mokhov's avatar
Andrey Mokhov committed
95
    libDir <- installGhcLibDir
96
    installDirectory (destDir ++ binDir)
Andrey Mokhov's avatar
Andrey Mokhov committed
97 98 99 100 101 102
    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
103
            version <- setting ProjectVersion
Andrey Mokhov's avatar
Andrey Mokhov committed
104
            -- Name of the binary file
Zhen Zhang's avatar
Zhen Zhang committed
105 106 107
            let binName = if pkg == ghc
                          then "ghc-" ++ version <.> exe
                          else programName context ++ "-" ++ version <.> exe
Andrey Mokhov's avatar
Andrey Mokhov committed
108
            -- Name of the symbolic link
Zhen Zhang's avatar
Zhen Zhang committed
109 110 111 112 113 114 115
            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
116
                        wrapper (WrappedBinary (destDir ++ libDir) symName)
117 118 119
                    let wrapperPath = destDir ++ binDir -/- binName
                    writeFileChanged wrapperPath contents
                    makeExecutable wrapperPath
Zhen Zhang's avatar
Zhen Zhang committed
120 121 122 123 124 125
                    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
126 127 128 129
  maybeStage <- latestBuildStage pkg
  case maybeStage of
      Just stage -> m stage
      Nothing    -> return ()
Zhen Zhang's avatar
Zhen Zhang committed
130 131

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

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

    ghcLibDir <- installGhcLibDir
Andrey Mokhov's avatar
Andrey Mokhov committed
155
    binDir    <- setting InstallBinDir
Zhen Zhang's avatar
Zhen Zhang committed
156 157 158

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

    -- Install RTS
    let rtsDir = destDir ++ ghcLibDir -/- "rts"
165
    installDirectory rtsDir
Andrey Mokhov's avatar
Andrey Mokhov committed
166
    ways    <- interpretInContext (vanillaContext Stage1 rts) getRtsWays
Zhen Zhang's avatar
Zhen Zhang committed
167 168 169 170 171 172 173 174
    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
175
            buildPath (vanillaContext Stage1 compiler) -/- "ghc_boot_platform.h"
Zhen Zhang's avatar
Zhen Zhang committed
176 177 178

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

179 180 181
    activePackages <- filterM ((isJust <$>) . latestBuildStage)
                              (knownPackages \\ [rts, libffi])

182
    installLibPkgs <- topsortPackages (filter isLibrary activePackages)
Zhen Zhang's avatar
Zhen Zhang committed
183 184 185

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

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

Zhen Zhang's avatar
Zhen Zhang committed
200 201 202
                let cabalFile = pkgCabalFile pkg

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

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

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

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

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

    forM_ installLibPkgs $ \pkg@Package{..} -> do
        when (isLibrary pkg) $
Andrey Mokhov's avatar
Andrey Mokhov committed
233 234
            withLatestBuildStage pkg $ \stage -> do
                let context = vanillaContext stage pkg
Andrey Mokhov's avatar
Andrey Mokhov committed
235
                top <- topDirectory
Zhen Zhang's avatar
Zhen Zhang committed
236 237 238
                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
239
                pref   <- setting InstallPrefix
Zhen Zhang's avatar
Zhen Zhang committed
240
                docDir <- installDocDir
Andrey Mokhov's avatar
Andrey Mokhov committed
241
                r      <- relocatableBuild
Zhen Zhang's avatar
Zhen Zhang committed
242
                unit $ cmd ghcCabalInplace
Andrey Mokhov's avatar
Andrey Mokhov committed
243 244 245 246 247 248 249 250 251 252 253
                    [ "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
254 255 256

    confs <- getDirectoryContents installedPackageConf
    forM_ confs (\f -> createData $ installedPackageConf -/- f)
Andrey Mokhov's avatar
Andrey Mokhov committed
257 258
    unit $ cmd installedGhcPkgReal [ "--force", "--global-package-db"
                                   , installedPackageConf, "recache" ]
Zhen Zhang's avatar
Zhen Zhang committed
259
  where
260
    createData f = unit $ cmd "chmod" [ "644", f ]
Andrey Mokhov's avatar
Andrey Mokhov committed
261 262 263 264 265 266
    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
267
-- ref: ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
268
-- | Install settings etc. files to @prefix/lib@.
Zhen Zhang's avatar
Zhen Zhang committed
269 270 271 272 273 274
installCommonLibs :: Action ()
installCommonLibs = do
    ghcLibDir <- installGhcLibDir
    installLibsTo inplaceLibCopyTargets (destDir ++ ghcLibDir)

-- ref: ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
275
-- | Install library files to some path.
Zhen Zhang's avatar
Zhen Zhang committed
276 277
installLibsTo :: [FilePath] -> FilePath -> Action ()
installLibsTo libs dir = do
278
    installDirectory dir
Zhen Zhang's avatar
Zhen Zhang committed
279 280 281 282 283 284 285
    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
286
               build $ target context Ranlib [out] [out]
Zhen Zhang's avatar
Zhen Zhang committed
287 288 289
           _ -> installData [lib] dir

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

-- ref: includes/ghc.mk
Andrey Mokhov's avatar
Andrey Mokhov committed
295
-- | Install header files to @prefix/lib/ghc-<version>/include@.
Zhen Zhang's avatar
Zhen Zhang committed
296 297 298 299
installIncludes ::Action ()
installIncludes = do
    ghclibDir <- installGhcLibDir
    let ghcheaderDir = ghclibDir -/- "include"
300
    installDirectory (destDir ++ ghcheaderDir)
Andrey Mokhov's avatar
Andrey Mokhov committed
301 302 303 304 305
    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
306 307 308 309 310 311
    installHeader (includesDependencies ++
                   [generatedPath -/- "DerivedConstants.h"] ++
                   libffiDependencies)
                  (destDir ++ ghcheaderDir ++ "/")
  where
    installHeader = installData -- they share same arguments