Configure.hs 66.1 KB
Newer Older
1 2
-----------------------------------------------------------------------------
-- |
ijones's avatar
ijones committed
3
-- Module      :  Distribution.Simple.Configure
4
-- Copyright   :  Isaac Jones 2003-2005
5
-- License     :  BSD3
6
--
Duncan Coutts's avatar
Duncan Coutts committed
7
-- Maintainer  :  cabal-devel@haskell.org
ijones's avatar
ijones committed
8
-- Portability :  portable
9
--
Duncan Coutts's avatar
Duncan Coutts committed
10 11 12 13 14 15 16 17
-- 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)
18
--
Duncan Coutts's avatar
Duncan Coutts committed
19 20 21 22
-- 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.
23

ijones's avatar
ijones committed
24 25
module Distribution.Simple.Configure (configure,
                                      writePersistBuildConfig,
ijones's avatar
ijones committed
26
                                      getPersistBuildConfig,
27
                                      checkPersistBuildConfigOutdated,
28
                                      tryGetPersistBuildConfig,
29
                                      maybeGetPersistBuildConfig,
ijones's avatar
ijones committed
30
                                      localBuildInfoFile,
31
                                      getInstalledPackages, getPackageDBContents,
32
                                      configCompiler, configCompilerAux,
33
                                      configCompilerEx, configCompilerAuxEx,
34
                                      ccLdOptionsBuildInfo,
35
                                      checkForeignDeps,
36
                                      interpretPackageDbFlags,
37 38 39 40

                                      ConfigStateFileErrorType(..),
                                      ConfigStateFileError,
                                      tryGetConfigStateFile,
41
                                      platformDefines,
ijones's avatar
ijones committed
42
                                     )
ijones's avatar
ijones committed
43
    where
44

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

112 113
import qualified Distribution.Simple.GHC  as GHC
import qualified Distribution.Simple.JHC  as JHC
David Himmelstrup's avatar
David Himmelstrup committed
114
import qualified Distribution.Simple.LHC  as LHC
115 116
import qualified Distribution.Simple.NHC  as NHC
import qualified Distribution.Simple.Hugs as Hugs
Andres Loeh's avatar
Andres Loeh committed
117
import qualified Distribution.Simple.UHC  as UHC
118
import qualified Distribution.Simple.HaskellSuite as HaskellSuite
119

120 121
-- Prefer the more generic Data.Traversable.mapM to Prelude.mapM
import Prelude hiding ( mapM )
122
import Control.Monad
123
    ( when, unless, foldM, filterM )
124
import Data.List
125
    ( (\\), nub, partition, isPrefixOf, inits )
126
import Data.Maybe
127
    ( isNothing, catMaybes, fromMaybe )
128 129
import Data.Either
    ( partitionEithers )
130 131
import Data.Monoid
    ( Monoid(..) )
132 133
import qualified Data.Map as Map
import Data.Map (Map)
134
import qualified Data.Set as Set
135 136
import Data.Traversable
    ( mapM )
137
import System.Directory
138
    ( doesFileExist, createDirectoryIfMissing, getTemporaryDirectory )
139
import System.FilePath
140
    ( (</>), isAbsolute )
141
import qualified System.Info
142
    ( compilerName, compilerVersion )
143
import System.IO
144
    ( hPutStrLn, hClose )
145
import Distribution.Text
146
    ( Text(disp), display, simpleParse )
dterei's avatar
dterei committed
147
import Text.PrettyPrint
148 149
    ( render, (<>), ($+$), char, text, comma
    , quotes, punctuate, nest, sep, hsep )
150
import Distribution.Compat.Exception ( catchExit, catchIO )
151

152 153
import qualified Data.ByteString.Lazy.Char8 as BS.Char8

154 155 156 157 158 159 160 161
data ConfigStateFileErrorType = ConfigStateFileCantParse
                              | ConfigStateFileMissing
                              | ConfigStateFileBadVersion
                              deriving Eq
