{-# OPTIONS_GHC -Wno-name-shadowing #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE CPP #-}
module GHC.Toolchain.Tools.Link ( CcLink(..), findCcLink ) where
import Control.Monad (when)
import Data.List (isInfixOf)
import System.FilePath
import GHC.Platform.ArchOS
import GHC.Toolchain.Prelude
import GHC.Toolchain.Utils
import GHC.Toolchain.Program
import GHC.Toolchain.Tools.Cc
import GHC.Toolchain.Tools.Readelf
data CcLink = CcLink { CcLink -> Program
ccLinkProgram :: Program
, CcLink -> Bool
ccLinkSupportsNoPie :: Bool
, CcLink -> Bool
ccLinkSupportsCompactUnwind :: Bool
, CcLink -> Bool
ccLinkSupportsFilelist :: Bool
, CcLink -> Bool
ccLinkSupportsSingleModule :: Bool
, CcLink -> Bool
ccLinkIsGnu :: Bool
}
deriving (ReadPrec [CcLink]
ReadPrec CcLink
Int -> ReadS CcLink
ReadS [CcLink]
(Int -> ReadS CcLink)
-> ReadS [CcLink]
-> ReadPrec CcLink
-> ReadPrec [CcLink]
-> Read CcLink
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS CcLink
readsPrec :: Int -> ReadS CcLink
$creadList :: ReadS [CcLink]
readList :: ReadS [CcLink]
$creadPrec :: ReadPrec CcLink
readPrec :: ReadPrec CcLink
$creadListPrec :: ReadPrec [CcLink]
readListPrec :: ReadPrec [CcLink]
Read, CcLink -> CcLink -> Bool
(CcLink -> CcLink -> Bool)
-> (CcLink -> CcLink -> Bool) -> Eq CcLink
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CcLink -> CcLink -> Bool
== :: CcLink -> CcLink -> Bool
$c/= :: CcLink -> CcLink -> Bool
/= :: CcLink -> CcLink -> Bool
Eq, Eq CcLink
Eq CcLink =>
(CcLink -> CcLink -> Ordering)
-> (CcLink -> CcLink -> Bool)
-> (CcLink -> CcLink -> Bool)
-> (CcLink -> CcLink -> Bool)
-> (CcLink -> CcLink -> Bool)
-> (CcLink -> CcLink -> CcLink)
-> (CcLink -> CcLink -> CcLink)
-> Ord CcLink
CcLink -> CcLink -> Bool
CcLink -> CcLink -> Ordering
CcLink -> CcLink -> CcLink
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: CcLink -> CcLink -> Ordering
compare :: CcLink -> CcLink -> Ordering
$c< :: CcLink -> CcLink -> Bool
< :: CcLink -> CcLink -> Bool
$c<= :: CcLink -> CcLink -> Bool
<= :: CcLink -> CcLink -> Bool
$c> :: CcLink -> CcLink -> Bool
> :: CcLink -> CcLink -> Bool
$c>= :: CcLink -> CcLink -> Bool
>= :: CcLink -> CcLink -> Bool
$cmax :: CcLink -> CcLink -> CcLink
max :: CcLink -> CcLink -> CcLink
$cmin :: CcLink -> CcLink -> CcLink
min :: CcLink -> CcLink -> CcLink
Ord)
instance Show CcLink where
show :: CcLink -> String
show CcLink{Bool
Program
ccLinkProgram :: CcLink -> Program
ccLinkSupportsNoPie :: CcLink -> Bool
ccLinkSupportsCompactUnwind :: CcLink -> Bool
ccLinkSupportsFilelist :: CcLink -> Bool
ccLinkSupportsSingleModule :: CcLink -> Bool
ccLinkIsGnu :: CcLink -> Bool
ccLinkProgram :: Program
ccLinkSupportsNoPie :: Bool
ccLinkSupportsCompactUnwind :: Bool
ccLinkSupportsFilelist :: Bool
ccLinkSupportsSingleModule :: Bool
ccLinkIsGnu :: Bool
..} = [String] -> String
unlines
[ String
"CcLink"
, String
"{ ccLinkProgram = " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Program -> String
forall a. Show a => a -> String
show Program
ccLinkProgram
, String
", ccLinkSupportsNoPie = " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> String
forall a. Show a => a -> String
show Bool
ccLinkSupportsNoPie
, String
", ccLinkSupportsCompactUnwind = " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> String
forall a. Show a => a -> String
show Bool
ccLinkSupportsCompactUnwind
, String
", ccLinkSupportsFilelist = " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> String
forall a. Show a => a -> String
show Bool
ccLinkSupportsFilelist
, String
", ccLinkSupportsSingleModule = " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> String
forall a. Show a => a -> String
show Bool
ccLinkSupportsSingleModule
, String
", ccLinkIsGnu = " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Bool -> String
forall a. Show a => a -> String
show Bool
ccLinkIsGnu
, String
"}"
]
_ccLinkProgram :: Lens CcLink Program
_ccLinkProgram :: Lens CcLink Program
_ccLinkProgram = (CcLink -> Program)
-> (Program -> CcLink -> CcLink) -> Lens CcLink Program
forall a b. (a -> b) -> (b -> a -> a) -> Lens a b
Lens CcLink -> Program
ccLinkProgram (\Program
x CcLink
o -> CcLink
o{ccLinkProgram=x})
findCcLink :: String
-> ProgOpt
-> ProgOpt
-> Bool
-> ArchOS -> Cc -> Maybe Readelf -> M CcLink
findCcLink :: String
-> ProgOpt
-> ProgOpt
-> Bool
-> ArchOS
-> Cc
-> Maybe Readelf
-> M CcLink
findCcLink String
target ProgOpt
ld ProgOpt
progOpt Bool
ldOverride ArchOS
archOs Cc
cc Maybe Readelf
readelf = String -> M CcLink -> M CcLink
forall a. Show a => String -> M a -> M a
checking String
"for C compiler for linking command" (M CcLink -> M CcLink) -> M CcLink -> M CcLink
forall a b. (a -> b) -> a -> b
$ do
rawCcLink <- String -> ProgOpt -> [String] -> M Program
findProgram String
"C compiler for linking" ProgOpt
progOpt [] M Program -> M Program -> M Program
forall a. M a -> M a -> M a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Program -> M Program
forall a. a -> M a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ProgOpt -> String -> [String] -> Program
programFromOpt ProgOpt
progOpt (Program -> String
prgPath (Program -> String) -> Program -> String
forall a b. (a -> b) -> a -> b
$ Cc -> Program
ccProgram Cc
cc) [])
ccLinkProgram <- case (poPath ld, poFlags progOpt) of
(Maybe String
_, Just [String]
_) ->
Program -> M Program
forall a. a -> M a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Program
rawCcLink
(Just {}, Maybe [String]
_) ->
Program -> M Program
forall a. a -> M a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Program
rawCcLink
(Maybe String, Maybe [String])
_ -> do
Bool -> Cc -> Program -> M Program
findLinkFlags Bool
ldOverride Cc
cc Program
rawCcLink M Program -> M Program -> M Program
forall a. M a -> M a -> M a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Program -> M Program
forall a. a -> M a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Program
rawCcLink
ccLinkProgram <- linkSupportsTarget archOs cc target ccLinkProgram
ccLinkSupportsNoPie <- checkSupportsNoPie cc ccLinkProgram
ccLinkSupportsCompactUnwind <- checkSupportsCompactUnwind archOs cc ccLinkProgram
ccLinkSupportsFilelist <- checkSupportsFilelist cc ccLinkProgram
ccLinkSupportsSingleModule <- checkSupportsSingleModule archOs cc ccLinkProgram
ccLinkIsGnu <- checkLinkIsGnu archOs ccLinkProgram
checkBfdCopyBug archOs cc readelf ccLinkProgram
ccLinkProgram <- addPlatformDepLinkFlags archOs cc ccLinkProgram
let ccLink = CcLink {Program
ccLinkProgram :: Program
ccLinkProgram :: Program
ccLinkProgram, Bool
ccLinkSupportsNoPie :: Bool
ccLinkSupportsNoPie :: Bool
ccLinkSupportsNoPie,
Bool
ccLinkSupportsCompactUnwind :: Bool
ccLinkSupportsCompactUnwind :: Bool
ccLinkSupportsCompactUnwind, Bool
ccLinkSupportsFilelist :: Bool
ccLinkSupportsFilelist :: Bool
ccLinkSupportsFilelist,
Bool
ccLinkSupportsSingleModule :: Bool
ccLinkSupportsSingleModule :: Bool
ccLinkSupportsSingleModule, Bool
ccLinkIsGnu :: Bool
ccLinkIsGnu :: Bool
ccLinkIsGnu}
ccLink <- linkRequiresNoFixupChains archOs cc ccLink
ccLink <- linkRequiresNoWarnDuplicateLibraries archOs cc ccLink
return ccLink
findLinkFlags :: Bool -> Cc -> Program -> M Program
findLinkFlags :: Bool -> Cc -> Program -> M Program
findLinkFlags Bool
enableOverride Cc
cc Program
ccLink
| Bool
enableOverride Bool -> Bool -> Bool
&& Bool
doLinkerSearch =
String -> [M Program] -> M Program
forall b. String -> [M b] -> M b
oneOf String
"this can't happen"
[
do _ <- String -> ProgOpt -> [String] -> M Program
findProgram (String
linker String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" linker") ProgOpt
emptyProgOpt [String
"ld."String -> ShowS
forall a. [a] -> [a] -> [a]
++String
linker]
prog <$ checkLinkWorks cc prog
| String
linker <- [String
"lld", String
"gold", String
"bfd"]
, let prog :: Program
prog = Lens Program [String]
-> ([String] -> [String]) -> Program -> Program
forall a b. Lens a b -> (b -> b) -> a -> a
over Lens Program [String]
_prgFlags ([String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++[String
"-fuse-ld="String -> ShowS
forall a. [a] -> [a] -> [a]
++String
linker]) Program
ccLink
]
M Program -> M Program -> M Program
forall a. M a -> M a -> M a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Program
ccLink Program -> M () -> M Program
forall a b. a -> M b -> M a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Cc -> Program -> M ()
checkLinkWorks Cc
cc Program
ccLink)
| Bool
otherwise =
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return Program
ccLink
linkSupportsTarget :: ArchOS -> Cc -> String -> Program -> M Program
linkSupportsTarget :: ArchOS -> Cc -> String -> Program -> M Program
linkSupportsTarget ArchOS
archOs Cc
cc String
target Program
link =
String -> M Program -> M Program
forall a. Show a => String -> M a -> M a
checking String
"whether cc linker supports --target" (M Program -> M Program) -> M Program -> M Program
forall a b. (a -> b) -> a -> b
$
ArchOS
-> Lens Program Program
-> (Program -> M ())
-> String
-> Program
-> M Program
forall compiler.
ArchOS
-> Lens compiler Program
-> (compiler -> M ())
-> String
-> compiler
-> M compiler
supportsTarget ArchOS
archOs ((Program -> Program)
-> (Program -> Program -> Program) -> Lens Program Program
forall a b. (a -> b) -> (b -> a -> a) -> Lens a b
Lens Program -> Program
forall a. a -> a
id Program -> Program -> Program
forall a b. a -> b -> a
const) (Cc -> Program -> M ()
checkLinkWorks Cc
cc) String
target Program
link
doLinkerSearch :: Bool
#if defined(linux_HOST_OS)
doLinkerSearch :: Bool
doLinkerSearch = Bool
True
#else
doLinkerSearch = False
#endif
checkSupportsNoPie :: Cc -> Program -> M Bool
checkSupportsNoPie :: Cc -> Program -> M Bool
checkSupportsNoPie Cc
cc Program
ccLink = String -> M Bool -> M Bool
forall a. Show a => String -> M a -> M a
checking String
"whether the cc linker supports -no-pie" (M Bool -> M Bool) -> M Bool -> M Bool
forall a b. (a -> b) -> a -> b
$
(String -> M Bool) -> M Bool
forall a. (String -> M a) -> M a
withTempDir ((String -> M Bool) -> M Bool) -> (String -> M Bool) -> M Bool
forall a b. (a -> b) -> a -> b
$ \String
dir -> do
let test_o :: String
test_o = String
dir String -> ShowS
</> String
"test.o"
let test :: String
test = String
dir String -> ShowS
</> String
"test"
Cc -> String -> String -> M ()
compileC Cc
cc String
test_o String
"int main() { return 0; }"
(code, out, err) <- Program -> [String] -> M (ExitCode, String, String)
readProgram Program
ccLink [String
"-no-pie", String
"-Werror", String
test_o, String
"-o", String
test]
return (isSuccess code && not ("unrecognized" `isInfixOf` out) && not ("unrecognized" `isInfixOf` err))
checkSupportsCompactUnwind :: ArchOS -> Cc -> Program -> M Bool
checkSupportsCompactUnwind :: ArchOS -> Cc -> Program -> M Bool
checkSupportsCompactUnwind ArchOS
archOs Cc
cc Program
ccLink
| OS
OSDarwin <- ArchOS -> OS
archOS_OS ArchOS
archOs = String -> M Bool -> M Bool
forall a. Show a => String -> M a -> M a
checking String
"whether the cc linker understands -no_compact_unwind" (M Bool -> M Bool) -> M Bool -> M Bool
forall a b. (a -> b) -> a -> b
$
(String -> M Bool) -> M Bool
forall a. (String -> M a) -> M a
withTempDir ((String -> M Bool) -> M Bool) -> (String -> M Bool) -> M Bool
forall a b. (a -> b) -> a -> b
$ \String
dir -> do
let test_o :: String
test_o = String
dir String -> ShowS
</> String
"test.o"
test2_o :: String
test2_o = String
dir String -> ShowS
</> String
"test2.o"
Cc -> String -> String -> M ()
compileC Cc
cc String
test_o String
"int foo() { return 0; }"
exitCode <- Program -> [String] -> M ExitCode
runProgram Program
ccLink [String
"-r", String
"-Wl,-no_compact_unwind", String
"-o", String
test2_o, String
test_o]
return $ isSuccess exitCode
| Bool
otherwise = Bool -> M Bool
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
checkSupportsFilelist :: Cc -> Program -> M Bool
checkSupportsFilelist :: Cc -> Program -> M Bool
checkSupportsFilelist Cc
cc Program
ccLink = String -> M Bool -> M Bool
forall a. Show a => String -> M a -> M a
checking String
"whether the cc linker understands -filelist" (M Bool -> M Bool) -> M Bool -> M Bool
forall a b. (a -> b) -> a -> b
$
(String -> M Bool) -> M Bool
forall a. (String -> M a) -> M a
withTempDir ((String -> M Bool) -> M Bool) -> (String -> M Bool) -> M Bool
forall a b. (a -> b) -> a -> b
$ \String
dir -> do
let test_o :: String
test_o = String
dir String -> ShowS
</> String
"test.o"
test1_o :: String
test1_o = String
dir String -> ShowS
</> String
"test1.o"
test2_o :: String
test2_o = String
dir String -> ShowS
</> String
"test2.o"
test_ofiles :: String
test_ofiles = String
dir String -> ShowS
</> String
"test.o-files"
Cc -> String -> String -> M ()
compileC Cc
cc String
test1_o String
"int foo() { return 0; }"
Cc -> String -> String -> M ()
compileC Cc
cc String
test2_o String
"int bar() { return 0; }"
String -> String -> M ()
writeFile String
test_ofiles ([String] -> String
unlines [String
test1_o,String
test2_o])
exitCode <- Program -> [String] -> M ExitCode
runProgram Program
ccLink [String
"-r", String
"-Wl,-filelist", String
test_ofiles, String
"-o", String
test_o]
return (isSuccess exitCode)
checkSupportsSingleModule :: ArchOS -> Cc -> Program -> M Bool
checkSupportsSingleModule :: ArchOS -> Cc -> Program -> M Bool
checkSupportsSingleModule ArchOS
archOs Cc
cc Program
link
| ArchOS Arch
_ OS
OSDarwin <- ArchOS
archOs
= String -> M Bool -> M Bool
forall a. Show a => String -> M a -> M a
checking String
"whether the darwin linker supports -single_module" (M Bool -> M Bool) -> M Bool -> M Bool
forall a b. (a -> b) -> a -> b
$ do
(String -> M Bool) -> M Bool
forall a. (String -> M a) -> M a
withTempDir ((String -> M Bool) -> M Bool) -> (String -> M Bool) -> M Bool
forall a b. (a -> b) -> a -> b
$ \String
dir -> do
let test_dylib :: String
test_dylib = String
dir String -> ShowS
</> String
"test.dylib"
test_c :: String
test_c = String
dir String -> ShowS
</> String
"test.c"
testmain_o :: String
testmain_o = String
dir String -> ShowS
</> String
"testmain.o"
testmain :: String
testmain = String
dir String -> ShowS
</> String
"testmain"
Cc -> String -> String -> M ()
compileC Cc
cc String
testmain_o String
"extern int foo(int); int main() { return foo(5); }"
String -> String -> M ()
writeFile String
test_c String
"int foo(int x) { return x*x; }"
_ <- Program -> [String] -> M ExitCode
runProgram (Cc -> Program
ccProgram Cc
cc) [String
"-shared", String
"-o", String
test_dylib, String
test_c]
(_, out, err) <- readProgram link ["-Wl,-single_module", "-o", testmain, test_dylib, testmain_o]
return $ not $ "obsolete" `isInfixOf` err || "obsolete" `isInfixOf` out
| Bool
otherwise
= Bool -> M Bool
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
checkLinkWorks :: Cc -> Program -> M ()
checkLinkWorks :: Cc -> Program -> M ()
checkLinkWorks Cc
cc Program
ccLink = (String -> M ()) -> M ()
forall a. (String -> M a) -> M a
withTempDir ((String -> M ()) -> M ()) -> (String -> M ()) -> M ()
forall a b. (a -> b) -> a -> b
$ \String
dir -> do
let test_o :: String
test_o = String
dir String -> ShowS
</> String
"test.o"
main_o :: String
main_o = String
dir String -> ShowS
</> String
"main.o"
Cc -> String -> String -> M ()
compileC Cc
cc String
test_o String
"int f(int a) { return 2*a; }"
Cc -> String -> String -> M ()
compileC Cc
cc String
main_o String
"int f(int a); int main(int argc, char **argv) { return f(0); }"
let out :: String
out = String
dir String -> ShowS
</> String
"test"
err :: String
err = String
"linker didn't produce any output"
Program -> [String] -> M ()
callProgram Program
ccLink [String
"-Werror", String
"-o", String
out, String
test_o, String
main_o]
String -> String -> M ()
expectFileExists String
out String
err
M () -> M () -> M ()
forall a. M a -> M a -> M a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> String -> M ()
expectFileExists (String
out String -> ShowS
<.> String
"exe") String
err
checkLinkIsGnu :: ArchOS -> Program -> M Bool
checkLinkIsGnu :: ArchOS -> Program -> M Bool
checkLinkIsGnu ArchOS
archOs Program
_
| Arch
ArchJavaScript <- ArchOS -> Arch
archOS_arch ArchOS
archOs = Bool -> M Bool
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
checkLinkIsGnu ArchOS
_ Program
ccLink = do
out <- Program -> [String] -> M String
readProgramStdout Program
ccLink [String
"-Wl,--version"]
return ("GNU" `isInfixOf` out)
checkBfdCopyBug :: ArchOS -> Cc -> Maybe Readelf -> Program -> M ()
checkBfdCopyBug :: ArchOS -> Cc -> Maybe Readelf -> Program -> M ()
checkBfdCopyBug ArchOS
archOs Cc
cc Maybe Readelf
mb_readelf Program
ccLink
| ArchARM{} <- ArchOS -> Arch
archOS_arch ArchOS
archOs =
String -> M () -> M ()
forall a. Show a => String -> M a -> M a
checking String
"whether linker is affected by binutils #16177" (M () -> M ()) -> M () -> M ()
forall a b. (a -> b) -> a -> b
$ (String -> M ()) -> M ()
forall a. (String -> M a) -> M a
withTempDir ((String -> M ()) -> M ()) -> (String -> M ()) -> M ()
forall a b. (a -> b) -> a -> b
$ \String
dir -> do
readelf <- case Maybe Readelf
mb_readelf of
Just Readelf
x -> Readelf -> M Readelf
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return Readelf
x
Maybe Readelf
Nothing -> String -> M Readelf
forall a. String -> M a
throwE String
"readelf needed to check for binutils #16177 but not found. Please set --readelf (and --readelf-opts as necessary)."
let test_o = String
dir String -> ShowS
</> String
"test.o"
lib_o = String
dir String -> ShowS
</> String
"lib.o"
lib_so = String
dir String -> ShowS
</> String
"lib.so"
main_o = String
dir String -> ShowS
</> String
"main.o"
exe = String
dir String -> ShowS
</> String
"exe"
compileAsm cc lib_o progLib
callProgram ccLink ["-shared", lib_o, "-o", lib_so]
compileC cc main_o progMain
compileAsm cc test_o progTest
callProgram ccLink ["-o", exe, test_o, main_o, lib_so]
out <- readProgramStdout (readelfProgram readelf) ["-r", exe]
when ("R_ARM_COPY" `isInfixOf` out) $
throwE "Your linker is affected by binutils #16177. Please choose a different linker."
| Bool
otherwise = () -> M ()
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where
progTest :: String
progTest = [String] -> String
unlines
[ String
".data"
, String
" .globl data_object"
, String
"object_reference:"
, String
" .long data_object"
, String
" .size object_reference, 4"
]
progLib :: String
progLib = [String] -> String
unlines
[ String
" .data"
, String
" .globl data_object"
, String
" .type data_object, %object"
, String
" .size data_object, 4"
, String
"data_object:"
, String
" .long 123"
]
progMain :: String
progMain =
String
"int main(int argc, char **argv) { return 0; }"
addPlatformDepLinkFlags :: ArchOS -> Cc -> Program -> M Program
addPlatformDepLinkFlags :: ArchOS -> Cc -> Program -> M Program
addPlatformDepLinkFlags ArchOS
archOs Cc
cc Program
ccLink0 = do
ccLink1 <- ArchOS -> Cc -> Program -> M Program
addNoAsNeeded ArchOS
archOs Cc
cc Program
ccLink0
ccLink2 <- addOSMinGW32CcFlags archOs cc ccLink1
case archOs of
ArchOS Arch
ArchX86_64 OS
OSSolaris2 ->
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> M Program) -> Program -> M Program
forall a b. (a -> b) -> a -> b
$ Program
ccLink2 Program -> (Program -> Program) -> Program
forall a b. a -> (a -> b) -> b
& Lens Program [String]
_prgFlags Lens Program [String] -> String -> Program -> Program
forall a b. Lens a [b] -> b -> a -> a
%++ String
"-m64"
ArchOS Arch
ArchAlpha OS
_ ->
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> M Program) -> Program -> M Program
forall a b. (a -> b) -> a -> b
$ Program
ccLink2 Program -> (Program -> Program) -> Program
forall a b. a -> (a -> b) -> b
& Lens Program [String]
-> ([String] -> [String]) -> Program -> Program
forall a b. Lens a b -> (b -> b) -> a -> a
over Lens Program [String]
_prgFlags ([String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++[String
"-w",String
"-mieee",String
"-D_REENTRANT"])
ArchOS ArchARM{} OS
OSFreeBSD ->
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> M Program) -> Program -> M Program
forall a b. (a -> b) -> a -> b
$ Program
ccLink2 Program -> (Program -> Program) -> Program
forall a b. a -> (a -> b) -> b
& Lens Program [String]
_prgFlags Lens Program [String] -> String -> Program -> Program
forall a b. Lens a [b] -> b -> a -> a
%++ String
"-Wl,-z,noexecstack"
ArchOS ArchARM{} OS
OSLinux ->
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> M Program) -> Program -> M Program
forall a b. (a -> b) -> a -> b
$ Program
ccLink2 Program -> (Program -> Program) -> Program
forall a b. a -> (a -> b) -> b
& Lens Program [String]
_prgFlags Lens Program [String] -> String -> Program -> Program
forall a b. Lens a [b] -> b -> a -> a
%++ String
"-Wl,-z,noexecstack"
ArchOS Arch
ArchAArch64 OS
OSFreeBSD ->
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> M Program) -> Program -> M Program
forall a b. (a -> b) -> a -> b
$ Program
ccLink2 Program -> (Program -> Program) -> Program
forall a b. a -> (a -> b) -> b
& Lens Program [String]
_prgFlags Lens Program [String] -> String -> Program -> Program
forall a b. Lens a [b] -> b -> a -> a
%++ String
"-Wl,-z,noexecstack"
ArchOS Arch
ArchAArch64 OS
OSLinux ->
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> M Program) -> Program -> M Program
forall a b. (a -> b) -> a -> b
$ Program
ccLink2 Program -> (Program -> Program) -> Program
forall a b. a -> (a -> b) -> b
& Lens Program [String]
_prgFlags Lens Program [String] -> String -> Program -> Program
forall a b. Lens a [b] -> b -> a -> a
%++ String
"-Wl,-z,noexecstack"
ArchOS Arch
ArchAArch64 OS
OSNetBSD ->
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> M Program) -> Program -> M Program
forall a b. (a -> b) -> a -> b
$ Program
ccLink2 Program -> (Program -> Program) -> Program
forall a b. a -> (a -> b) -> b
& Lens Program [String]
_prgFlags Lens Program [String] -> String -> Program -> Program
forall a b. Lens a [b] -> b -> a -> a
%++ String
"-Wl,-z,noexecstack"
ArchOS Arch
ArchPPC OS
OSAIX ->
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> M Program) -> Program -> M Program
forall a b. (a -> b) -> a -> b
$ Program
ccLink2 Program -> (Program -> Program) -> Program
forall a b. a -> (a -> b) -> b
& Lens Program [String]
-> ([String] -> [String]) -> Program -> Program
forall a b. Lens a b -> (b -> b) -> a -> a
over Lens Program [String]
_prgFlags ([String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++[String
"-D_THREAD_SAFE",String
"-Wl,-bnotextro"])
ArchOS
_ ->
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return Program
ccLink2
addOSMinGW32CcFlags :: ArchOS -> Cc -> Program -> M Program
addOSMinGW32CcFlags :: ArchOS -> Cc -> Program -> M Program
addOSMinGW32CcFlags ArchOS
archOs Cc
cc Program
link
| ArchOS Arch
_ OS
OSMinGW32 <- ArchOS
archOs = do
Cc -> Program -> M Program
checkFStackCheck Cc
cc Program
link M Program -> M Program -> M Program
forall a. M a -> M a -> M a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> M Program
forall a. String -> M a
throwE String
"Windows requires -fstack-check support yet the C compiler linker appears not to support it"
| Bool
otherwise = Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return Program
link
checkFStackCheck :: Cc -> Program -> M Program
checkFStackCheck :: Cc -> Program -> M Program
checkFStackCheck Cc
cc Program
link = String -> M Program -> M Program
forall a. Show a => String -> M a -> M a
checking String
"that -fstack-check works" (M Program -> M Program) -> M Program -> M Program
forall a b. (a -> b) -> a -> b
$ do
let link' :: Program
link' = Program
link Program -> (Program -> Program) -> Program
forall a b. a -> (a -> b) -> b
& Lens Program [String]
_prgFlags Lens Program [String] -> String -> Program -> Program
forall a b. Lens a [b] -> b -> a -> a
%++ String
"-fstack-check"
Cc -> Program -> M ()
checkLinkWorks Cc
cc Program
link'
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return Program
link'
addNoAsNeeded :: ArchOS -> Cc -> Program -> M Program
addNoAsNeeded :: ArchOS -> Cc -> Program -> M Program
addNoAsNeeded ArchOS
archOs Cc
cc Program
ccLink
| OS
os <- ArchOS -> OS
archOS_OS ArchOS
archOs
, OS -> Bool
osElfTarget OS
os
= String -> M Program -> M Program
forall a. Show a => String -> M a -> M a
checking String
"that --no-as-needed works" (M Program -> M Program) -> M Program -> M Program
forall a b. (a -> b) -> a -> b
$ do
let ccLink' :: Program
ccLink' = Lens Program [String]
-> ([String] -> [String]) -> Program -> Program
forall a b. Lens a b -> (b -> b) -> a -> a
over Lens Program [String]
_prgFlags ([String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++[String
"-Wl,--no-as-needed"]) Program
ccLink
Cc -> Program -> M ()
checkLinkWorks Cc
cc Program
ccLink'
Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return Program
ccLink'
| Bool
otherwise = Program -> M Program
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return Program
ccLink
linkRequiresNoFixupChains :: ArchOS -> Cc -> CcLink -> M CcLink
linkRequiresNoFixupChains :: ArchOS -> Cc -> CcLink -> M CcLink
linkRequiresNoFixupChains ArchOS
archOs Cc
cc CcLink
ccLink
| OS
OSDarwin <- ArchOS -> OS
archOS_OS ArchOS
archOs = String -> M CcLink -> M CcLink
forall a. Show a => String -> M a -> M a
checking String
"whether CC linker requires -no_fixup_chains" (M CcLink -> M CcLink) -> M CcLink -> M CcLink
forall a b. (a -> b) -> a -> b
$
let ccLink' :: CcLink
ccLink' = Lens CcLink [String] -> ([String] -> [String]) -> CcLink -> CcLink
forall a b. Lens a b -> (b -> b) -> a -> a
over (Lens CcLink Program
_ccLinkProgram Lens CcLink Program
-> Lens Program [String] -> Lens CcLink [String]
forall a b c. Lens a b -> Lens b c -> Lens a c
% Lens Program [String]
_prgFlags) ([String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++[String
"-Wl,-no_fixup_chains"]) CcLink
ccLink
in (CcLink
ccLink' CcLink -> M () -> M CcLink
forall a b. a -> M b -> M a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Cc -> Program -> M ()
checkLinkWorks Cc
cc (CcLink -> Program
ccLinkProgram CcLink
ccLink')) M CcLink -> M CcLink -> M CcLink
forall a. M a -> M a -> M a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> CcLink -> M CcLink
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return CcLink
ccLink
| Bool
otherwise = CcLink -> M CcLink
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return CcLink
ccLink
linkRequiresNoWarnDuplicateLibraries :: ArchOS -> Cc -> CcLink -> M CcLink
linkRequiresNoWarnDuplicateLibraries :: ArchOS -> Cc -> CcLink -> M CcLink
linkRequiresNoWarnDuplicateLibraries ArchOS
archOs Cc
cc CcLink
ccLink
| OS
OSDarwin <- ArchOS -> OS
archOS_OS ArchOS
archOs = String -> M CcLink -> M CcLink
forall a. Show a => String -> M a -> M a
checking String
"whether CC linker requires -no_warn_duplicate_libraries" (M CcLink -> M CcLink) -> M CcLink -> M CcLink
forall a b. (a -> b) -> a -> b
$
let ccLink' :: CcLink
ccLink' = Lens CcLink [String] -> ([String] -> [String]) -> CcLink -> CcLink
forall a b. Lens a b -> (b -> b) -> a -> a
over (Lens CcLink Program
_ccLinkProgram Lens CcLink Program
-> Lens Program [String] -> Lens CcLink [String]
forall a b c. Lens a b -> Lens b c -> Lens a c
% Lens Program [String]
_prgFlags) ([String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++[String
"-Wl,-no_warn_duplicate_libraries"]) CcLink
ccLink
in (CcLink
ccLink' CcLink -> M () -> M CcLink
forall a b. a -> M b -> M a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Cc -> Program -> M ()
checkLinkWorks Cc
cc (CcLink -> Program
ccLinkProgram CcLink
ccLink')) M CcLink -> M CcLink -> M CcLink
forall a. M a -> M a -> M a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> CcLink -> M CcLink
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return CcLink
ccLink
| Bool
otherwise = CcLink -> M CcLink
forall a. a -> M a
forall (m :: * -> *) a. Monad m => a -> m a
return CcLink
ccLink