-
Notifications
You must be signed in to change notification settings - Fork 49
/
Setup.hs
133 lines (122 loc) · 6.16 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
{-# LANGUAGE CPP #-}
import Control.Monad
import Distribution.Simple
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Setup
import Distribution.PackageDescription
import Distribution.Simple.Utils
import Distribution.Simple.Program
import Distribution.Verbosity
import System.Process
import System.Directory
import System.FilePath
import System.Exit
import System.IO
main = defaultMainWithHooks hk
where
hk = simpleUserHooks { buildHook = \pd lbi uh bf -> do
-- let ccProg = Program "gcc" undefined undefined undefined
let mConf = lookupProgram ghcProgram (withPrograms lbi)
err = error "Could not determine C compiler"
cc = locationPath . programLocation . maybe err id $ mConf
lbiNew <- checkRDRAND cc lbi >>= checkGetrandom cc >>= checkGetentropy cc
buildHook simpleUserHooks pd lbiNew uh bf
}
compileCheck :: FilePath -> String -> String -> String -> IO Bool
compileCheck cc testName message sourceCode = do
withTempDirectory normal "" testName $ \tmpDir -> do
writeFile (tmpDir ++ "/" ++ testName ++ ".c") sourceCode
ec <- myRawSystemExitCode normal cc [tmpDir </> testName ++ ".c", "-o", tmpDir ++ "/a","-no-hs-main"]
notice normal $ message ++ show (ec == ExitSuccess)
return (ec == ExitSuccess)
addOptions :: [String] -> [String] -> LocalBuildInfo -> LocalBuildInfo
addOptions cArgs hsArgs lbi = lbi {withPrograms = newWithPrograms }
where newWithPrograms1 = userSpecifyArgs "gcc" cArgs (withPrograms lbi)
newWithPrograms = userSpecifyArgs "ghc" (hsArgs ++ map ("-optc" ++) cArgs) newWithPrograms1
checkRDRAND :: FilePath -> LocalBuildInfo -> IO LocalBuildInfo
checkRDRAND cc lbi = do
b <- compileCheck cc "testRDRAND" "Result of RDRAND Test: "
(unlines [ "#include <stdint.h>"
, "int main() {"
, " uint64_t therand;"
, " unsigned char err;"
, " asm volatile(\"rdrand %0 ; setc %1\""
, " : \"=r\" (therand), \"=qm\" (err));"
, " return (!err);"
, "}"
])
return $ if b then addOptions cArgs cArgs lbi else lbi
where cArgs = ["-DHAVE_RDRAND"]
checkGetrandom :: FilePath -> LocalBuildInfo -> IO LocalBuildInfo
checkGetrandom cc lbi = do
libcGetrandom <- compileCheck cc "testLibcGetrandom" "Result of libc getrandom() Test: "
(unlines [ "#define _GNU_SOURCE"
, "#include <errno.h>"
, "#include <sys/random.h>"
, "int main()"
, "{"
, " char tmp;"
, " return getrandom(&tmp, sizeof(tmp), GRND_NONBLOCK) != -1;"
, "}"
])
if libcGetrandom then return $ addOptions cArgsLibc cArgsLibc lbi
else do
syscallGetrandom <- compileCheck cc "testSyscallGetrandom" "Result of syscall getrandom() Test: "
(unlines [ "#define _GNU_SOURCE"
, "#include <errno.h>"
, "#include <unistd.h>"
, "#include <sys/syscall.h>"
, "#include <sys/types.h>"
, "#include <linux/random.h>"
, "static ssize_t getrandom(void* buf, size_t buflen, unsigned int flags)"
, "{"
, " return syscall(SYS_getrandom, buf, buflen, flags);"
, "}"
, "int main()"
, "{"
, " char tmp;"
, " return getrandom(&tmp, sizeof(tmp), GRND_NONBLOCK) != -1;"
, "}"
])
return $ if syscallGetrandom then addOptions cArgs cArgs lbi else lbi
where cArgs = ["-DHAVE_GETRANDOM"]
cArgsLibc = cArgs ++ ["-DHAVE_LIBC_GETRANDOM"]
checkGetentropy :: FilePath -> LocalBuildInfo -> IO LocalBuildInfo
checkGetentropy cc lbi = do
b <- compileCheck cc "testGetentropy" "Result of getentropy() Test: "
(unlines [ "#define _GNU_SOURCE"
, "#include <unistd.h>"
, "int main()"
, "{"
, " char tmp;"
, " return getentropy(&tmp, sizeof(tmp));"
, "}"
])
return $ if b then addOptions cArgs cArgs lbi else lbi
where cArgs = ["-DHAVE_GETENTROPY"]
myRawSystemExitCode :: Verbosity -> FilePath -> [String] -> IO ExitCode
#if MIN_VERSION_Cabal(3,14,0)
myRawSystemExitCode verbosity program arguments =
rawSystemExitCode verbosity Nothing program arguments Nothing
#elif __GLASGOW_HASKELL__ >= 704
-- We know for sure, that if GHC >= 7.4 implies Cabal >= 1.14
myRawSystemExitCode = rawSystemExitCode
#else
-- Legacy branch:
-- We implement our own 'rawSystemExitCode', this will even work if
-- the user happens to have Cabal >= 1.14 installed with GHC 7.0 or
-- 7.2
myRawSystemExitCode verbosity path args = do
printRawCommandAndArgs verbosity path args
hFlush stdout
exitcode <- rawSystem path args
unless (exitcode == ExitSuccess) $ do
debug verbosity $ path ++ " returned " ++ show exitcode
return exitcode
where
printRawCommandAndArgs :: Verbosity -> FilePath -> [String] -> IO ()
printRawCommandAndArgs verbosity path args
| verbosity >= deafening = print (path, args)
| verbosity >= verbose = putStrLn $ unwords (path : args)
| otherwise = return ()
#endif