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

    -----------------------------------------------------------------------------

    -- |
    -- Module      :  Distribution.Simple.Program.Strip
    --
    -- Maintainer  :  cabal-devel@haskell.org
    -- Portability :  portable
    --
    -- This module provides an library interface to the @strip@ program.
    module Distribution.Simple.Program.Strip (stripLib, stripExe)
    where

    import Distribution.Compat.Prelude
    import Prelude ()

    import Distribution.Simple.Program
    import Distribution.Simple.Utils
    import Distribution.System
    import Distribution.Verbosity
    import Distribution.Version

    import System.FilePath (takeBaseName)

    runStrip :: Verbosity -> ProgramDb -> FilePath -> [String] -> IO ()
    runStrip :: Verbosity -> ProgramDb -> FilePath -> [FilePath] -> IO ()
    runStrip Verbosity
    verbosity ProgramDb
    progDb FilePath
    path [FilePath]
    args =
      case Program -> ProgramDb -> Maybe ConfiguredProgram
    lookupProgram Program
    stripProgram ProgramDb
    progDb of
        Just ConfiguredProgram
    strip -> Verbosity -> ConfiguredProgram -> [FilePath] -> IO ()
    runProgram Verbosity
    verbosity ConfiguredProgram
    strip ([FilePath]
    args [FilePath] -> [FilePath] -> [FilePath]
    forall a. [a] -> [a] -> [a]
    ++ [FilePath
    path])
        Maybe ConfiguredProgram
    Nothing ->
          Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless (OS
    buildOS OS -> OS -> Bool
    forall a. Eq a => a -> a -> Bool
    == OS
    Windows) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $
            -- Don't bother warning on windows, we don't expect them to
            -- have the strip program anyway.
            Verbosity -> FilePath -> IO ()
    warn Verbosity
    verbosity (FilePath -> IO ()) -> FilePath -> IO ()
    forall a b. (a -> b) -> a -> b
    $
              FilePath
    "Unable to strip executable or library '"
                FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ (FilePath -> FilePath
    takeBaseName FilePath
    path)
                FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    "' (missing the 'strip' program)"

    stripExe :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()
    stripExe :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()
    stripExe Verbosity
    verbosity (Platform Arch
    _arch OS
    os) ProgramDb
    progdb FilePath
    path =
      Verbosity -> ProgramDb -> FilePath -> [FilePath] -> IO ()
    runStrip Verbosity
    verbosity ProgramDb
    progdb FilePath
    path [FilePath]
    args
      where
        args :: [FilePath]
    args = case OS
    os of
          OS
    OSX -> [FilePath
    "-x"] -- By default, stripping the ghc binary on at least
          -- some OS X installations causes:
          --     HSbase-3.0.o: unknown symbol `_environ'"
          -- The -x flag fixes that.
          OS
    _ -> []

    stripLib :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()
    stripLib :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()
    stripLib Verbosity
    verbosity (Platform Arch
    arch OS
    os) ProgramDb
    progdb FilePath
    path = do
      case OS
    os of
        OS
    OSX ->
          -- '--strip-unneeded' is not supported on OS X, iOS, AIX, or
          -- Solaris. See #1630.
          () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
        OS
    IOS -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
        OS
    AIX -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
        OS
    Solaris -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
        OS
    Windows ->
          -- Stripping triggers a bug in 'strip.exe' for
          -- libraries with lots identically named modules. See
          -- #1784.
          () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
        OS
    Linux
          | Arch
    arch Arch -> Arch -> Bool
    forall a. Eq a => a -> a -> Bool
    == Arch
    I386 ->
              -- Versions of 'strip' on 32-bit Linux older than 2.18 are
              -- broken. See #2339.
              let okVersion :: VersionRange
    okVersion = Version -> VersionRange
    orLaterVersion ([Int] -> Version
    mkVersion [Int
    2, Int
    18])
               in case ConfiguredProgram -> Maybe Version
    programVersion (ConfiguredProgram -> Maybe Version)
    -> Maybe ConfiguredProgram -> Maybe Version
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Program -> ProgramDb -> Maybe ConfiguredProgram
    lookupProgram Program
    stripProgram ProgramDb
    progdb of
                    Just Version
    v
                      | Version -> VersionRange -> Bool
    withinRange Version
    v VersionRange
    okVersion ->
                          Verbosity -> ProgramDb -> FilePath -> [FilePath] -> IO ()
    runStrip Verbosity
    verbosity ProgramDb
    progdb FilePath
    path [FilePath]
    args
                    Maybe Version
    _ ->
                      Verbosity -> FilePath -> IO ()
    warn Verbosity
    verbosity (FilePath -> IO ()) -> FilePath -> IO ()
    forall a b. (a -> b) -> a -> b
    $
                        FilePath
    "Unable to strip library '"
                          FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ (FilePath -> FilePath
    takeBaseName FilePath
    path)
                          FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    "' (version of 'strip' too old; "
                          FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    "requires >= 2.18 on 32-bit Linux)"
        OS
    _ -> Verbosity -> ProgramDb -> FilePath -> [FilePath] -> IO ()
    runStrip Verbosity
    verbosity ProgramDb
    progdb FilePath
    path [FilePath]
    args
      where
        args :: [FilePath]
    args = [FilePath
    "--strip-unneeded"]