{-# 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 Prelude ()
import Distribution.Compat.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
verbosity progDb :: ProgramDb
progDb path :: FilePath
path args :: [FilePath]
args =
  case Program -> ProgramDb -> Maybe ConfiguredProgram
lookupProgram Program
stripProgram ProgramDb
progDb of
    Just strip :: ConfiguredProgram
strip -> Verbosity -> ConfiguredProgram -> [FilePath] -> IO ()
runProgram Verbosity
verbosity ConfiguredProgram
strip ([FilePath]
args [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath
path])
    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
$ "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]
++ "' (missing the 'strip' program)"

stripExe :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()
stripExe :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()
stripExe verbosity :: Verbosity
verbosity (Platform _arch :: Arch
_arch os :: OS
os) progdb :: ProgramDb
progdb path :: FilePath
path =
  Verbosity -> ProgramDb -> FilePath -> [FilePath] -> IO ()
runStrip Verbosity
verbosity ProgramDb
progdb FilePath
path [FilePath]
args
  where
    args :: [FilePath]
args = case OS
os of
       OSX -> ["-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.
       _   -> []

stripLib :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()
stripLib :: Verbosity -> Platform -> ProgramDb -> FilePath -> IO ()
stripLib verbosity :: Verbosity
verbosity (Platform arch :: Arch
arch os :: OS
os) progdb :: ProgramDb
progdb path :: FilePath
path = do
  case OS
os of
    OSX -> -- '--strip-unneeded' is not supported on OS X, iOS, AIX, or
           -- Solaris. See #1630.
           () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    IOS -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    AIX -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    Solaris -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    Windows -> -- Stripping triggers a bug in 'strip.exe' for
               -- libraries with lots identically named modules. See
               -- #1784.
               () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return()
    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 [2,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 v :: Version
v | Version -> VersionRange -> Bool
withinRange Version
v VersionRange
okVersion ->
            Verbosity -> ProgramDb -> FilePath -> [FilePath] -> IO ()
runStrip Verbosity
verbosity ProgramDb
progdb FilePath
path [FilePath]
args
          _ -> Verbosity -> FilePath -> IO ()
warn Verbosity
verbosity (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ "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]
++ "' (version of 'strip' too old; "
                                FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ "requires >= 2.18 on 32-bit Linux)"
    _   -> Verbosity -> ProgramDb -> FilePath -> [FilePath] -> IO ()
runStrip Verbosity
verbosity ProgramDb
progdb FilePath
path [FilePath]
args
  where
    args :: [FilePath]
args = ["--strip-unneeded"]