{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Distribution.Simple.LocalBuildInfo
-- Copyright   :  Isaac Jones 2003-2004
-- License     :  BSD3
--
-- Maintainer  :  cabal-devel@haskell.org
-- Portability :  portable
--
-- Once a package has been configured we have resolved conditionals and
-- dependencies, configured the compiler and other needed external programs.
-- The 'LocalBuildInfo' is used to hold all this information. It holds the
-- install dirs, the compiler, the exact package dependencies, the configured
-- programs, the package database to use and a bunch of miscellaneous configure
-- flags. It gets saved and reloaded from a file (@dist\/setup-config@). It gets
-- passed in to very many subsequent build actions.

module Distribution.Simple.LocalBuildInfo (
        LocalBuildInfo(..),
        externalPackageDeps,
        localComponentId,
        localUnitId,
        localCompatPackageKey,

        -- * Buildable package components
        Component(..),
        ComponentName(..),
        LibraryName(..),
        defaultLibName,
        showComponentName,
        componentNameString,
        ComponentLocalBuildInfo(..),
        componentBuildDir,
        foldComponent,
        componentName,
        componentBuildInfo,
        componentBuildable,
        pkgComponents,
        pkgBuildableComponents,
        lookupComponent,
        getComponent,
        getComponentLocalBuildInfo,
        allComponentsInBuildOrder,
        componentsInBuildOrder,
        depLibraryPaths,
        allLibModules,

        withAllComponentsInBuildOrder,
        withComponentsInBuildOrder,
        withComponentsLBI,
        withLibLBI,
        withExeLBI,
        withBenchLBI,
        withTestLBI,
        enabledTestLBIs,
        enabledBenchLBIs,

        -- * Installation directories
        module Distribution.Simple.InstallDirs,
        absoluteInstallDirs, prefixRelativeInstallDirs,
        absoluteComponentInstallDirs, prefixRelativeComponentInstallDirs,
        substPathTemplate,
  ) where

import Prelude ()
import Distribution.Compat.Prelude

import Distribution.Types.Component
import Distribution.Types.PackageId
import Distribution.Types.UnitId
import Distribution.Types.ComponentName
import Distribution.Types.UnqualComponentName
import Distribution.Types.PackageDescription
import Distribution.Types.ComponentLocalBuildInfo
import Distribution.Types.LocalBuildInfo
import Distribution.Types.TargetInfo

import Distribution.Simple.InstallDirs hiding (absoluteInstallDirs,
                                               prefixRelativeInstallDirs,
                                               substPathTemplate, )
import qualified Distribution.Simple.InstallDirs as InstallDirs
import Distribution.PackageDescription
import qualified Distribution.InstalledPackageInfo as Installed
import Distribution.Package
import Distribution.ModuleName
import Distribution.Simple.Compiler
import Distribution.Simple.PackageIndex
import Distribution.Simple.Utils
import Distribution.Pretty
import qualified Distribution.Compat.Graph as Graph

import Data.List (stripPrefix)
import System.FilePath
import qualified Data.Map as Map

import System.Directory (doesDirectoryExist, canonicalizePath)

-- -----------------------------------------------------------------------------
-- Configuration information of buildable components

componentBuildDir :: LocalBuildInfo -> ComponentLocalBuildInfo -> FilePath
-- For now, we assume that libraries/executables/test-suites/benchmarks
-- are only ever built once.  With Backpack, we need a special case for
-- libraries so that we can handle building them multiple times.
componentBuildDir :: LocalBuildInfo -> ComponentLocalBuildInfo -> FilePath
componentBuildDir lbi :: LocalBuildInfo
lbi clbi :: ComponentLocalBuildInfo
clbi
    = LocalBuildInfo -> FilePath
buildDir LocalBuildInfo
lbi FilePath -> FilePath -> FilePath
</>
        case ComponentLocalBuildInfo -> ComponentName
componentLocalName ComponentLocalBuildInfo
clbi of
            CLibName LMainLibName ->
                if UnitId -> FilePath
forall a. Pretty a => a -> FilePath
prettyShow (ComponentLocalBuildInfo -> UnitId
componentUnitId ComponentLocalBuildInfo
clbi) FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== ComponentId -> FilePath
forall a. Pretty a => a -> FilePath
prettyShow (ComponentLocalBuildInfo -> ComponentId
componentComponentId ComponentLocalBuildInfo
clbi)
                    then ""
                    else UnitId -> FilePath
forall a. Pretty a => a -> FilePath
prettyShow (ComponentLocalBuildInfo -> UnitId
componentUnitId ComponentLocalBuildInfo
clbi)
            CLibName (LSubLibName s :: UnqualComponentName
s) ->
                if UnitId -> FilePath
forall a. Pretty a => a -> FilePath
prettyShow (ComponentLocalBuildInfo -> UnitId
componentUnitId ComponentLocalBuildInfo
clbi) FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== ComponentId -> FilePath
forall a. Pretty a => a -> FilePath
prettyShow (ComponentLocalBuildInfo -> ComponentId
componentComponentId ComponentLocalBuildInfo
clbi)
                    then UnqualComponentName -> FilePath
unUnqualComponentName UnqualComponentName
s
                    else UnitId -> FilePath
forall a. Pretty a => a -> FilePath
prettyShow (ComponentLocalBuildInfo -> UnitId
componentUnitId ComponentLocalBuildInfo
clbi)
            CFLibName s :: UnqualComponentName
s  -> UnqualComponentName -> FilePath
unUnqualComponentName UnqualComponentName
s
            CExeName s :: UnqualComponentName
s   -> UnqualComponentName -> FilePath
unUnqualComponentName UnqualComponentName
s
            CTestName s :: UnqualComponentName
s  -> UnqualComponentName -> FilePath
unUnqualComponentName UnqualComponentName
s
            CBenchName s :: UnqualComponentName
s -> UnqualComponentName -> FilePath
unUnqualComponentName UnqualComponentName
s

{-# DEPRECATED getComponentLocalBuildInfo "This function is not well-defined, because a 'ComponentName' does not uniquely identify a 'ComponentLocalBuildInfo'.  If you have a 'TargetInfo', you should use 'targetCLBI' to get the 'ComponentLocalBuildInfo'.  Otherwise, use 'componentNameTargets' to get all possible 'ComponentLocalBuildInfo's.  This will be removed in Cabal 2.2." #-}
getComponentLocalBuildInfo :: LocalBuildInfo -> ComponentName -> ComponentLocalBuildInfo
getComponentLocalBuildInfo :: LocalBuildInfo -> ComponentName -> ComponentLocalBuildInfo
getComponentLocalBuildInfo lbi :: LocalBuildInfo
lbi cname :: ComponentName
cname =
    case LocalBuildInfo -> ComponentName -> [ComponentLocalBuildInfo]
componentNameCLBIs LocalBuildInfo
lbi ComponentName
cname of
      [clbi :: ComponentLocalBuildInfo
clbi] -> ComponentLocalBuildInfo
clbi
      [] ->
          FilePath -> ComponentLocalBuildInfo
forall a. HasCallStack => FilePath -> a
error (FilePath -> ComponentLocalBuildInfo)
-> FilePath -> ComponentLocalBuildInfo
forall a b. (a -> b) -> a -> b
$ "internal error: there is no configuration data "
               FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ "for component " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ ComponentName -> FilePath
forall a. Show a => a -> FilePath
show ComponentName
cname
      clbis :: [ComponentLocalBuildInfo]
clbis ->
          FilePath -> ComponentLocalBuildInfo
forall a. HasCallStack => FilePath -> a
error (FilePath -> ComponentLocalBuildInfo)
-> FilePath -> ComponentLocalBuildInfo
forall a b. (a -> b) -> a -> b
$ "internal error: the component name " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ ComponentName -> FilePath
forall a. Show a => a -> FilePath
show ComponentName
cname
               FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ "is ambiguous.  Refers to: "
               FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate ", " ((ComponentLocalBuildInfo -> FilePath)
-> [ComponentLocalBuildInfo] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (UnitId -> FilePath
forall a. Pretty a => a -> FilePath
prettyShow (UnitId -> FilePath)
-> (ComponentLocalBuildInfo -> UnitId)
-> ComponentLocalBuildInfo
-> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComponentLocalBuildInfo -> UnitId
componentUnitId) [ComponentLocalBuildInfo]
clbis)

-- | Perform the action on each enabled 'library' in the package
-- description with the 'ComponentLocalBuildInfo'.
withLibLBI :: PackageDescription -> LocalBuildInfo
           -> (Library -> ComponentLocalBuildInfo -> IO ()) -> IO ()
withLibLBI :: PackageDescription
-> LocalBuildInfo
-> (Library -> ComponentLocalBuildInfo -> IO ())
-> IO ()
withLibLBI pkg :: PackageDescription
pkg lbi :: LocalBuildInfo
lbi f :: Library -> ComponentLocalBuildInfo -> IO ()
f =
    PackageDescription
-> LocalBuildInfo -> (TargetInfo -> IO ()) -> IO ()
withAllTargetsInBuildOrder' PackageDescription
pkg LocalBuildInfo
lbi ((TargetInfo -> IO ()) -> IO ()) -> (TargetInfo -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \target :: TargetInfo
target ->
        case TargetInfo -> Component
targetComponent TargetInfo
target of
            CLib lib :: Library
lib -> Library -> ComponentLocalBuildInfo -> IO ()
f Library
lib (TargetInfo -> ComponentLocalBuildInfo
targetCLBI TargetInfo
target)
            _ -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- | Perform the action on each enabled 'Executable' in the package
-- description.  Extended version of 'withExe' that also gives corresponding
-- build info.
withExeLBI :: PackageDescription -> LocalBuildInfo
           -> (Executable -> ComponentLocalBuildInfo -> IO ()) -> IO ()
withExeLBI :: PackageDescription
-> LocalBuildInfo
-> (Executable -> ComponentLocalBuildInfo -> IO ())
-> IO ()
withExeLBI pkg :: PackageDescription
pkg lbi :: LocalBuildInfo
lbi f :: Executable -> ComponentLocalBuildInfo -> IO ()
f =
    PackageDescription
-> LocalBuildInfo -> (TargetInfo -> IO ()) -> IO ()
withAllTargetsInBuildOrder' PackageDescription
pkg LocalBuildInfo
lbi ((TargetInfo -> IO ()) -> IO ()) -> (TargetInfo -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \target :: TargetInfo
target ->
        case TargetInfo -> Component
targetComponent TargetInfo
target of
            CExe exe :: Executable
exe -> Executable -> ComponentLocalBuildInfo -> IO ()
f Executable
exe (TargetInfo -> ComponentLocalBuildInfo
targetCLBI TargetInfo
target)
            _ -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- | Perform the action on each enabled 'Benchmark' in the package
-- description.
withBenchLBI :: PackageDescription -> LocalBuildInfo
            -> (Benchmark -> ComponentLocalBuildInfo -> IO ()) -> IO ()
withBenchLBI :: PackageDescription
-> LocalBuildInfo
-> (Benchmark -> ComponentLocalBuildInfo -> IO ())
-> IO ()
withBenchLBI pkg :: PackageDescription
pkg lbi :: LocalBuildInfo
lbi f :: Benchmark -> ComponentLocalBuildInfo -> IO ()
f =
    [IO ()] -> IO ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ Benchmark -> ComponentLocalBuildInfo -> IO ()
f Benchmark
bench ComponentLocalBuildInfo
clbi | (bench :: Benchmark
bench, clbi :: ComponentLocalBuildInfo
clbi) <- PackageDescription
-> LocalBuildInfo -> [(Benchmark, ComponentLocalBuildInfo)]
enabledBenchLBIs PackageDescription
pkg LocalBuildInfo
lbi ]

withTestLBI :: PackageDescription -> LocalBuildInfo
            -> (TestSuite -> ComponentLocalBuildInfo -> IO ()) -> IO ()
withTestLBI :: PackageDescription
-> LocalBuildInfo
-> (TestSuite -> ComponentLocalBuildInfo -> IO ())
-> IO ()
withTestLBI pkg :: PackageDescription
pkg lbi :: LocalBuildInfo
lbi f :: TestSuite -> ComponentLocalBuildInfo -> IO ()
f =
    [IO ()] -> IO ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ [ TestSuite -> ComponentLocalBuildInfo -> IO ()
f TestSuite
test ComponentLocalBuildInfo
clbi | (test :: TestSuite
test, clbi :: ComponentLocalBuildInfo
clbi) <- PackageDescription
-> LocalBuildInfo -> [(TestSuite, ComponentLocalBuildInfo)]
enabledTestLBIs PackageDescription
pkg LocalBuildInfo
lbi ]

enabledTestLBIs :: PackageDescription -> LocalBuildInfo
             -> [(TestSuite, ComponentLocalBuildInfo)]
enabledTestLBIs :: PackageDescription
-> LocalBuildInfo -> [(TestSuite, ComponentLocalBuildInfo)]
enabledTestLBIs pkg :: PackageDescription
pkg lbi :: LocalBuildInfo
lbi =
    [ (TestSuite
test, TargetInfo -> ComponentLocalBuildInfo
targetCLBI TargetInfo
target)
    | TargetInfo
target <- PackageDescription -> LocalBuildInfo -> [TargetInfo]
allTargetsInBuildOrder' PackageDescription
pkg LocalBuildInfo
lbi
    , CTest test :: TestSuite
test <- [TargetInfo -> Component
targetComponent TargetInfo
target] ]

enabledBenchLBIs :: PackageDescription -> LocalBuildInfo
             -> [(Benchmark, ComponentLocalBuildInfo)]
enabledBenchLBIs :: PackageDescription
-> LocalBuildInfo -> [(Benchmark, ComponentLocalBuildInfo)]
enabledBenchLBIs pkg :: PackageDescription
pkg lbi :: LocalBuildInfo
lbi =
    [ (Benchmark
bench, TargetInfo -> ComponentLocalBuildInfo
targetCLBI TargetInfo
target)
    | TargetInfo
target <- PackageDescription -> LocalBuildInfo -> [TargetInfo]
allTargetsInBuildOrder' PackageDescription
pkg LocalBuildInfo
lbi
    , CBench bench :: Benchmark
bench <- [TargetInfo -> Component
targetComponent TargetInfo
target] ]

{-# DEPRECATED withComponentsLBI "Use withAllComponentsInBuildOrder" #-}
withComponentsLBI :: PackageDescription -> LocalBuildInfo
                  -> (Component -> ComponentLocalBuildInfo -> IO ())
                  -> IO ()
withComponentsLBI :: PackageDescription
-> LocalBuildInfo
-> (Component -> ComponentLocalBuildInfo -> IO ())
-> IO ()
withComponentsLBI = PackageDescription
-> LocalBuildInfo
-> (Component -> ComponentLocalBuildInfo -> IO ())
-> IO ()
PackageDescription
-> LocalBuildInfo
-> (Component -> ComponentLocalBuildInfo -> IO ())
-> IO ()
withAllComponentsInBuildOrder

-- | Perform the action on each buildable 'Library' or 'Executable' (Component)
-- in the PackageDescription, subject to the build order specified by the
-- 'compBuildOrder' field of the given 'LocalBuildInfo'
withAllComponentsInBuildOrder :: PackageDescription -> LocalBuildInfo
                              -> (Component -> ComponentLocalBuildInfo -> IO ())
                              -> IO ()
withAllComponentsInBuildOrder :: PackageDescription
-> LocalBuildInfo
-> (Component -> ComponentLocalBuildInfo -> IO ())
-> IO ()
withAllComponentsInBuildOrder pkg :: PackageDescription
pkg lbi :: LocalBuildInfo
lbi f :: Component -> ComponentLocalBuildInfo -> IO ()
f =
    PackageDescription
-> LocalBuildInfo -> (TargetInfo -> IO ()) -> IO ()
withAllTargetsInBuildOrder' PackageDescription
pkg LocalBuildInfo
lbi ((TargetInfo -> IO ()) -> IO ()) -> (TargetInfo -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \target :: TargetInfo
target ->
        Component -> ComponentLocalBuildInfo -> IO ()
f (TargetInfo -> Component
targetComponent TargetInfo
target) (TargetInfo -> ComponentLocalBuildInfo
targetCLBI TargetInfo
target)

{-# DEPRECATED withComponentsInBuildOrder "You have got a 'TargetInfo' right? Use 'withNeededTargetsInBuildOrder' on the 'UnitId's you can 'nodeKey' out." #-}
withComponentsInBuildOrder :: PackageDescription -> LocalBuildInfo
                           -> [ComponentName]
                           -> (Component -> ComponentLocalBuildInfo -> IO ())
                           -> IO ()
withComponentsInBuildOrder :: PackageDescription
-> LocalBuildInfo
-> [ComponentName]
-> (Component -> ComponentLocalBuildInfo -> IO ())
-> IO ()
withComponentsInBuildOrder pkg :: PackageDescription
pkg lbi :: LocalBuildInfo
lbi cnames :: [ComponentName]
cnames f :: Component -> ComponentLocalBuildInfo -> IO ()
f =
    PackageDescription
-> LocalBuildInfo -> [UnitId] -> (TargetInfo -> IO ()) -> IO ()
withNeededTargetsInBuildOrder' PackageDescription
pkg LocalBuildInfo
lbi [UnitId]
uids ((TargetInfo -> IO ()) -> IO ()) -> (TargetInfo -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \target :: TargetInfo
target ->
        Component -> ComponentLocalBuildInfo -> IO ()
f (TargetInfo -> Component
targetComponent TargetInfo
target) (TargetInfo -> ComponentLocalBuildInfo
targetCLBI TargetInfo
target)
  where uids :: [UnitId]
uids = (ComponentName -> [UnitId]) -> [ComponentName] -> [UnitId]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (LocalBuildInfo -> ComponentName -> [UnitId]
componentNameToUnitIds LocalBuildInfo
lbi) [ComponentName]
cnames

allComponentsInBuildOrder :: LocalBuildInfo
                          -> [ComponentLocalBuildInfo]
allComponentsInBuildOrder :: LocalBuildInfo -> [ComponentLocalBuildInfo]
allComponentsInBuildOrder lbi :: LocalBuildInfo
lbi =
    Graph ComponentLocalBuildInfo -> [ComponentLocalBuildInfo]
forall a. Graph a -> [a]
Graph.topSort (LocalBuildInfo -> Graph ComponentLocalBuildInfo
componentGraph LocalBuildInfo
lbi)

-- | Private helper function for some of the deprecated implementations.
componentNameToUnitIds :: LocalBuildInfo -> ComponentName -> [UnitId]
componentNameToUnitIds :: LocalBuildInfo -> ComponentName -> [UnitId]
componentNameToUnitIds lbi :: LocalBuildInfo
lbi cname :: ComponentName
cname =
    case ComponentName
-> Map ComponentName [ComponentLocalBuildInfo]
-> Maybe [ComponentLocalBuildInfo]
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup ComponentName
cname (LocalBuildInfo -> Map ComponentName [ComponentLocalBuildInfo]
componentNameMap LocalBuildInfo
lbi) of
        Just clbis :: [ComponentLocalBuildInfo]
clbis -> (ComponentLocalBuildInfo -> UnitId)
-> [ComponentLocalBuildInfo] -> [UnitId]
forall a b. (a -> b) -> [a] -> [b]
map ComponentLocalBuildInfo -> UnitId
componentUnitId [ComponentLocalBuildInfo]
clbis
        Nothing -> FilePath -> [UnitId]
forall a. HasCallStack => FilePath -> a
error (FilePath -> [UnitId]) -> FilePath -> [UnitId]
forall a b. (a -> b) -> a -> b
$ "componentNameToUnitIds " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ ComponentName -> FilePath
forall a. Pretty a => a -> FilePath
prettyShow ComponentName
cname

{-# DEPRECATED componentsInBuildOrder "You've got 'TargetInfo' right? Use 'neededTargetsInBuildOrder' on the 'UnitId's you can 'nodeKey' out." #-}
componentsInBuildOrder :: LocalBuildInfo -> [ComponentName]
                       -> [ComponentLocalBuildInfo]
componentsInBuildOrder :: LocalBuildInfo -> [ComponentName] -> [ComponentLocalBuildInfo]
componentsInBuildOrder lbi :: LocalBuildInfo
lbi cnames :: [ComponentName]
cnames
    -- NB: use of localPkgDescr here is safe because we throw out the
    -- result immediately afterwards
    = (TargetInfo -> ComponentLocalBuildInfo)
-> [TargetInfo] -> [ComponentLocalBuildInfo]
forall a b. (a -> b) -> [a] -> [b]
map TargetInfo -> ComponentLocalBuildInfo
targetCLBI (PackageDescription -> LocalBuildInfo -> [UnitId] -> [TargetInfo]
neededTargetsInBuildOrder' (LocalBuildInfo -> PackageDescription
localPkgDescr LocalBuildInfo
lbi) LocalBuildInfo
lbi [UnitId]
uids)
  where uids :: [UnitId]
uids = (ComponentName -> [UnitId]) -> [ComponentName] -> [UnitId]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (LocalBuildInfo -> ComponentName -> [UnitId]
componentNameToUnitIds LocalBuildInfo
lbi) [ComponentName]
cnames

-- -----------------------------------------------------------------------------
-- A random function that has no business in this module

-- | Determine the directories containing the dynamic libraries of the
-- transitive dependencies of the component we are building.
--
-- When wanted, and possible, returns paths relative to the installDirs 'prefix'
depLibraryPaths :: Bool -- ^ Building for inplace?
                -> Bool -- ^ Generate prefix-relative library paths
                -> LocalBuildInfo
                -> ComponentLocalBuildInfo -- ^ Component that is being built
                -> NoCallStackIO [FilePath]
depLibraryPaths :: Bool
-> Bool
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> NoCallStackIO [FilePath]
depLibraryPaths inplace :: Bool
inplace relative :: Bool
relative lbi :: LocalBuildInfo
lbi clbi :: ComponentLocalBuildInfo
clbi = do
    let pkgDescr :: PackageDescription
pkgDescr    = LocalBuildInfo -> PackageDescription
localPkgDescr LocalBuildInfo
lbi
        installDirs :: InstallDirs FilePath
installDirs = PackageDescription
-> LocalBuildInfo -> UnitId -> CopyDest -> InstallDirs FilePath
absoluteComponentInstallDirs PackageDescription
pkgDescr LocalBuildInfo
lbi (ComponentLocalBuildInfo -> UnitId
componentUnitId ComponentLocalBuildInfo
clbi) CopyDest
NoCopyDest
        executable :: Bool
executable  = case ComponentLocalBuildInfo
clbi of
                        ExeComponentLocalBuildInfo {} -> Bool
True
                        _                             -> Bool
False
        relDir :: FilePath
relDir | Bool
executable = InstallDirs FilePath -> FilePath
forall dir. InstallDirs dir -> dir
bindir InstallDirs FilePath
installDirs
               | Bool
otherwise  = InstallDirs FilePath -> FilePath
forall dir. InstallDirs dir -> dir
libdir InstallDirs FilePath
installDirs

    let -- TODO: this is kind of inefficient
        internalDeps :: [UnitId]
internalDeps = [ UnitId
uid
                       | (uid :: UnitId
uid, _) <- ComponentLocalBuildInfo -> [(UnitId, MungedPackageId)]
componentPackageDeps ComponentLocalBuildInfo
clbi
                       -- Test that it's internal
                       , TargetInfo
sub_target <- PackageDescription -> LocalBuildInfo -> [TargetInfo]
allTargetsInBuildOrder' PackageDescription
pkgDescr LocalBuildInfo
lbi
                       , ComponentLocalBuildInfo -> UnitId
componentUnitId (TargetInfo -> ComponentLocalBuildInfo
targetCLBI (TargetInfo
sub_target)) UnitId -> UnitId -> Bool
forall a. Eq a => a -> a -> Bool
== UnitId
uid ]
        internalLibs :: [FilePath]
internalLibs = [ ComponentLocalBuildInfo -> FilePath
getLibDir (TargetInfo -> ComponentLocalBuildInfo
targetCLBI TargetInfo
sub_target)
                       | TargetInfo
sub_target <- PackageDescription -> LocalBuildInfo -> [UnitId] -> [TargetInfo]
neededTargetsInBuildOrder'
                                        PackageDescription
pkgDescr LocalBuildInfo
lbi [UnitId]
internalDeps ]
    {-
    -- This is better, but it doesn't work, because we may be passed a
    -- CLBI which doesn't actually exist, and was faked up when we
    -- were building a test suite/benchmark.  See #3599 for proposal
    -- to fix this.
    let internalCLBIs = filter ((/= componentUnitId clbi) . componentUnitId)
                      . map targetCLBI
                      $ neededTargetsInBuildOrder lbi [componentUnitId clbi]
        internalLibs = map getLibDir internalCLBIs
    -}
        getLibDir :: ComponentLocalBuildInfo -> FilePath
getLibDir sub_clbi :: ComponentLocalBuildInfo
sub_clbi
          | Bool
inplace    = LocalBuildInfo -> ComponentLocalBuildInfo -> FilePath
componentBuildDir LocalBuildInfo
lbi ComponentLocalBuildInfo
sub_clbi
          | Bool
otherwise  = InstallDirs FilePath -> FilePath
forall dir. InstallDirs dir -> dir
dynlibdir (PackageDescription
-> LocalBuildInfo -> UnitId -> CopyDest -> InstallDirs FilePath
absoluteComponentInstallDirs PackageDescription
pkgDescr LocalBuildInfo
lbi (ComponentLocalBuildInfo -> UnitId
componentUnitId ComponentLocalBuildInfo
sub_clbi) CopyDest
NoCopyDest)

    -- Why do we go through all the trouble of a hand-crafting
    -- internalLibs, when 'installedPkgs' actually contains the
    -- internal libraries?  The trouble is that 'installedPkgs'
    -- may contain *inplace* entries, which we must NOT use for
    -- not inplace 'depLibraryPaths' (e.g., for RPATH calculation).
    -- See #4025 for more details. This is all horrible but it
    -- is a moot point if you are using a per-component build,
    -- because you never have any internal libraries in this case;
    -- they're all external.
    let external_ipkgs :: [InstalledPackageInfo]
external_ipkgs = (InstalledPackageInfo -> Bool)
-> [InstalledPackageInfo] -> [InstalledPackageInfo]
forall a. (a -> Bool) -> [a] -> [a]
filter InstalledPackageInfo -> Bool
forall pkg. HasUnitId pkg => pkg -> Bool
is_external (PackageIndex InstalledPackageInfo -> [InstalledPackageInfo]
forall a. PackageIndex a -> [a]
allPackages (LocalBuildInfo -> PackageIndex InstalledPackageInfo
installedPkgs LocalBuildInfo
lbi))
        is_external :: pkg -> Bool
is_external ipkg :: pkg
ipkg = Bool -> Bool
not (pkg -> UnitId
forall pkg. HasUnitId pkg => pkg -> UnitId
installedUnitId pkg
ipkg UnitId -> [UnitId] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [UnitId]
internalDeps)
        -- First look for dynamic libraries in `dynamic-library-dirs`, and use
        -- `library-dirs` as a fall back.
        getDynDir :: InstalledPackageInfo -> [FilePath]
getDynDir pkg :: InstalledPackageInfo
pkg  = case InstalledPackageInfo -> [FilePath]
Installed.libraryDynDirs InstalledPackageInfo
pkg of
                           [] -> InstalledPackageInfo -> [FilePath]
Installed.libraryDirs InstalledPackageInfo
pkg
                           d :: [FilePath]
d  -> [FilePath]
d
        allDepLibDirs :: [FilePath]
allDepLibDirs  = (InstalledPackageInfo -> [FilePath])
-> [InstalledPackageInfo] -> [FilePath]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap InstalledPackageInfo -> [FilePath]
getDynDir [InstalledPackageInfo]
external_ipkgs

        allDepLibDirs' :: [FilePath]
allDepLibDirs' = [FilePath]
internalLibs [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
allDepLibDirs
    [FilePath]
allDepLibDirsC <- (FilePath -> IO FilePath) -> [FilePath] -> NoCallStackIO [FilePath]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse FilePath -> IO FilePath
canonicalizePathNoFail [FilePath]
allDepLibDirs'

    let p :: FilePath
p                = InstallDirs FilePath -> FilePath
forall dir. InstallDirs dir -> dir
prefix InstallDirs FilePath
installDirs
        prefixRelative :: FilePath -> Bool
prefixRelative l :: FilePath
l = Maybe FilePath -> Bool
forall a. Maybe a -> Bool
isJust (FilePath -> FilePath -> Maybe FilePath
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix FilePath
p FilePath
l)
        libPaths :: [FilePath]
libPaths
          | Bool
relative Bool -> Bool -> Bool
&&
            FilePath -> Bool
prefixRelative FilePath
relDir = (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (\l :: FilePath
l ->
                                          if FilePath -> Bool
prefixRelative FilePath
l
                                             then FilePath -> FilePath -> FilePath
shortRelativePath FilePath
relDir FilePath
l
                                             else FilePath
l
                                        ) [FilePath]
allDepLibDirsC
          | Bool
otherwise             = [FilePath]
allDepLibDirsC

    [FilePath] -> NoCallStackIO [FilePath]
forall (m :: * -> *) a. Monad m => a -> m a
return [FilePath]
libPaths
  where
    -- 'canonicalizePath' fails on UNIX when the directory does not exists.
    -- So just don't canonicalize when it doesn't exist.
    canonicalizePathNoFail :: FilePath -> IO FilePath
canonicalizePathNoFail p :: FilePath
p = do
      Bool
exists <- FilePath -> IO Bool
doesDirectoryExist FilePath
p
      if Bool
exists
         then FilePath -> IO FilePath
canonicalizePath FilePath
p
         else FilePath -> IO FilePath
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
p

-- | Get all module names that needed to be built by GHC; i.e., all
-- of these 'ModuleName's have interface files associated with them
-- that need to be installed.
allLibModules :: Library -> ComponentLocalBuildInfo -> [ModuleName]
allLibModules :: Library -> ComponentLocalBuildInfo -> [ModuleName]
allLibModules lib :: Library
lib clbi :: ComponentLocalBuildInfo
clbi =
    [ModuleName] -> [ModuleName]
forall a. Ord a => [a] -> [a]
ordNub ([ModuleName] -> [ModuleName]) -> [ModuleName] -> [ModuleName]
forall a b. (a -> b) -> a -> b
$
    Library -> [ModuleName]
explicitLibModules Library
lib [ModuleName] -> [ModuleName] -> [ModuleName]
forall a. [a] -> [a] -> [a]
++
    case ComponentLocalBuildInfo
clbi of
        LibComponentLocalBuildInfo { componentInstantiatedWith :: ComponentLocalBuildInfo -> [(ModuleName, OpenModule)]
componentInstantiatedWith = [(ModuleName, OpenModule)]
insts } -> ((ModuleName, OpenModule) -> ModuleName)
-> [(ModuleName, OpenModule)] -> [ModuleName]
forall a b. (a -> b) -> [a] -> [b]
map (ModuleName, OpenModule) -> ModuleName
forall a b. (a, b) -> a
fst [(ModuleName, OpenModule)]
insts
        _ -> []

-- -----------------------------------------------------------------------------
-- Wrappers for a couple functions from InstallDirs

-- | Backwards compatibility function which computes the InstallDirs
-- assuming that @$libname@ points to the public library (or some fake
-- package identifier if there is no public library.)  IF AT ALL
-- POSSIBLE, please use 'absoluteComponentInstallDirs' instead.
absoluteInstallDirs :: PackageDescription -> LocalBuildInfo
                    -> CopyDest
                    -> InstallDirs FilePath
absoluteInstallDirs :: PackageDescription
-> LocalBuildInfo -> CopyDest -> InstallDirs FilePath
absoluteInstallDirs pkg :: PackageDescription
pkg lbi :: LocalBuildInfo
lbi copydest :: CopyDest
copydest =
    PackageDescription
-> LocalBuildInfo -> UnitId -> CopyDest -> InstallDirs FilePath
absoluteComponentInstallDirs PackageDescription
pkg LocalBuildInfo
lbi (LocalBuildInfo -> UnitId
localUnitId LocalBuildInfo
lbi) CopyDest
copydest

-- | See 'InstallDirs.absoluteInstallDirs'.
absoluteComponentInstallDirs :: PackageDescription -> LocalBuildInfo
                             -> UnitId
                             -> CopyDest
                             -> InstallDirs FilePath
absoluteComponentInstallDirs :: PackageDescription
-> LocalBuildInfo -> UnitId -> CopyDest -> InstallDirs FilePath
absoluteComponentInstallDirs pkg :: PackageDescription
pkg lbi :: LocalBuildInfo
lbi uid :: UnitId
uid copydest :: CopyDest
copydest =
  PackageIdentifier
-> UnitId
-> CompilerInfo
-> CopyDest
-> Platform
-> InstallDirs PathTemplate
-> InstallDirs FilePath
InstallDirs.absoluteInstallDirs
    (PackageDescription -> PackageIdentifier
forall pkg. Package pkg => pkg -> PackageIdentifier
packageId PackageDescription
pkg)
    UnitId
uid
    (Compiler -> CompilerInfo
compilerInfo (LocalBuildInfo -> Compiler
compiler LocalBuildInfo
lbi))
    CopyDest
copydest
    (LocalBuildInfo -> Platform
hostPlatform LocalBuildInfo
lbi)
    (LocalBuildInfo -> InstallDirs PathTemplate
installDirTemplates LocalBuildInfo
lbi)

-- | Backwards compatibility function which computes the InstallDirs
-- assuming that @$libname@ points to the public library (or some fake
-- package identifier if there is no public library.)  IF AT ALL
-- POSSIBLE, please use 'prefixRelativeComponentInstallDirs' instead.
prefixRelativeInstallDirs :: PackageId -> LocalBuildInfo
                          -> InstallDirs (Maybe FilePath)
prefixRelativeInstallDirs :: PackageIdentifier -> LocalBuildInfo -> InstallDirs (Maybe FilePath)
prefixRelativeInstallDirs pkg_descr :: PackageIdentifier
pkg_descr lbi :: LocalBuildInfo
lbi =
    PackageIdentifier
-> LocalBuildInfo -> UnitId -> InstallDirs (Maybe FilePath)
prefixRelativeComponentInstallDirs PackageIdentifier
pkg_descr LocalBuildInfo
lbi (LocalBuildInfo -> UnitId
localUnitId LocalBuildInfo
lbi)

-- |See 'InstallDirs.prefixRelativeInstallDirs'
prefixRelativeComponentInstallDirs :: PackageId -> LocalBuildInfo
                                   -> UnitId
                                   -> InstallDirs (Maybe FilePath)
prefixRelativeComponentInstallDirs :: PackageIdentifier
-> LocalBuildInfo -> UnitId -> InstallDirs (Maybe FilePath)
prefixRelativeComponentInstallDirs pkg_descr :: PackageIdentifier
pkg_descr lbi :: LocalBuildInfo
lbi uid :: UnitId
uid =
  PackageIdentifier
-> UnitId
-> CompilerInfo
-> Platform
-> InstallDirs PathTemplate
-> InstallDirs (Maybe FilePath)
InstallDirs.prefixRelativeInstallDirs
    (PackageIdentifier -> PackageIdentifier
forall pkg. Package pkg => pkg -> PackageIdentifier
packageId PackageIdentifier
pkg_descr)
    UnitId
uid
    (Compiler -> CompilerInfo
compilerInfo (LocalBuildInfo -> Compiler
compiler LocalBuildInfo
lbi))
    (LocalBuildInfo -> Platform
hostPlatform LocalBuildInfo
lbi)
    (LocalBuildInfo -> InstallDirs PathTemplate
installDirTemplates LocalBuildInfo
lbi)

substPathTemplate :: PackageId -> LocalBuildInfo
                  -> UnitId
                  -> PathTemplate -> FilePath
substPathTemplate :: PackageIdentifier
-> LocalBuildInfo -> UnitId -> PathTemplate -> FilePath
substPathTemplate pkgid :: PackageIdentifier
pkgid lbi :: LocalBuildInfo
lbi uid :: UnitId
uid = PathTemplate -> FilePath
fromPathTemplate
                                    (PathTemplate -> FilePath)
-> (PathTemplate -> PathTemplate) -> PathTemplate -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ( PathTemplateEnv -> PathTemplate -> PathTemplate
InstallDirs.substPathTemplate PathTemplateEnv
env )
    where env :: PathTemplateEnv
env = PackageIdentifier
-> UnitId -> CompilerInfo -> Platform -> PathTemplateEnv
initialPathTemplateEnv
                   PackageIdentifier
pkgid
                   UnitId
uid
                   (Compiler -> CompilerInfo
compilerInfo (LocalBuildInfo -> Compiler
compiler LocalBuildInfo
lbi))
                   (LocalBuildInfo -> Platform
hostPlatform LocalBuildInfo
lbi)