type ConfigStateFileError = (String, ConfigStateFileErrorType)

tryGetConfigStateFile :: (Read a) => FilePath
                         -> IO (Either ConfigStateFileError a)
162
tryGetConfigStateFile filename = do
163 164
  exists <- doesFileExist filename
  if not exists
165
    then return (Left (missing, ConfigStateFileMissing))
166 167
    else withFileContents filename $ \str ->
      case lines str of
tibbe's avatar
tibbe committed
168
        [header, rest] -> case checkHeader header of
169
          Just err -> return (Left err)
170
          Nothing  -> case reads rest of
171
            [(bi,_)] -> return (Right bi)
172 173
            _        -> return (Left (cantParse, ConfigStateFileCantParse))
        _            -> return (Left (cantParse, ConfigStateFileCantParse))
174
  where
175
    checkHeader :: String -> Maybe ConfigStateFileError
176
    checkHeader header = case parseHeader header of
177
      Just (cabalId, compId)
178 179
        | cabalId
       == currentCabalId -> Nothing
180 181 182 183
        | otherwise      -> Just (badVersion cabalId compId
                                 ,ConfigStateFileBadVersion)
      Nothing            -> Just (cantParse
                                 ,ConfigStateFileCantParse)
184 185 186 187

    missing   = "Run the 'configure' command first."
    cantParse = "Saved package config file seems to be corrupt. "
             ++ "Try re-running the 'configure' command."
188
    badVersion cabalId compId
189 190
              = "You need to re-run the 'configure' command. "
             ++ "The version of Cabal being used has changed (was "
191 192
             ++ display cabalId ++ ", now "
             ++ display currentCabalId ++ ")."
193 194 195
             ++ badcompiler compId
    badcompiler compId | compId == currentCompilerId = ""
                       | otherwise
196
              = " Additionally the compiler is different (was "
197
             ++ display compId ++ ", now "
198
             ++ display currentCompilerId
199
             ++ ") which is probably the cause of the problem."
200

201
-- |Try to read the 'localBuildInfoFile'.
202 203
tryGetPersistBuildConfig :: FilePath
                            -> IO (Either ConfigStateFileError LocalBuildInfo)
204 205
tryGetPersistBuildConfig distPref
    = tryGetConfigStateFile (localBuildInfoFile distPref)
206

207 208 209
-- |Read the 'localBuildInfoFile'.  Error if it doesn't exist.  Also
-- fail if the file containing LocalBuildInfo is older than the .cabal
-- file, indicating that a re-configure is required.
210 211 212
getPersistBuildConfig :: FilePath -> IO LocalBuildInfo
getPersistBuildConfig distPref = do
  lbi <- tryGetPersistBuildConfig distPref
213
  either (die . fst) return lbi
214

ijones's avatar
ijones committed
215
-- |Try to read the 'localBuildInfoFile'.
216 217 218
maybeGetPersistBuildConfig :: FilePath -> IO (Maybe LocalBuildInfo)
maybeGetPersistBuildConfig distPref = do
  lbi <- tryGetPersistBuildConfig distPref
219
  return $ either (const Nothing) Just lbi
ijones's avatar
ijones committed
220

ijones's avatar
ijones committed
221 222
-- |After running configure, output the 'LocalBuildInfo' to the
-- 'localBuildInfoFile'.
223 224
writePersistBuildConfig :: FilePath -> LocalBuildInfo -> IO ()
writePersistBuildConfig distPref lbi = do
Ross Paterson's avatar
Ross Paterson committed
225
  createDirectoryIfMissing False distPref
226
  writeFileAtomic (localBuildInfoFile distPref)
227
                  (BS.Char8.pack $ showHeader pkgid ++ '\n' : show lbi)
228 229 230 231 232
  where
    pkgid   = packageId (localPkgDescr lbi)

