content: -----------------------------------------------------------------------------
  -- |
  -- Module      :  Distribution.Simple.Program.Ar
  -- Copyright   :  Duncan Coutts 2009
  --
  -- Maintainer  :  cabal-devel@haskell.org
  -- Portability :  portable
  --
  -- This module provides an library interface to the @ar@ program.
  
  module Distribution.Simple.Program.Ar (
      createArLibArchive,
      multiStageProgramInvocation,
    ) where
  
  import Distribution.Simple.Program.Types
           ( ConfiguredProgram(..) )
  import Distribution.Simple.Program.Run
           ( programInvocation, multiStageProgramInvocation
           , runProgramInvocation )
  import Distribution.System
           ( OS(..), buildOS )
  import Distribution.Verbosity
           ( Verbosity, deafening, verbose )
  
  -- | Call @ar@ to create a library archive from a bunch of object files.
  --
  createArLibArchive :: Verbosity -> ConfiguredProgram
                     -> FilePath -> [FilePath] -> IO ()
  createArLibArchive verbosity ar target files =
  
    -- The args to use with "ar" are actually rather subtle and system-dependent.
    -- In particular we have the following issues:
    --
    --  -- On OS X, "ar q" does not make an archive index. Archives with no
    --     index cannot be used.
    --
    --  -- GNU "ar r" will not let us add duplicate objects, only "ar q" lets us
    --     do that. We have duplicates because of modules like "A.M" and "B.M"
    --     both make an object file "M.o" and ar does not consider the directory.
    --
    -- Our solution is to use "ar r" in the simple case when one call is enough.
    -- When we need to call ar multiple times we use "ar q" and for the last
    -- call on OSX we use "ar qs" so that it'll make the index.
  
    let simpleArgs  = case buildOS of
               OSX -> ["-r", "-s"]
               _   -> ["-r"]
  
        initialArgs = ["-q"]
        finalArgs   = case buildOS of
               OSX -> ["-q", "-s"]
               _   -> ["-q"]
  
        extraArgs   = verbosityOpts verbosity ++ [target]
  
        simple  = programInvocation ar (simpleArgs  ++ extraArgs)
        initial = programInvocation ar (initialArgs ++ extraArgs)
        middle  = initial
        final   = programInvocation ar (finalArgs   ++ extraArgs)
  
     in sequence_
          [ runProgramInvocation verbosity inv
          | inv <- multiStageProgramInvocation
                     simple (initial, middle, final) files ]
  
    where
      verbosityOpts v | v >= deafening = ["-v"]
                      | v >= verbose   = []
                      | otherwise      = ["-c"]
  