content: 
  -- | Linking Haskell units
  module GHC.Linker.Unit
     ( UnitLinkOpts (..)
     , collectLinkOpts
     , collectArchives
     , getUnitLinkOpts
     , getLibs
     )
  where
  
  import GHC.Prelude
  import GHC.Platform.Ways
  import GHC.Unit.Types
  import GHC.Unit.Info
  import GHC.Unit.State
  import GHC.Unit.Env
  import GHC.Utils.Misc
  
  import qualified GHC.Data.ShortText as ST
  
  import GHC.Settings
  
  import Control.Monad
  import System.Directory
  import System.FilePath
  
  -- | Linker flags collected from units
  data UnitLinkOpts = UnitLinkOpts
    { hsLibs     :: [String] -- ^ Haskell libraries (as a list of "-lHSfoo...")
    , extraLibs  :: [String] -- ^ External libraries (as a list of "-lfoo...")
    , otherFlags :: [String] -- ^ Extra linker options
    }
    deriving (Show)
  
  -- | Find all the link options in these and the preload packages,
  -- returning (package hs lib options, extra library options, other flags)
  getUnitLinkOpts :: GhcNameVersion -> Ways -> UnitEnv -> [UnitId] -> IO UnitLinkOpts
  getUnitLinkOpts namever ways unit_env pkgs = do
      ps <- mayThrowUnitErr $ preloadUnitsInfo' unit_env pkgs
      return (collectLinkOpts namever ways ps)
  
  collectLinkOpts :: GhcNameVersion -> Ways -> [UnitInfo] -> UnitLinkOpts
  collectLinkOpts namever ways ps = UnitLinkOpts
    { hsLibs     = concatMap (map ("-l" ++) . unitHsLibs namever ways) ps
    , extraLibs  = concatMap (map ("-l" ++) . map ST.unpack . unitExtDepLibsSys) ps
    , otherFlags = concatMap (map ST.unpack . unitLinkerOptions) ps
    }
  
  collectArchives :: GhcNameVersion -> Ways -> UnitInfo -> IO [FilePath]
  collectArchives namever ways pc =
    filterM doesFileExist [ searchPath </> ("lib" ++ lib ++ ".a")
                          | searchPath <- searchPaths
                          , lib <- libs ]
    where searchPaths = ordNub . filter notNull . libraryDirsForWay ways $ pc
          libs        = unitHsLibs namever ways pc ++ map ST.unpack (unitExtDepLibsSys pc)
  
  -- | Either the 'unitLibraryDirs' or 'unitLibraryDynDirs' as appropriate for the way.
  libraryDirsForWay :: Ways -> UnitInfo -> [String]
  libraryDirsForWay ws
    | hasWay ws WayDyn = map ST.unpack . unitLibraryDynDirs
    | otherwise        = map ST.unpack . unitLibraryDirs
  
  getLibs :: GhcNameVersion -> Ways -> UnitEnv -> [UnitId] -> IO [(String,String)]
  getLibs namever ways unit_env pkgs = do
    ps <- mayThrowUnitErr $ preloadUnitsInfo' unit_env pkgs
    fmap concat . forM ps $ \p -> do
      let candidates = [ (l </> f, f) | l <- collectLibraryDirs ways [p]
                                      , f <- (\n -> "lib" ++ n ++ ".a") <$> unitHsLibs namever ways p ]
      filterM (doesFileExist . fst) candidates
  
  