Configure.hs 78.3 KB
Newer Older
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
1
{-# LANGUAGE CPP                #-}
2
{-# LANGUAGE DeriveDataTypeable #-}
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
3 4
{-# LANGUAGE OverloadedStrings  #-}
{-# LANGUAGE RecordWildCards    #-}
5

6 7
-----------------------------------------------------------------------------
-- |
ijones's avatar
ijones committed
8
-- Module      :  Distribution.Simple.Configure
9
-- Copyright   :  Isaac Jones 2003-2005
10
-- License     :  BSD3
11
--
Duncan Coutts's avatar
Duncan Coutts committed
12
-- Maintainer  :  cabal-devel@haskell.org
ijones's avatar
ijones committed
13
-- Portability :  portable
14
--
Duncan Coutts's avatar
Duncan Coutts committed
15 16 17 18 19 20 21 22
-- This deals with the /configure/ phase. It provides the 'configure' action
-- which is given the package description and configure flags. It then tries
-- to: configure the compiler; resolves any conditionals in the package
-- description; resolve the package dependencies; check if all the extensions
-- used by this package are supported by the compiler; check that all the build
-- tools are available (including version checks if appropriate); checks for
-- any required @pkg-config@ packages (updating the 'BuildInfo' with the
-- results)
23
--
Duncan Coutts's avatar
Duncan Coutts committed
24 25 26 27
-- Then based on all this it saves the info in the 'LocalBuildInfo' and writes
-- it out to the @dist\/setup-config@ file. It also displays various details to
-- the user, the amount of information displayed depending on the verbosity
-- level.
28

ijones's avatar
ijones committed
29 30
module Distribution.Simple.Configure (configure,
                                      writePersistBuildConfig,
31
                                      getConfigStateFile,
ijones's avatar
ijones committed
32
                                      getPersistBuildConfig,
33
                                      checkPersistBuildConfigOutdated,
34
                                      tryGetPersistBuildConfig,
35
                                      maybeGetPersistBuildConfig,
ijones's avatar
ijones committed
36
                                      localBuildInfoFile,
37
                                      getInstalledPackages, getPackageDBContents,
38
                                      configCompiler, configCompilerAux,
39
                                      configCompilerEx, configCompilerAuxEx,
40
                                      ccLdOptionsBuildInfo,
41
                                      checkForeignDeps,
42
                                      interpretPackageDbFlags,
43
                                      ConfigStateFileError(..),
44
                                      tryGetConfigStateFile,
45
                                      platformDefines,
ijones's avatar
ijones committed
46
                                     )
ijones's avatar
ijones committed
47
    where
48

49 50
import Distribution.Compiler
    ( CompilerId(..) )
51
import Distribution.Utils.NubList
52
import Distribution.Simple.Compiler
53
    ( CompilerFlavor(..), Compiler(..), compilerFlavor, compilerVersion
54
    , compilerInfo
55
    , showCompilerId, unsupportedLanguages, unsupportedExtensions
56
    , PackageDB(..), PackageDBStack, reexportedModulesSupported
57
    , packageKeySupported, renamingPackageFlagsSupported )
58
import Distribution.Simple.PreProcess ( platformDefines )
59
import Distribution.Package
60
    ( PackageName(PackageName), PackageIdentifier(..), PackageId
61
    , packageName, packageVersion, Package(..)
62
    , Dependency(Dependency), simplifyDependency
63
    , InstalledPackageId(..), thisPackageVersion
64
    , mkPackageKey, PackageKey(..), packageKeyLibraryName )
65
import qualified Distribution.InstalledPackageInfo as Installed
66
import Distribution.InstalledPackageInfo (InstalledPackageInfo, emptyInstalledPackageInfo)
67
import qualified Distribution.Simple.PackageIndex as PackageIndex
68
import Distribution.Simple.PackageIndex (InstalledPackageIndex)
69
import Distribution.PackageDescription as PD
70
    ( PackageDescription(..), specVersion, GenericPackageDescription(..)
71
    , Library(..), hasLibs, Executable(..), BuildInfo(..), allExtensions
72
    , HookedBuildInfo, updatePackageDescription, allBuildInfo
73
    , Flag(flagName), FlagName(..), TestSuite(..), Benchmark(..)
74
    , ModuleReexport(..) , defaultRenaming )
75 76
import Distribution.ModuleName
    ( ModuleName )
77
import Distribution.PackageDescription.Configuration
78
    ( finalizePackageDescription, mapTreeData )
79
import Distribution.PackageDescription.Check
80
    ( PackageCheck(..), checkPackage, checkPackageFiles )
81
import Distribution.Simple.Program
82
    ( Program(..), ProgramLocation(..), ConfiguredProgram(..)
Duncan Coutts's avatar
Duncan Coutts committed
83
    , ProgramConfiguration, defaultProgramConfiguration
84
    , ProgramSearchPathEntry(..), getProgramSearchPath, setProgramSearchPath
85
    , configureAllKnownPrograms, knownPrograms, lookupKnownProgram
86
    , userSpecifyArgss, userSpecifyPaths
87
    , lookupProgram, requireProgram, requireProgramVersion
88
    , pkgConfigProgram, gccProgram, rawSystemProgramStdoutConf )
89
import Distribution.Simple.Setup
90 91
    ( ConfigFlags(..), CopyDest(..), Flag(..), fromFlag, fromFlagOrDefault
    , flagToMaybe )
92
import Distribution.Simple.InstallDirs
93
    ( InstallDirs(..), defaultInstallDirs, combineInstallDirs )
94
import Distribution.Simple.LocalBuildInfo
95 96
    ( LocalBuildInfo(..), Component(..), ComponentLocalBuildInfo(..)
    , LibraryName(..)
97
    , absoluteInstallDirs, prefixRelativeInstallDirs, inplacePackageId
98 99
    , ComponentName(..), showComponentName, pkgEnabledComponents
    , componentBuildInfo, componentName, checkComponentsCyclic )
100 101
import Distribution.Simple.BuildPaths
    ( autogenModulesDir )
102
import Distribution.Simple.Utils
103 104
    ( die, warn, info, setupMessage
    , createDirectoryIfMissingVerbose, moreRecentFile
105
    , intercalate, cabalVersion
106
    , writeFileAtomic
107
    , withTempFile )
108
import Distribution.System
109
    ( OS(..), buildOS, Platform (..), buildPlatform )
110
import Distribution.Version
111
         ( Version(..), anyVersion, orLaterVersion, withinRange, isAnyVersion )
112
import Distribution.Verbosity
113
    ( Verbosity, lessVerbose )
114

115 116 117 118 119
import qualified Distribution.Simple.GHC   as GHC
import qualified Distribution.Simple.GHCJS as GHCJS
import qualified Distribution.Simple.JHC   as JHC
import qualified Distribution.Simple.LHC   as LHC
import qualified Distribution.Simple.UHC   as UHC
120
import qualified Distribution.Simple.HaskellSuite as HaskellSuite
121

122 123
-- Prefer the more generic Data.Traversable.mapM to Prelude.mapM
import Prelude hiding ( mapM )
124 125
import Control.Exception
    ( ErrorCall(..), Exception, evaluate, throw, throwIO, try )
126
import Control.Monad
127
    ( liftM, when, unless, foldM, filterM )
128
import Distribution.Compat.Binary ( decodeOrFailIO, encode )
129
import Data.ByteString.Lazy (ByteString)
130 131
import qualified Data.ByteString            as BS
import qualified Data.ByteString.Lazy.Char8 as BLC8
132
import Data.List
133
    ( (\\), nub, partition, isPrefixOf, inits, stripPrefix )
134
import Data.Maybe
135
    ( isNothing, catMaybes, fromMaybe, isJust )
136 137
import Data.Either
    ( partitionEithers )
138
import qualified Data.Set as Set
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
139
#if __GLASGOW_HASKELL__ < 710
140 141
import Data.Monoid
    ( Monoid(..) )
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
142
#endif
143 144
import qualified Data.Map as Map
import Data.Map (Map)
145 146
import Data.Traversable
    ( mapM )
147
import Data.Typeable
148
import System.Directory
149
    ( doesFileExist, createDirectoryIfMissing, getTemporaryDirectory )
150
import System.FilePath
151
    ( (</>), isAbsolute )
152
import qualified System.Info
153
    ( compilerName, compilerVersion )
154
import System.IO
155
    ( hPutStrLn, hClose )
156
import Distribution.Text
157
    ( Text(disp), display, simpleParse )
dterei's avatar
dterei committed
158
import Text.PrettyPrint
159 160
    ( render, (<>), ($+$), char, text, comma
    , quotes, punctuate, nest, sep, hsep )
161
import Distribution.Compat.Exception ( catchExit, catchIO )
162

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
data ConfigStateFileError
    = ConfigStateFileNoHeader
    | ConfigStateFileBadHeader
    | ConfigStateFileNoParse
    | ConfigStateFileMissing
    | ConfigStateFileBadVersion PackageIdentifier PackageIdentifier (Either ConfigStateFileError LocalBuildInfo)
  deriving (Typeable)

instance Show ConfigStateFileError where
    show ConfigStateFileNoHeader =
        "Saved package config file header is missing. "
        ++ "Try re-running the 'configure' command."
    show ConfigStateFileBadHeader =
        "Saved package config file header is corrupt. "
        ++ "Try re-running the 'configure' command."
    show ConfigStateFileNoParse =
        "Saved package config file body is corrupt. "
        ++ "Try re-running the 'configure' command."
    show ConfigStateFileMissing = "Run the 'configure' command first."
    show (ConfigStateFileBadVersion oldCabal oldCompiler _) =
        "You need to re-run the 'configure' command. "
        ++ "The version of Cabal being used has changed (was "
        ++ display oldCabal ++ ", now "
        ++ display currentCabalId ++ ")."
        ++ badCompiler
      where
        badCompiler
          | oldCompiler == currentCompilerId = ""
          | otherwise =
              " Additionally the compiler is different (was "
              ++ display oldCompiler ++ ", now "
              ++ display currentCompilerId
              ++ ") which is probably the cause of the problem."

instance Exception ConfigStateFileError
198

199 200
getConfigStateFile :: FilePath -> IO LocalBuildInfo
getConfigStateFile filename = do
201
    exists <- doesFileExist filename
202
    unless exists $ throwIO ConfigStateFileMissing
203 204 205 206
    -- Read the config file into a strict ByteString to avoid problems with
    -- lazy I/O, then convert to lazy because the binary package needs that.
    contents <- BS.readFile filename
    let (header, body) = BLC8.span (/='\n') (BLC8.fromChunks [contents])
207

208 209 210 211 212 213
    headerParseResult <- try $ evaluate $ parseHeader header
    let (cabalId, compId) =
            case headerParseResult of
              Left (ErrorCall _) -> throw ConfigStateFileBadHeader
              Right x -> x

214 215 216 217 218
    let getStoredValue = do
          result <- decodeOrFailIO (BLC8.tail body)
          case result of
            Left _ -> throw ConfigStateFileNoParse
            Right x -> return x
219
        deferErrorIfBadVersion act
220
          | cabalId /= currentCabalId = do
221 222 223 224 225 226 227 228
              eResult <- try act
              throw $ ConfigStateFileBadVersion cabalId compId eResult
          | otherwise = act
    deferErrorIfBadVersion getStoredValue

tryGetConfigStateFile :: FilePath
                      -> IO (Either ConfigStateFileError LocalBuildInfo)
tryGetConfigStateFile = try . getConfigStateFile
229

230
-- |Try to read the 'localBuildInfoFile'.
231
tryGetPersistBuildConfig :: FilePath
232 233
                         -> IO (Either ConfigStateFileError LocalBuildInfo)
tryGetPersistBuildConfig = try . getPersistBuildConfig
234

235 236 237
-- | Read the 'localBuildInfoFile'. Throw an exception if the file is
-- missing, if the file cannot be read, or if the file was created by an older
-- version of Cabal.
238
getPersistBuildConfig :: FilePath -> IO LocalBuildInfo
239
getPersistBuildConfig = getConfigStateFile . localBuildInfoFile
240

ijones's avatar
ijones committed
241
-- |Try to read the 'localBuildInfoFile'.
242
maybeGetPersistBuildConfig :: FilePath -> IO (Maybe LocalBuildInfo)
243 244
maybeGetPersistBuildConfig =
    liftM (either (const Nothing) Just) . tryGetPersistBuildConfig
ijones's avatar
ijones committed
245

ijones's avatar
ijones committed
246 247
-- |After running configure, output the 'LocalBuildInfo' to the
-- 'localBuildInfoFile'.
248 249
writePersistBuildConfig :: FilePath -> LocalBuildInfo -> IO ()
writePersistBuildConfig distPref lbi = do
250 251
    createDirectoryIfMissing False distPref
    writeFileAtomic (localBuildInfoFile distPref) $
252
      BLC8.unlines [showHeader pkgId, encode lbi]
253 254
  where
    pkgId = packageId $ localPkgDescr lbi
255 256

currentCabalId :: PackageIdentifier
257
currentCabalId = PackageIdentifier (PackageName "Cabal") cabalVersion
258 259

currentCompilerId :: PackageIdentifier
Duncan Coutts's avatar
Duncan Coutts committed
260
currentCompilerId = PackageIdentifier (PackageName System.Info.compilerName)
261 262
                                      System.Info.compilerVersion

263
parseHeader :: ByteString -> (PackageIdentifier, PackageIdentifier)
264
parseHeader header = case BLC8.words header of
265 266
  ["Saved", "package", "config", "for", pkgId, "written", "by", cabalId, "using", compId] ->
      fromMaybe (throw ConfigStateFileBadHeader) $ do
267 268 269
          _ <- simpleParse (BLC8.unpack pkgId) :: Maybe PackageIdentifier
          cabalId' <- simpleParse (BLC8.unpack cabalId)
          compId' <- simpleParse (BLC8.unpack compId)
270 271
          return (cabalId', compId')
  _ -> throw ConfigStateFileNoHeader
272 273

showHeader :: PackageIdentifier -> ByteString
274
showHeader pkgId = BLC8.unwords
275
    [ "Saved", "package", "config", "for"
276
    , BLC8.pack $ display pkgId
277
    , "written", "by"
278
    , BLC8.pack $ display currentCabalId
279
    , "using"
280
    , BLC8.pack $ display currentCompilerId
281
    ]
282

283 284
-- |Check that localBuildInfoFile is up-to-date with respect to the
-- .cabal file.
285 286
checkPersistBuildConfigOutdated :: FilePath -> FilePath -> IO Bool
checkPersistBuildConfigOutdated distPref pkg_descr_file = do
287
  pkg_descr_file `moreRecentFile` (localBuildInfoFile distPref)
288

Ross Paterson's avatar
Ross Paterson committed
289
-- |@dist\/setup-config@
290 291
localBuildInfoFile :: FilePath -> FilePath
localBuildInfoFile distPref = distPref </> "setup-config"
ijones's avatar
ijones committed
292

293
-- -----------------------------------------------------------------------------
ijones's avatar
ijones committed
294 295
-- * Configuration
-- -----------------------------------------------------------------------------
296

297 298
-- |Perform the \"@.\/setup configure@\" action.
-- Returns the @.setup-config@ file.
299
configure :: (GenericPackageDescription, HookedBuildInfo)
300
          -> ConfigFlags -> IO LocalBuildInfo
301
configure (pkg_descr0, pbi) cfg
302
  = do  let distPref = fromFlag (configDistPref cfg)
intractable's avatar
intractable committed
303
            buildDir' = distPref </> "build"
304
            verbosity = fromFlag (configVerbosity cfg)
305

Duncan Coutts's avatar
Duncan Coutts committed
306
        setupMessage verbosity "Configuring" (packageId pkg_descr0)
307

308 309 310 311 312 313 314
        unless (configLibCoverage cfg == NoFlag) $ do
          let enable | fromFlag (configLibCoverage cfg) = "enable"
                     | otherwise = "disable"
          warn verbosity
            ("The flag --" ++ enable ++ "-library-coverage is deprecated. "
             ++ "Please use --" ++ enable ++ "-coverage instead.")

315
        createDirectoryIfMissingVerbose (lessVerbose verbosity) True distPref
316

317
        let programsConfig = mkProgramsConfig cfg (configPrograms cfg)
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
318 319 320
            userInstall    = fromFlag (configUserInstall cfg)
            packageDbs     = interpretPackageDbFlags userInstall
                             (configPackageDBs cfg)
321

322
        -- detect compiler
323
        (comp, compPlatform, programsConfig') <- configCompilerEx
324 325 326
          (flagToMaybe $ configHcFlavor cfg)
          (flagToMaybe $ configHcPath cfg) (flagToMaybe $ configHcPkg cfg)
          programsConfig (lessVerbose verbosity)
327 328
        let version = compilerVersion comp
            flavor  = compilerFlavor comp
329

330
        -- Create a PackageIndex that makes *any libraries that might be*
331 332 333 334 335 336 337 338 339 340 341 342 343 344
        -- defined internally to this package look like installed packages, in
        -- case an executable should refer to any of them as dependencies.
        --
        -- It must be *any libraries that might be* defined rather than the
        -- actual definitions, because these depend on conditionals in the .cabal
        -- file, and we haven't resolved them yet.  finalizePackageDescription
        -- does the resolution of conditionals, and it takes internalPackageSet
        -- as part of its input.
        --
        -- Currently a package can define no more than one library (which has
        -- the same name as the package) but we could extend this later.
        -- If we later allowed private internal libraries, then here we would
        -- need to pre-scan the conditional data to make a list of all private
        -- libraries that could possibly be defined by the .cabal file.
345
        let pid = packageId pkg_descr0
346 347 348 349 350
            internalPackage = emptyInstalledPackageInfo {
                --TODO: should use a per-compiler method to map the source
                --      package ID into an installed package id we can use
                --      for the internal package set. The open-codes use of
                --      InstalledPackageId . display here is a hack.
refold's avatar
refold committed
351 352
                Installed.installedPackageId =
                   InstalledPackageId $ display $ pid,
353 354 355
                Installed.sourcePackageId = pid
              }
            internalPackageSet = PackageIndex.fromList [internalPackage]
356
        installedPackageSet <- getInstalledPackages (lessVerbose verbosity) comp
357
                                      packageDbs programsConfig'
358

359 360 361 362 363 364 365 366 367 368 369 370
        (allConstraints, requiredDepsMap) <- either die return $
          combinedConstraints (configConstraints cfg)
                              (configDependencies cfg)
                              installedPackageSet

        let exactConf = fromFlagOrDefault False (configExactConfiguration cfg)
            -- Constraint test function for the solver
            dependencySatisfiable d@(Dependency depName verRange)
              | exactConf =
                -- When we're given '--exact-configuration', we assume that all
                -- dependencies and flags are exactly specified on the command
                -- line. Thus we only consult the 'requiredDepsMap'. Note that
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
371 372 373
                -- we're not doing the version range check, so if there's some
                -- dependency that wasn't specified on the command line,
                -- 'finalizePackageDescription' will fail.
374 375 376
                --
                -- TODO: mention '--exact-configuration' in the error message
                -- when this fails?
377
                (depName `Map.member` requiredDepsMap) || isInternalDep
378 379 380 381 382

              | otherwise =
                -- Normal operation: just look up dependency in the package
                -- index.
                not . null . PackageIndex.lookupDependency pkgs' $ d
383 384
              where
                pkgs' = PackageIndex.insert internalPackage installedPackageSet
385 386
                isInternalDep = pkgName pid == depName
                                && pkgVersion pid `withinRange` verRange
387 388 389
            enableTest t = t { testEnabled = fromFlag (configTests cfg) }
            flaggedTests = map (\(n, t) -> (n, mapTreeData enableTest t))
                               (condTestSuites pkg_descr0)
refold's avatar
refold committed
390 391 392 393
            enableBenchmark bm = bm { benchmarkEnabled =
                                         fromFlag (configBenchmarks cfg) }
            flaggedBenchmarks = map (\(n, bm) ->
                                      (n, mapTreeData enableBenchmark bm))
394 395 396
                               (condBenchmarks pkg_descr0)
            pkg_descr0'' = pkg_descr0 { condTestSuites = flaggedTests
                                      , condBenchmarks = flaggedBenchmarks }
397

398
        (pkg_descr0', flags) <-
399
                case finalizePackageDescription
400
                       (configConfigurationsFlags cfg)
401
                       dependencySatisfiable
402
                       compPlatform
403
                       (compilerInfo comp)
404
                       allConstraints
ttuegel's avatar
ttuegel committed
405
                       pkg_descr0''
406
                of Right r -> return r
407
                   Left missing ->
408
                       die $ "At least the following dependencies are missing:\n"
409 410 411
                         ++ (render . nest 4 . sep . punctuate comma
                                    . map (disp . simplifyDependency)
                                    $ missing)
412

413 414 415 416 417 418 419 420 421 422 423
        -- Sanity check: if '--exact-configuration' was given, ensure that the
        -- complete flag assignment was specified on the command line.
        when exactConf $ do
          let cmdlineFlags = map fst (configConfigurationsFlags cfg)
              allFlags     = map flagName . genPackageFlags $ pkg_descr0
              diffFlags    = allFlags \\ cmdlineFlags
          when (not . null $ diffFlags) $
            die $ "'--exact-conf' was given, "
            ++ "but the following flags were not specified: "
            ++ intercalate ", " (map show diffFlags)

424 425
        -- add extra include/lib dirs as specified in cfg
        -- we do it here so that those get checked too
426
        let pkg_descr = addExtraIncludeLibDirs pkg_descr0'
427

428 429 430 431 432 433 434 435
        unless (renamingPackageFlagsSupported comp ||
                    and [ rn == defaultRenaming
                        | bi <- allBuildInfo pkg_descr
                        , rn <- Map.elems (targetBuildRenaming bi)]) $
            die $ "Your compiler does not support thinning and renaming on "
               ++ "package flags.  To use this feature you probably must use "
               ++ "GHC 7.9 or later."

436
        when (not (null flags)) $
437 438 439
          info verbosity $ "Flags chosen: "
                        ++ intercalate ", " [ name ++ "=" ++ display value
                                            | (FlagName name, value) <- flags ]
440

441 442
        when (maybe False (not.null.PD.reexportedModules) (PD.library pkg_descr)
              && not (reexportedModulesSupported comp)) $ do
443
            die $ "Your compiler does not support module re-exports. To use "
444 445
               ++ "this feature you probably must use GHC 7.9 or later."

446
        checkPackageProblems verbosity pkg_descr0
447
          (updatePackageDescription pbi pkg_descr)
448

449 450 451
        -- Handle hole instantiation
        (holeDeps, hole_insts) <- configureInstantiateWith pkg_descr cfg installedPackageSet

452 453 454
        let selectDependencies :: [Dependency] ->
                                  ([FailedDependency], [ResolvedDependency])
            selectDependencies =
455
                (\xs -> ([ x | Left x <- xs ], [ x | Right x <- xs ]))
456 457
              . map (selectDependency internalPackageSet installedPackageSet
                                      requiredDepsMap)
458

refold's avatar
refold committed
459
            (failedDeps, allPkgDeps) =
460
              selectDependencies (buildDepends pkg_descr)
461

refold's avatar
refold committed
462 463 464 465
            internalPkgDeps = [ pkgid
                              | InternalDependency _ pkgid <- allPkgDeps ]
            externalPkgDeps = [ pkg
                              | ExternalDependency _ pkg   <- allPkgDeps ]
466

refold's avatar
refold committed
467 468
        when (not (null internalPkgDeps)
              && not (newPackageDepsBehaviour pkg_descr)) $
469 470
            die $ "The field 'build-depends: "
               ++ intercalate ", " (map (display . packageName) internalPkgDeps)
471
               ++ "' refers to a library which is defined within the same "
472 473
               ++ "package. To use this feature the package must specify at "
               ++ "least 'cabal-version: >= 1.8'."
474

475 476
        reportFailedDependencies failedDeps
        reportSelectedDependencies verbosity allPkgDeps
477

478 479 480 481 482
        let installDeps = Map.elems
                        . Map.fromList
                        . map (\v -> (Installed.installedPackageId v, v))
                        $ externalPkgDeps ++ holeDeps

483
        packageDependsIndex <-
484
          case PackageIndex.dependencyClosure installedPackageSet
485
                  (map Installed.installedPackageId installDeps) of
486 487 488
            Left packageDependsIndex -> return packageDependsIndex
            Right broken ->
              die $ "The following installed packages are broken because other"
489 490
                 ++ " packages they depend on are missing. These broken "
                 ++ "packages must be rebuilt before they can be used.\n"
491
                 ++ unlines [ "package "
492
                           ++ display (packageId pkg)
493
                           ++ " is broken due to missing package "
494
                           ++ intercalate ", " (map display deps)
495 496
                            | (pkg, deps) <- broken ]

497
        let pseudoTopPkg = emptyInstalledPackageInfo {
refold's avatar
refold committed
498 499
                Installed.installedPackageId =
                   InstalledPackageId (display (packageId pkg_descr)),
500
                Installed.sourcePackageId = packageId pkg_descr,
refold's avatar
refold committed
501
                Installed.depends =
502
                  map Installed.installedPackageId installDeps
503
              }
504
        case PackageIndex.dependencyInconsistencies
Duncan Coutts's avatar
Duncan Coutts committed
505
           . PackageIndex.insert pseudoTopPkg
506
           $ packageDependsIndex of
507 508 509
          [] -> return ()
          inconsistencies ->
            warn verbosity $
510
                 "This package indirectly depends on multiple versions of the same "
511
              ++ "package. This is highly likely to cause a compile failure.\n"
512 513
              ++ unlines [ "package " ++ display pkg ++ " requires "
                        ++ display (PackageIdentifier name ver)
514 515
                         | (name, uses) <- inconsistencies
                         , (pkg, ver) <- uses ]
Simon Marlow's avatar
Simon Marlow committed
516

517 518 519
        -- Calculate the package key.  We're going to store it in LocalBuildInfo
        -- canonically, but ComponentsLocalBuildInfo also needs to know about it
        -- XXX Do we need the internal deps?
520
        -- NB: does *not* include holeDeps!
521 522
        let pkg_key = mkPackageKey (packageKeySupported comp)
                                   (package pkg_descr)
523 524
                                   (map Installed.packageKey externalPkgDeps)
                                   (map (\(k,(p,m)) -> (k,(Installed.packageKey p,m))) hole_insts)
525

526 527
        -- internal component graph
        buildComponents <-
528
          case mkComponentsGraph pkg_descr internalPkgDeps of
529
            Left  componentCycle -> reportComponentCycle componentCycle
530 531
            Right components     ->
              case mkComponentsLocalBuildInfo packageDependsIndex pkg_descr
532 533
                                              internalPkgDeps externalPkgDeps holeDeps
                                              (Map.fromList hole_insts)
534 535 536
                                              pkg_key components of
                Left  problems    -> reportModuleReexportProblems problems
                Right components' -> return components'
537

538 539 540
        -- installation directories
        defaultDirs <- defaultInstallDirs flavor userInstall (hasLibs pkg_descr)
        let installDirs = combineInstallDirs fromFlagOrDefault
541
                            defaultDirs (configInstallDirs cfg)
542

543
        -- check languages and extensions
refold's avatar
refold committed
544 545
        let langlist = nub $ catMaybes $ map defaultLanguage
                       (allBuildInfo pkg_descr)
546 547 548 549 550 551
        let langs = unsupportedLanguages comp langlist
        when (not (null langs)) $
          die $ "The package " ++ display (packageId pkg_descr0)
             ++ " requires the following languages which are not "
             ++ "supported by " ++ display (compilerId comp) ++ ": "
             ++ intercalate ", " (map display langs)
552
        let extlist = nub $ concatMap allExtensions (allBuildInfo pkg_descr)
553
        let exts = unsupportedExtensions comp extlist
554 555 556 557 558
        when (not (null exts)) $
          die $ "The package " ++ display (packageId pkg_descr0)
             ++ " requires the following language extensions which are not "
             ++ "supported by " ++ display (compilerId comp) ++ ": "
             ++ intercalate ", " (map display exts)
559

560 561 562 563 564 565
        -- configured known/required programs & external build tools
        -- exclude build-tool deps on "internal" exes in the same package
        let requiredBuildTools =
              [ buildTool
              | let exeNames = map exeName (executables pkg_descr)
              , bi <- allBuildInfo pkg_descr
refold's avatar
refold committed
566 567
              , buildTool@(Dependency (PackageName toolName) reqVer)
                <- buildTools bi
568 569 570 571 572 573 574 575 576
              , let isInternal =
                        toolName `elem` exeNames
                        -- we assume all internal build-tools are
                        -- versioned with the package:
                     && packageVersion pkg_descr `withinRange` reqVer
              , not isInternal ]

        programsConfig'' <-
              configureAllKnownPrograms (lessVerbose verbosity) programsConfig'
577
          >>= configureRequiredPrograms verbosity requiredBuildTools
intractable's avatar
intractable committed
578

579 580
        (pkg_descr', programsConfig''') <-
          configurePkgconfigPackages verbosity pkg_descr programsConfig''
581

582 583 584 585 586
        split_objs <-
           if not (fromFlag $ configSplitObjs cfg)
                then return False
                else case flavor of
                            GHC | version >= Version [6,5] [] -> return True
587
                            GHCJS                             -> return True
588
                            _ -> do warn verbosity
Ian Lynagh's avatar
Ian Lynagh committed
589
                                         ("this compiler does not support " ++
590 591 592
                                          "--enable-split-objs; ignoring")
                                    return False

593 594 595 596 597
        let ghciLibByDefault =
              case compilerId comp of
                CompilerId GHC _ ->
                  -- If ghc is non-dynamic, then ghci needs object files,
                  -- so we build one by default.
598
                  --
599 600 601 602 603
                  -- Technically, archive files should be sufficient for ghci,
                  -- but because of GHC bug #8942, it has never been safe to
                  -- rely on them. By the time that bug was fixed, ghci had
                  -- been changed to read shared libraries instead of archive
                  -- files (see next code block).
604 605 606
                  not (GHC.isDynamic comp)
                CompilerId GHCJS _ ->
                  not (GHCJS.isDynamic comp)
607 608
                _ -> False

609 610 611 612 613 614
        let sharedLibsByDefault
              | fromFlag (configDynExe cfg) =
                  -- build a shared library if dynamically-linked
                  -- executables are requested
                  True
              | otherwise = case compilerId comp of
615 616 617
                CompilerId GHC _ ->
                  -- if ghc is dynamic, then ghci needs a shared
                  -- library, so we build one by default.
618 619 620
                  GHC.isDynamic comp
                CompilerId GHCJS _ ->
                  GHCJS.isDynamic comp
621
                _ -> False
622 623 624 625 626 627 628
            withSharedLib_ =
                -- build shared libraries if required by GHC or by the
                -- executable linking mode, but allow the user to force
                -- building only static library archives with
                -- --disable-shared.
                fromFlagOrDefault sharedLibsByDefault $ configSharedLib cfg
            withDynExe_ = fromFlag $ configDynExe cfg
629 630 631 632 633
        when (withDynExe_ && not withSharedLib_) $ warn verbosity $
               "Executables will use dynamic linking, but a shared library "
            ++ "is not being built. Linking will fail if any executables "
            ++ "depend on the library."

634
        let withProfExe_ = fromFlagOrDefault False $ configProfExe cfg
635 636 637 638 639
            withProfLib_ = fromFlagOrDefault withProfExe_ $ configProfLib cfg
        when (withProfExe_ && not withProfLib_) $ warn verbosity $
               "Executables will be built with profiling, but library "
            ++ "profiling is disabled. Linking will fail if any executables "
            ++ "depend on the library."
640

641 642 643 644 645
        let configCoverage_ =
              mappend (configCoverage cfg) (configLibCoverage cfg)

            cfg' = cfg { configCoverage = configCoverage_ }

646 647 648
        reloc <-
           if not (fromFlag $ configRelocatable cfg)
                then return False
649
                else return True
650

651
        let lbi = LocalBuildInfo {
652
                    configFlags         = cfg',
653 654 655
                    extraConfigArgs     = [],  -- Currently configure does not
                                               -- take extra args, but if it
                                               -- did they would go here.
656 657
                    installDirTemplates = installDirs,
                    compiler            = comp,
658
                    hostPlatform        = compPlatform,
659
                    buildDir            = buildDir',
660
                    componentsConfigs   = buildComponents,
661
                    installedPkgs       = packageDependsIndex,
662
                    pkgDescrFile        = Nothing,
663
                    localPkgDescr       = pkg_descr',
664
                    pkgKey              = pkg_key,
665
                    instantiatedWith    = hole_insts,
666
                    withPrograms        = programsConfig''',
667
                    withVanillaLib      = fromFlag $ configVanillaLib cfg,
668
                    withProfLib         = withProfLib_,
669 670
                    withSharedLib       = withSharedLib_,
                    withDynExe          = withDynExe_,
671
                    withProfExe         = withProfExe_,
672
                    withOptimization    = fromFlag $ configOptimization cfg,
tibbe's avatar
tibbe committed
673
                    withDebugInfo       = fromFlag $ configDebugInfo cfg,
674 675
                    withGHCiLib         = fromFlagOrDefault ghciLibByDefault $
                                          configGHCiLib cfg,
676
                    splitObjs           = split_objs,
677
                    stripExes           = fromFlag $ configStripExes cfg,
678
                    stripLibs           = fromFlag $ configStripLibs cfg,
679
                    withPackageDB       = packageDbs,
680
                    progPrefix          = fromFlag $ configProgPrefix cfg,
681 682
                    progSuffix          = fromFlag $ configProgSuffix cfg,
                    relocatable         = reloc
Duncan Coutts's avatar
Duncan Coutts committed
683
                  }
ijones's avatar
ijones committed
684

685
        when reloc (checkRelocatable verbosity pkg_descr lbi)
686

687
        let dirs = absoluteInstallDirs pkg_descr lbi NoCopyDest
688
            relative = prefixRelativeInstallDirs (packageId pkg_descr) lbi
689

690 691 692
        unless (isAbsolute (prefix dirs)) $ die $
            "expected an absolute directory name for --prefix: " ++ prefix dirs

693 694
        info verbosity $ "Using " ++ display currentCabalId
                      ++ " compiled by " ++ display currentCompilerId
695 696
        info verbosity $ "Using compiler: " ++ showCompilerId comp
        info verbosity $ "Using install prefix: " ++ prefix dirs
697

698 699
        let dirinfo name dir isPrefixRelative =
              info verbosity $ name ++ " installed in: " ++ dir ++ relNote
700 701 702 703 704
              where relNote = case buildOS of
                      Windows | not (hasLibs pkg_descr)
                             && isNothing isPrefixRelative
                             -> "  (fixed location)"
                      _      -> ""
705

706 707 708 709 710
        dirinfo "Binaries"         (bindir dirs)     (bindir relative)
        dirinfo "Libraries"        (libdir dirs)     (libdir relative)
        dirinfo "Private binaries" (libexecdir dirs) (libexecdir relative)
        dirinfo "Data files"       (datadir dirs)    (datadir relative)
        dirinfo "Documentation"    (docdir dirs)     (docdir relative)
clint's avatar
clint committed
711
        dirinfo "Configuration files" (sysconfdir dirs) (sysconfdir relative)
712 713

        sequence_ [ reportProgram verbosity prog configuredProg
714
                  | (prog, configuredProg) <- knownPrograms programsConfig''' ]
715

716
        return lbi
717

718 719 720
    where
      addExtraIncludeLibDirs pkg_descr =
          let extraBi = mempty { extraLibDirs = configExtraLibDirs cfg
Malcolm.Wallace's avatar
Malcolm.Wallace committed
721
                               , PD.includeDirs = configExtraIncludeDirs cfg}
refold's avatar
refold committed
722 723 724 725
              modifyLib l        = l{ libBuildInfo = libBuildInfo l
                                                     `mappend` extraBi }
              modifyExecutable e = e{ buildInfo    = buildInfo e
                                                     `mappend` extraBi}
726
          in pkg_descr{ library     = modifyLib        `fmap` library pkg_descr
refold's avatar
refold committed
727 728
                      , executables = modifyExecutable  `map`
                                      executables pkg_descr}
729

730 731 732 733 734 735 736 737
mkProgramsConfig :: ConfigFlags -> ProgramConfiguration -> ProgramConfiguration
mkProgramsConfig cfg initialProgramsConfig = programsConfig
  where
    programsConfig = userSpecifyArgss (configProgramArgs cfg)
                   . userSpecifyPaths (configProgramPaths cfg)
                   . setProgramSearchPath searchpath
                   $ initialProgramsConfig
    searchpath     = getProgramSearchPath (initialProgramsConfig)
738
                  ++ map ProgramSearchPathDir (fromNubList $ configProgramPathExtra cfg)