Support GHC 9.12
[cabal.git] / Cabal / src / Distribution / Simple / Program / Ld.hs
blobd7449b9396457bc0d5b518dffb377ca834a5fb3c
1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE RankNTypes #-}
4 -----------------------------------------------------------------------------
6 -- |
7 -- Module : Distribution.Simple.Program.Ld
8 -- Copyright : Duncan Coutts 2009
9 --
10 -- Maintainer : cabal-devel@haskell.org
11 -- Portability : portable
13 -- This module provides an library interface to the @ld@ linker program.
14 module Distribution.Simple.Program.Ld
15 ( combineObjectFiles
16 ) where
18 import Distribution.Compat.Prelude
19 import Prelude ()
21 import Distribution.Simple.Compiler (arResponseFilesSupported)
22 import Distribution.Simple.Flag
23 ( fromFlagOrDefault
25 import Distribution.Simple.LocalBuildInfo (LocalBuildInfo (..))
26 import Distribution.Simple.Program.ResponseFile
27 ( withResponseFile
29 import Distribution.Simple.Program.Run
30 ( ProgramInvocation
31 , multiStageProgramInvocation
32 , programInvocation
33 , runProgramInvocation
35 import Distribution.Simple.Program.Types
36 ( ConfiguredProgram (..)
38 import Distribution.Simple.Setup.Config
39 ( configUseResponseFiles
41 import Distribution.Simple.Utils
42 ( defaultTempFileOptions
44 import Distribution.Verbosity
45 ( Verbosity
48 import System.Directory
49 ( renameFile
51 import System.FilePath
52 ( takeDirectory
53 , (<.>)
56 -- | Call @ld -r@ to link a bunch of object files together.
57 combineObjectFiles
58 :: Verbosity
59 -> LocalBuildInfo
60 -> ConfiguredProgram
61 -> FilePath
62 -> [FilePath]
63 -> IO ()
64 combineObjectFiles verbosity lbi ld target files = do
65 -- Unlike "ar", the "ld" tool is not designed to be used with xargs. That is,
66 -- if we have more object files than fit on a single command line then we
67 -- have a slight problem. What we have to do is link files in batches into
68 -- a temp object file and then include that one in the next batch.
70 let simpleArgs = ["-r", "-o", target]
72 initialArgs = ["-r", "-o", target]
73 middleArgs = ["-r", "-o", target, tmpfile]
74 finalArgs = middleArgs
76 simple = programInvocation ld simpleArgs
77 initial = programInvocation ld initialArgs
78 middle = programInvocation ld middleArgs
79 final = programInvocation ld finalArgs
81 targetDir = takeDirectory target
83 invokeWithResponesFile :: FilePath -> ProgramInvocation
84 invokeWithResponesFile atFile =
85 programInvocation ld $ simpleArgs ++ ['@' : atFile]
87 oldVersionManualOverride =
88 fromFlagOrDefault False $ configUseResponseFiles $ configFlags lbi
89 -- Whether ghc's ar supports response files is a good proxy for
90 -- whether ghc's ld supports them as well.
91 responseArgumentsNotSupported =
92 not (arResponseFilesSupported (compiler lbi))
94 if oldVersionManualOverride || responseArgumentsNotSupported
95 then run $ multiStageProgramInvocation simple (initial, middle, final) files
96 else withResponseFile verbosity defaultTempFileOptions targetDir "ld.rsp" Nothing files $
97 \path -> runProgramInvocation verbosity $ invokeWithResponesFile path
98 where
99 tmpfile = target <.> "tmp" -- perhaps should use a proper temp file
100 run :: [ProgramInvocation] -> IO ()
101 run [] = return ()
102 run [inv] = runProgramInvocation verbosity inv
103 run (inv : invs) = do
104 runProgramInvocation verbosity inv
105 renameFile target tmpfile
106 run invs