@@ -20,23 +20,26 @@ main = defaultMainWithHooks hk
2020 let mConf = lookupProgram ghcProgram (withPrograms lbi)
2121 err = error "Could not determine C compiler"
2222 cc = locationPath . programLocation . maybe err id $ mConf
23− b <- canUseRDRAND cc
24− let newWithPrograms1 = userSpecifyArgs "gcc" cArgs (withPrograms lbi)
25− newWithPrograms = userSpecifyArgs "ghc" cArgsHC newWithPrograms1
26− lbiNew = if b then (lbi {withPrograms = newWithPrograms }) else lbi
23+ lbiNew <- checkRDRAND cc lbi >>= checkGetrandom cc >>= checkGetentropy cc
2724 buildHook simpleUserHooks pd lbiNew uh bf
2825 }
2926
30−cArgs :: [String]
31−cArgs = ["-DHAVE_RDRAND"]
27+compileCheck :: FilePath -> String -> String -> String -> IO Bool
28+compileCheck cc testName message sourceCode = do
29+ withTempDirectory normal "" testName $ \tmpDir -> do
30+ writeFile (tmpDir ++ "/" ++ testName ++ ".c") sourceCode
31+ ec <- myRawSystemExitCode normal cc [tmpDir </> testName ++ ".c", "-o", tmpDir ++ "/a","-no-hs-main"]
32+ notice normal $ message ++ show (ec == ExitSuccess)
33+ return (ec == ExitSuccess)
3234
33−cArgsHC :: [String]
34−cArgsHC = cArgs ++ map ("-optc" ++) cArgs
35+addOptions :: [String] -> [String] -> LocalBuildInfo -> LocalBuildInfo
36+addOptions cArgs hsArgs lbi = lbi {withPrograms = newWithPrograms }
37+ where newWithPrograms1 = userSpecifyArgs "gcc" cArgs (withPrograms lbi)
38+ newWithPrograms = userSpecifyArgs "ghc" (hsArgs ++ map ("-optc" ++) cArgs) newWithPrograms1
3539
36−canUseRDRAND :: FilePath -> IO Bool
37−canUseRDRAND cc = do
38− withTempDirectory normal "" "testRDRAND" $ \tmpDir -> do
39− writeFile (tmpDir ++ "/testRDRAND.c")
40+checkRDRAND :: FilePath -> LocalBuildInfo -> IO LocalBuildInfo
41+checkRDRAND cc lbi = do
42+ b <- compileCheck cc "testRDRAND" "Result of RDRAND Test: "
4043 (unlines [ "#include <stdint.h>"
4144 , "int main() {"
4245 , " uint64_t therand;"
@@ -46,9 +49,61 @@ canUseRDRAND cc = do
4649 , " return (!err);"
4750 , "}"
4851 ])
49− ec <- myRawSystemExitCode normal cc [tmpDir </> "testRDRAND.c", "-o", tmpDir ++ "/a.o","-c"]
50− notice normal $ "Result of RDRAND Test: " ++ show (ec == ExitSuccess)
51− return (ec == ExitSuccess)
52+ return $ if b then addOptions cArgs cArgs lbi else lbi
53+ where cArgs = ["-DHAVE_RDRAND"]
54+
55+checkGetrandom :: FilePath -> LocalBuildInfo -> IO LocalBuildInfo
56+checkGetrandom cc lbi = do
57+ libcGetrandom <- compileCheck cc "testLibcGetrandom" "Result of libc getrandom() Test: "
58+ (unlines [ "#define _GNU_SOURCE"
59+ , "#include <errno.h>"
60+ , "#include <sys/random.h>"
61+
62+ , "int main()"
63+ , "{"
64+ , " char tmp;"
65+ , " return getrandom(&tmp, sizeof(tmp), GRND_NONBLOCK) != -1;"
66+ , "}"
67+ ])
68+ if libcGetrandom then return $ addOptions cArgsLibc cArgsLibc lbi
69+ else do
70+ syscallGetrandom <- compileCheck cc "testSyscallGetrandom" "Result of syscall getrandom() Test: "
71+ (unlines [ "#define _GNU_SOURCE"
72+ , "#include <errno.h>"
73+ , "#include <unistd.h>"
74+ , "#include <sys/syscall.h>"
75+ , "#include <sys/types.h>"
76+ , "#include <linux/random.h>"
77+
78+ , "static ssize_t getrandom(void* buf, size_t buflen, unsigned int flags)"
79+ , "{"
80+ , " return syscall(SYS_getrandom, buf, buflen, flags);"
81+ , "}"
82+
83+ , "int main()"
84+ , "{"
85+ , " char tmp;"
86+ , " return getrandom(&tmp, sizeof(tmp), GRND_NONBLOCK) != -1;"
87+ , "}"
88+ ])
89+ return $ if syscallGetrandom then addOptions cArgs cArgs lbi else lbi
90+ where cArgs = ["-DHAVE_GETRANDOM"]
91+ cArgsLibc = cArgs ++ ["-DHAVE_LIBC_GETRANDOM"]
92+
93+checkGetentropy :: FilePath -> LocalBuildInfo -> IO LocalBuildInfo
94+checkGetentropy cc lbi = do
95+ b <- compileCheck cc "testGetentropy" "Result of getentropy() Test: "
96+ (unlines [ "#define _GNU_SOURCE"
97+ , "#include <unistd.h>"
98+
99+ , "int main()"
100+ , "{"
101+ , " char tmp;"
102+ , " return getentropy(&tmp, sizeof(tmp));"
103+ , "}"
104+ ])
105+ return $ if b then addOptions cArgs cArgs lbi else lbi
106+ where cArgs = ["-DHAVE_GETENTROPY"]
52107
53108myRawSystemExitCode :: Verbosity -> FilePath -> [String] -> IO ExitCode
54109#if __GLASGOW_HASKELL__ >= 704