-
Notifications
You must be signed in to change notification settings - Fork 6
/
Setup.hs
135 lines (112 loc) · 4.95 KB
/
Setup.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import Distribution.PackageDescription
import Distribution.PackageDescription.Parse
import Distribution.Verbosity
import Distribution.System
import Distribution.Simple
import Distribution.Simple.Utils
import Distribution.Simple.Setup
import Distribution.Simple.Command
import Distribution.Simple.Program
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.PreProcess hiding (ppC2hs)
import Control.Exception
import Control.Monad
import System.Exit (ExitCode (ExitSuccess, ExitFailure))
import System.FilePath
import System.Directory
import System.Environment
import System.IO.Error hiding (catch)
import Prelude hiding (catch)
-- Replicate the invocation of the postConf script, so that we can insert the
-- arguments of --extra-include-dirs and --extra-lib-dirs as paths in CPPFLAGS
-- and LDFLAGS into the environment
--
main :: IO ()
main = defaultMainWithHooks customHooks
where
preprocessors = hookedPreProcessors autoconfUserHooks
customHooks = autoconfUserHooks {
preConf = preConfHook,
postConf = postConfHook,
hookedPreProcessors = ("chs",ppC2hs) : filter (\x -> fst x /= "chs") preprocessors
}
preConfHook :: Args -> ConfigFlags -> IO HookedBuildInfo
preConfHook args flags = do
let verbosity = fromFlag (configVerbosity flags)
confExists <- doesFileExist "configure"
unless confExists $ do
code <- rawSystemExitCode verbosity "autoconf" []
case code of
ExitSuccess -> return ()
ExitFailure c -> die $ "autoconf exited with code " ++ show c
preConf autoconfUserHooks args flags
postConfHook :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()
postConfHook args flags pkg_descr lbi
= let verbosity = fromFlag (configVerbosity flags)
in do
noExtraFlags args
confExists <- doesFileExist "configure"
if confExists
then runConfigureScript verbosity False flags lbi
else die "configure script not found."
pbi <- getHookedBuildInfo verbosity
let pkg_descr' = updatePackageDescription pbi pkg_descr
postConf simpleUserHooks args flags pkg_descr' lbi
runConfigureScript :: Verbosity -> Bool -> ConfigFlags -> LocalBuildInfo -> IO ()
runConfigureScript verbosity backwardsCompatHack flags lbi = do
env <- getEnvironment
(ccProg, ccFlags) <- configureCCompiler verbosity (withPrograms lbi)
let env' = foldr appendToEnvironment env
[("CC", ccProg)
,("CFLAGS", unwords ccFlags)
,("CPPFLAGS", unwords $ map ("-I"++) (configExtraIncludeDirs flags))
,("LDFLAGS", unwords $ map ("-L"++) (configExtraLibDirs flags))
]
handleNoWindowsSH $ rawSystemExitWithEnv verbosity "sh" args env'
where
args = "configure" : configureArgs backwardsCompatHack flags
appendToEnvironment (key, val) [] = [(key, val)]
appendToEnvironment (key, val) (kv@(k, v) : rest)
| key == k = (key, v ++ " " ++ val) : rest
| otherwise = kv : appendToEnvironment (key, val) rest
handleNoWindowsSH action
| buildOS /= Windows
= action
| otherwise
= action
`catch` \ioe -> if isDoesNotExistError ioe
then die notFoundMsg
else throwIO ioe
notFoundMsg = "The package has a './configure' script. This requires a "
++ "Unix compatibility toolchain such as MinGW+MSYS or Cygwin."
getHookedBuildInfo :: Verbosity -> IO HookedBuildInfo
getHookedBuildInfo verbosity = do
maybe_infoFile <- defaultHookedPackageDesc
case maybe_infoFile of
Nothing -> return emptyHookedBuildInfo
Just infoFile -> do
info verbosity $ "Reading parameters from " ++ infoFile
readHookedBuildInfo verbosity infoFile
-- Replicate the default C2HS preprocessor hook here, and inject a value for
-- extra-c2hs-options, if it was present in the buildinfo file
--
-- Everything below copied from Distribution.Simple.PreProcess
--
ppC2hs :: BuildInfo -> LocalBuildInfo -> PreProcessor
ppC2hs bi lbi
= PreProcessor {
platformIndependent = False,
runPreProcessor = \(inBaseDir, inRelativeFile)
(outBaseDir, outRelativeFile) verbosity ->
rawSystemProgramConf verbosity c2hsProgram (withPrograms lbi) . filter (not . null) $
maybe [] words (lookup "x-extra-c2hs-options" (customFieldsBI bi))
++ ["--include=" ++ outBaseDir]
++ ["--cppopts=" ++ opt | opt <- getCppOptions bi lbi]
++ ["--output-dir=" ++ outBaseDir,
"--output=" ++ outRelativeFile,
inBaseDir </> inRelativeFile]
}
getCppOptions :: BuildInfo -> LocalBuildInfo -> [String]
getCppOptions bi lbi
= ["-I" ++ dir | dir <- includeDirs bi]
++ [opt | opt@('-':c:_) <- ccOptions bi, c `elem` "DIU"]