showHeader :: PackageIdentifier -> String
showHeader pkgid =
233 234 235
     "Saved package config for " ++ display pkgid
  ++ " written by " ++ display currentCabalId
  ++      " using " ++ display currentCompilerId
236 237

currentCabalId :: PackageIdentifier
238
currentCabalId = PackageIdentifier (PackageName "Cabal") cabalVersion
239 240

currentCompilerId :: PackageIdentifier
Duncan Coutts's avatar
Duncan Coutts committed
241
currentCompilerId = PackageIdentifier (PackageName System.Info.compilerName)
242 243
                                      System.Info.compilerVersion

244
parseHeader :: String -> Maybe (PackageIdentifier, PackageIdentifier)
245 246 247
parseHeader header = case words header of
  ["Saved", "package", "config", "for", pkgid,
   "written", "by", cabalid, "using", compilerid]
248 249 250
    -> case (simpleParse pkgid :: Maybe PackageIdentifier,
             simpleParse cabalid,
             simpleParse compilerid) of
251 252 253 254 255
        (Just _,
         Just cabalid',
         Just compilerid') -> Just (cabalid', compilerid')
        _                  -> Nothing
  _                        -> Nothing
256

257 258
-- |Check that localBuildInfoFile is up-to-date with respect to the
-- .cabal file.
259 260
checkPersistBuildConfigOutdated :: FilePath -> FilePath -> IO Bool
checkPersistBuildConfigOutdated distPref pkg_descr_file = do
261
  pkg_descr_file `moreRecentFile` (localBuildInfoFile distPref)
262

Ross Paterson's avatar
Ross Paterson committed
263
-- |@dist\/setup-config@
264 265
localBuildInfoFile :: FilePath -> FilePath
localBuildInfoFile distPref = distPref </> "setup-config"
ijones's avatar
ijones committed
266

267
-- -----------------------------------------------------------------------------
ijones's avatar
ijones committed
268 269
-- * Configuration
-- -----------------------------------------------------------------------------
270

271 272
-- |Perform the \"@.\/setup configure@\" action.
-- Returns the @.setup-config@ file.
273
configure :: (GenericPackageDescription, HookedBuildInfo)
274
          -> ConfigFlags -> IO LocalBuildInfo
275
configure (pkg_descr0, pbi) cfg
276
  = do  let distPref = fromFlag (configDistPref cfg)
intractable's avatar
intractable committed
277
            buildDir' = distPref </> "build"
278
            verbosity = fromFlag (configVerbosity cfg)
279

Duncan Coutts's avatar
Duncan Coutts committed
280
        setupMessage verbosity "Configuring" (packageId pkg_descr0)
281

282
        createDirectoryIfMissingVerbose (lessVerbose verbosity) True distPref
283

284
        let programsConfig = mkProgramsConfig cfg (configPrograms cfg)
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
285 286 287
            userInstall    = fromFlag (configUserInstall cfg)
            packageDbs     = interpretPackageDbFlags userInstall
                             (configPackageDBs cfg)
288

289
        -- detect compiler
290
        (comp, compPlatform, programsConfig') <- configCompilerEx
291 292 293
          (flagToMaybe $ configHcFlavor cfg)
          (flagToMaybe $ configHcPath cfg) (flagToMaybe $ configHcPkg cfg)
          programsConfig (lessVerbose verbosity)
294 295
        let version = compilerVersion comp
            flavor  = compilerFlavor comp
296

297
        -- Create a PackageIndex that makes *any libraries that might be*
298 299 300 301 302 303 304 305 306 307 308 309 310 311
        -- 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.
312
        let pid = packageId pkg_descr0
313 314 315 316 317
            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
318 319
                Installed.installedPackageId =
                   InstalledPackageId $ display $ pid,
320 321 322
                Installed.sourcePackageId = pid
              }
            internalPackageSet = PackageIndex.fromList [internalPackage]
323
        installedPackageSet <- getInstalledPackages (lessVerbose verbosity) comp
324
                                      packageDbs programsConfig'
325

326 327 328 329 330 331 332 333 334 335 336 337
        (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
338 339 340
                -- 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.
341 342 343
                --
                -- TODO: mention '--exact-configuration' in the error message
                -- when this fails?
344
                (depName `Map.member` requiredDepsMap) || isInternalDep
345 346 347 348 349

              | otherwise =
                -- Normal operation: just look up dependency in the package
                -- index.
                not . null . PackageIndex.lookupDependency pkgs' $ d
350 351
              where
                pkgs' = PackageIndex.insert internalPackage installedPackageSet
352 353
                isInternalDep = pkgName pid == depName
                                && pkgVersion pid `withinRange` verRange
354 355 356
            enableTest t = t { testEnabled = fromFlag (configTests cfg) }
            flaggedTests = map (\(n, t) -> (n, mapTreeData enableTest t))
                               (condTestSuites pkg_descr0)
refold's avatar
refold committed
357 358 359 360
            enableBenchmark bm = bm { benchmarkEnabled =
                                         fromFlag (configBenchmarks cfg) }
            flaggedBenchmarks = map (\(n, bm) ->
                                      (n, mapTreeData enableBenchmark bm))
361 362 363
                               (condBenchmarks pkg_descr0)
            pkg_descr0'' = pkg_descr0 { condTestSuites = flaggedTests
                                      , condBenchmarks = flaggedBenchmarks }
364

365
        (pkg_descr0', flags) <-
366
                case finalizePackageDescription
367
                       (configConfigurationsFlags cfg)
368
                       dependencySatisfiable
369
                       compPlatform
370
                       (compilerId comp)
371
                       allConstraints
ttuegel's avatar
ttuegel committed
372
                       pkg_descr0''
373
                of Right r -> return r
374
                   Left missing ->
375
                       die $ "At least the following dependencies are missing:\n"
376 377 378
                         ++ (render . nest 4 . sep . punctuate comma
                                    . map (disp . simplifyDependency)
                                    $ missing)
379

380 381 382 383 384 385 386 387 388 389 390
        -- 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)

391 392
        -- add extra include/lib dirs as specified in cfg
        -- we do it here so that those get checked too
393 394 395
        let pkg_descr =
                enableCoverage (fromFlag (configLibCoverage cfg)) distPref
                $ addExtraIncludeLibDirs pkg_descr0'
396

397
        when (not (null flags)) $
398 399 400
          info verbosity $ "Flags chosen: "
                        ++ intercalate ", " [ name ++ "=" ++ display value
                                            | (FlagName name, value) <- flags ]
401

402 403
        when (maybe False (not.null.PD.reexportedModules) (PD.library pkg_descr)
              && not (reexportedModulesSupported comp)) $ do
404
            die $ "Your compiler does not support module re-exports. To use "
405 406
               ++ "this feature you probably must use GHC 7.9 or later."

407
        checkPackageProblems verbosity pkg_descr0
408
          (updatePackageDescription pbi pkg_descr)
409

410 411 412
        let selectDependencies :: [Dependency] ->
                                  ([FailedDependency], [ResolvedDependency])
            selectDependencies =
413
                (\xs -> ([ x | Left x <- xs ], [ x | Right x <- xs ]))
414 415
              . map (selectDependency internalPackageSet installedPackageSet
                                      requiredDepsMap)
416

refold's avatar
refold committed
417
            (failedDeps, allPkgDeps) =
418
              selectDependencies (buildDepends pkg_descr)
419

refold's avatar
refold committed
420 421 422 423
            internalPkgDeps = [ pkgid
                              | InternalDependency _ pkgid <- allPkgDeps ]
            externalPkgDeps = [ pkg
                              | ExternalDependency _ pkg   <- allPkgDeps ]
424

refold's avatar
refold committed
425 426
        when (not (null internalPkgDeps)
              && not (newPackageDepsBehaviour pkg_descr)) $
427 428
            die $ "The field 'build-depends: "
               ++ intercalate ", " (map (display . packageName) internalPkgDeps)
429
               ++ "' refers to a library which is defined within the same "
430 431
               ++ "package. To use this feature the package must specify at "
               ++ "least 'cabal-version: >= 1.8'."
432

433 434
        reportFailedDependencies failedDeps
        reportSelectedDependencies verbosity allPkgDeps
435

436
        packageDependsIndex <-
437 438
          case PackageIndex.dependencyClosure installedPackageSet
                  (map Installed.installedPackageId externalPkgDeps) of
439 440 441
            Left packageDependsIndex -> return packageDependsIndex
            Right broken ->
              die $ "The following installed packages are broken because other"
442 443
                 ++ " packages they depend on are missing. These broken "
                 ++ "packages must be rebuilt before they can be used.\n"
444
                 ++ unlines [ "package "
445
                           ++ display (packageId pkg)
446
                           ++ " is broken due to missing package "
447
                           ++ intercalate ", " (map display deps)
448 449
                            | (pkg, deps) <- broken ]

450
        let pseudoTopPkg = emptyInstalledPackageInfo {
refold's avatar
refold committed
451 452
                Installed.installedPackageId =
                   InstalledPackageId (display (packageId pkg_descr)),
453
                Installed.sourcePackageId = packageId pkg_descr,
refold's avatar
refold committed
454 455
                Installed.depends =
                  map Installed.installedPackageId externalPkgDeps
456
              }
457
        case PackageIndex.dependencyInconsistencies
Duncan Coutts's avatar
Duncan Coutts committed
458
           . PackageIndex.insert pseudoTopPkg
459
           $ packageDependsIndex of
460 461 462
          [] -> return ()
          inconsistencies ->
            warn verbosity $
463
                 "This package indirectly depends on multiple versions of the same "
464
              ++ "package. This is highly likely to cause a compile failure.\n"
465 466
              ++ unlines [ "package " ++ display pkg ++ " requires "
                        ++ display (PackageIdentifier name ver)
467 468
                         | (name, uses) <- inconsistencies
                         , (pkg, ver) <- uses ]
Simon Marlow's avatar
Simon Marlow committed
469

470 471 472 473 474 475 476
        -- 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?
        let pkg_key = mkPackageKey (packageKeySupported comp)
                                   (package pkg_descr)
                                   (map packageKey externalPkgDeps)

477 478
        -- internal component graph
        buildComponents <-
479
          case mkComponentsGraph pkg_descr internalPkgDeps of
480
            Left  componentCycle -> reportComponentCycle componentCycle
481 482 483 484 485 486
            Right components     ->
              case mkComponentsLocalBuildInfo packageDependsIndex pkg_descr
                                              internalPkgDeps externalPkgDeps
                                              pkg_key components of
                Left  problems    -> reportModuleReexportProblems problems
                Right components' -> return components'
487

488 489 490
        -- installation directories
        defaultDirs <- defaultInstallDirs flavor userInstall (hasLibs pkg_descr)
        let installDirs = combineInstallDirs fromFlagOrDefault
491
                            defaultDirs (configInstallDirs cfg)
492

493
        -- check languages and extensions
refold's avatar
refold committed
494 495
        let langlist = nub $ catMaybes $ map defaultLanguage
                       (allBuildInfo pkg_descr)
496 497 498 499 500 501
        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)
502
        let extlist = nub $ concatMap allExtensions (allBuildInfo pkg_descr)
503
        let exts = unsupportedExtensions comp extlist
504 505 506 507 508
        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)
509

510 511 512 513 514 515
        -- 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
516 517
              , buildTool@(Dependency (PackageName toolName) reqVer)
                <- buildTools bi
518 519 520 521 522 523 524 525 526
              , 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'
527
          >>= configureRequiredPrograms verbosity requiredBuildTools
intractable's avatar
intractable committed
528

529 530
        (pkg_descr', programsConfig''') <-
          configurePkgconfigPackages verbosity pkg_descr programsConfig''
531

532 533 534 535 536 537
        split_objs <-
           if not (fromFlag $ configSplitObjs cfg)
                then return False
                else case flavor of
                            GHC | version >= Version [6,5] [] -> return True
                            _ -> do warn verbosity
Ian Lynagh's avatar
Ian Lynagh committed
538
                                         ("this compiler does not support " ++
539 540 541
                                          "--enable-split-objs; ignoring")
                                    return False

542 543 544 545 546 547 548
        let sharedLibsByDefault =
              case compilerId comp of
                CompilerId GHC _ ->
                  -- if ghc is dynamic, then ghci needs a shared
                  -- library, so we build one by default.
                  GHC.ghcDynamic comp
                _ -> False
549

550
        let lbi = LocalBuildInfo {
551
                    configFlags         = cfg,
552 553 554
                    extraConfigArgs     = [],  -- Currently configure does not
                                               -- take extra args, but if it
                                               -- did they would go here.
555 556
                    installDirTemplates = installDirs,
                    compiler            = comp,
557
                    hostPlatform        = compPlatform,
558
                    buildDir            = buildDir',
559
                    scratchDir          = fromFlagOrDefault
560 561
                                            (distPref </> "scratch")
                                            (configScratchDir cfg),
562
                    componentsConfigs   = buildComponents,
563
                    installedPkgs       = packageDependsIndex,
564
                    pkgDescrFile        = Nothing,
565
                    localPkgDescr       = pkg_descr',
566
                    pkgKey              = pkg_key,
567
                    withPrograms        = programsConfig''',
568 569
                    withVanillaLib      = fromFlag $ configVanillaLib cfg,
                    withProfLib         = fromFlag $ configProfLib cfg,
refold's avatar
refold committed
570 571
                    withSharedLib       = fromFlagOrDefault sharedLibsByDefault $
                                          configSharedLib cfg,
572
                    withDynExe          = fromFlag $ configDynExe cfg,
573 574 575 576
                    withProfExe         = fromFlag $ configProfExe cfg,
                    withOptimization    = fromFlag $ configOptimization cfg,
                    withGHCiLib         = fromFlag $ configGHCiLib cfg,
                    splitObjs           = split_objs,
577
                    stripExes           = fromFlag $ configStripExes cfg,
578
                    stripLibs           = fromFlag $ configStripLibs cfg,
579
                    withPackageDB       = packageDbs,
580 581
                    progPrefix          = fromFlag $ configProgPrefix cfg,
                    progSuffix          = fromFlag $ configProgSuffix cfg
Duncan Coutts's avatar
Duncan Coutts committed
582
                  }
ijones's avatar
ijones committed
583

584
        let dirs = absoluteInstallDirs pkg_descr lbi NoCopyDest
585
            relative = prefixRelativeInstallDirs (packageId pkg_descr) lbi
586

587 588 589
        unless (isAbsolute (prefix dirs)) $ die $
            "expected an absolute directory name for --prefix: " ++ prefix dirs

590 591
        info verbosity $ "Using " ++ display currentCabalId
                      ++ " compiled by " ++ display currentCompilerId
592 593
        info verbosity $ "Using compiler: " ++ showCompilerId comp
        info verbosity $ "Using install prefix: " ++ prefix dirs
594

595 596
        let dirinfo name dir isPrefixRelative =
              info verbosity $ name ++ " installed in: " ++ dir ++ relNote
597 598 599 600 601
              where relNote = case buildOS of
                      Windows | not (hasLibs pkg_descr)
                             && isNothing isPrefixRelative
                             -> "  (fixed location)"
                      _      -> ""
602

603 604 605 606 607
        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
608
        dirinfo "Configuration files" (sysconfdir dirs) (sysconfdir relative)
609 610

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

613
        return lbi
614

615 616 617
    where
      addExtraIncludeLibDirs pkg_descr =
          let extraBi = mempty { extraLibDirs = configExtraLibDirs cfg
Malcolm.Wallace's avatar
Malcolm.Wallace committed
618
                               , PD.includeDirs = configExtraIncludeDirs cfg}
refold's avatar
refold committed
619 620 621 622
              modifyLib l        = l{ libBuildInfo = libBuildInfo l
                                                     `mappend` extraBi }
              modifyExecutable e = e{ buildInfo    = buildInfo e
                                                     `mappend` extraBi}
623
          in pkg_descr{ library     = modifyLib        `fmap` library pkg_descr
refold's avatar
refold committed
624 625
                      , executables = modifyExecutable  `map`
                                      executables pkg_descr}
626

627 628 629 630 631 632 633 634 635 636
mkProgramsConfig :: ConfigFlags -> ProgramConfiguration -> ProgramConfiguration
mkProgramsConfig cfg initialProgramsConfig = programsConfig
  where
    programsConfig = userSpecifyArgss (configProgramArgs cfg)
                   . userSpecifyPaths (configProgramPaths cfg)
                   . setProgramSearchPath searchpath
                   $ initialProgramsConfig
    searchpath     = getProgramSearchPath (initialProgramsConfig)
                  ++ map ProgramSearchPathDir (configProgramPathExtra cfg)

637 638 639
-- -----------------------------------------------------------------------------
-- Configuring package dependencies

640 641 642 643 644
reportProgram :: Verbosity -> Program -> Maybe ConfiguredProgram -> IO ()
reportProgram verbosity prog Nothing
    = info verbosity $ "No " ++ programName prog ++ " found"
reportProgram verbosity prog (Just configuredProg)
    = info verbosity $ "Using " ++ programName prog ++ version ++ location
645 646 647 648 649
    where location = case programLocation configuredProg of
            FoundOnSystem p -> " found on system at: " ++ p
            UserSpecified p -> " given by user at: " ++ p
          version = case programVersion configuredProg of
            Nothing -> ""
650
            Just v  -> " version " ++ display v
ijones's avatar
ijones committed
651

652
hackageUrl :: String
653 654 655
hackageUrl = "http://hackage.haskell.org/package/"

data ResolvedDependency = ExternalDependency Dependency InstalledPackageInfo
refold's avatar
refold committed
656 657
                        | InternalDependency Dependency PackageId -- should be a
                                                                  -- lib name
658 659 660

data FailedDependency = DependencyNotExists PackageName
                      | DependencyNoVersion Dependency
661

ijones's avatar
ijones committed
662
-- | Test for a package dependency and record the version we have installed.
663
selectDependency :: PackageIndex  -- ^ Internally defined packages
Duncan Coutts's avatar
Duncan Coutts committed
664
                 -> PackageIndex  -- ^ Installed packages
665 666
                 -> Map PackageName InstalledPackageInfo
                    -- ^ Packages for which we have been given specific deps to use
667
                 -> Dependency
668
                 -> Either FailedDependency ResolvedDependency
669
selectDependency internalIndex installedIndex requiredDepsMap
670
  dep@(Dependency pkgname vr) =
671 672 673 674 675 676 677 678 679 680 681 682 683 684
  -- If the dependency specification matches anything in the internal package
  -- index, then we prefer that match to anything in the second.
  -- For example:
  --
  -- Name: MyLibrary
  -- Version: 0.1
  -- Library
  --     ..
  -- Executable my-exec
  --     build-depends: MyLibrary
  --
  -- We want "build-depends: MyLibrary" always to match the internal library
  -- even if there is a newer installed library "MyLibrary-0.2".
  -- However, "build-depends: MyLibrary >= 0.2" should match the installed one.
685 686 687 688
  case PackageIndex.lookupPackageName internalIndex pkgname of
    [(_,[pkg])] | packageVersion pkg `withinRange` vr
           -> Right $ InternalDependency dep (packageId pkg)

689 690 691 692 693 694 695 696 697
    _      -> case Map.lookup pkgname requiredDepsMap of
      -- If we know the exact pkg to use, then use it.
      Just pkginstance -> Right (ExternalDependency dep pkginstance)
      -- Otherwise we just pick an arbitrary instance of the latest version.
      Nothing -> case PackageIndex.lookupDependency installedIndex dep of
        []   -> Left  $ DependencyNotExists pkgname
        pkgs -> Right $ ExternalDependency dep $
                case last pkgs of
                  (_ver, pkginstances) -> head pkginstances
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714

reportSelectedDependencies :: Verbosity
                           -> [ResolvedDependency] -> IO ()
reportSelectedDependencies verbosity deps =
  info verbosity $ unlines
    [ "Dependency " ++ display (simplifyDependency dep)
                    ++ ": using " ++ display pkgid
    | resolved <- deps
    , let (dep, pkgid) = case resolved of
            ExternalDependency dep' pkg'   -> (dep', packageId pkg')
            InternalDependency dep' pkgid' -> (dep', pkgid') ]

reportFailedDependencies :: [FailedDependency] -> IO ()
reportFailedDependencies []     = return ()
reportFailedDependencies failed =
    die (intercalate "\n\n" (map reportFailedDependency failed))

715
  where
716 717 718 719 720 721 722
    reportFailedDependency (DependencyNotExists pkgname) =
         "there is no version of " ++ display pkgname ++ " installed.\n"
      ++ "Perhaps you need to download and install it from\n"
      ++ hackageUrl ++ display pkgname ++ "?"

    reportFailedDependency (DependencyNoVersion dep) =
        "cannot satisfy dependency " ++ display (simplifyDependency dep) ++ "\n"
ijones's avatar
ijones committed
723

724 725
getInstalledPackages :: Verbosity -> Compiler
                     -> PackageDBStack -> ProgramConfiguration
726
                     -> IO PackageIndex
727
getInstalledPackages verbosity comp packageDBs progconf = do
728 729 730 731 732
  when (null packageDBs) $
    die $ "No package databases have been specified. If you use "
       ++ "--package-db=clear, you must follow it with --package-db= "
       ++ "with 'global', 'user' or a specific file."

733
  info verbosity "Reading installed packages..."
734
  case compilerFlavor comp of
735 736 737 738 739
    GHC -> GHC.getInstalledPackages verbosity packageDBs progconf
    Hugs->Hugs.getInstalledPackages verbosity packageDBs progconf
    JHC -> JHC.getInstalledPackages verbosity packageDBs progconf
    LHC -> LHC.getInstalledPackages verbosity packageDBs progconf
    NHC -> NHC.getInstalledPackages verbosity packageDBs progconf
740
    UHC -> UHC.getInstalledPackages verbosity comp packageDBs progconf
741 742
    HaskellSuite {} ->
      HaskellSuite.getInstalledPackages verbosity packageDBs progconf
743 744
    flv -> die $ "don't know how to find the installed packages for "
              ++ display flv
ekarttun's avatar
ekarttun committed
745

746 747 748 749 750 751 752 753 754 755 756 757 758
-- | Like 'getInstalledPackages', but for a single package DB.
getPackageDBContents :: Verbosity -> Compiler
                     -> PackageDB -> ProgramConfiguration
                     -> IO PackageIndex
getPackageDBContents verbosity comp packageDB progconf = do
  info verbosity "Reading installed packages..."
  case compilerFlavor comp of
    GHC -> GHC.getPackageDBContents verbosity packageDB progconf

    -- For other compilers, try to fall back on 'getInstalledPackages'.
    _   -> getInstalledPackages verbosity comp [packageDB] progconf


759 760 761 762
-- | The user interface specifies the package dbs to use with a combination of
-- @--global@, @--user@ and @--package-db=global|user|clear|$file@.
-- This function combines the global/user flag and interprets the package-db
-- flag into a single package db stack.
763
--