Minor clean up, taking hlint suggestions
[ghc.git] / src / Rules / Libffi.hs
1 module Rules.Libffi (libffiRules, libffiBuildPath, libffiDependencies) where
2
3 import Hadrian.Utilities
4
5 import Settings.Builders.Common
6 import Settings.Packages.Rts
7 import Target
8 import Utilities
9
10 -- | Libffi is considered a Stage1 package. This determines its build directory.
11 libffiContext :: Context
12 libffiContext = vanillaContext Stage1 libffi
13
14 -- | Build directory for in-tree Libffi library.
15 libffiBuildPath :: Action FilePath
16 libffiBuildPath = buildPath libffiContext
17
18 libffiDependencies :: [FilePath]
19 libffiDependencies = ["ffi.h", "ffitarget.h"]
20
21 libffiLibrary :: FilePath
22 libffiLibrary = "inst/lib/libffi.a"
23
24 fixLibffiMakefile :: FilePath -> String -> String
25 fixLibffiMakefile top =
26 replace "-MD" "-MMD"
27 . replace "@toolexeclibdir@" "$(libdir)"
28 . replace "@INSTALL@" ("$(subst ../install-sh," ++ top ++ "/install-sh,@INSTALL@)")
29
30 -- TODO: remove code duplication (see Settings/Builders/GhcCabal.hs)
31 -- TODO: check code duplication w.r.t. ConfCcArgs
32 configureEnvironment :: Action [CmdOption]
33 configureEnvironment = do
34 cFlags <- interpretInContext libffiContext $ mconcat
35 [ cArgs
36 , getStagedSettingList ConfCcArgs ]
37 ldFlags <- interpretInContext libffiContext ldArgs
38 sequence [ builderEnvironment "CC" $ Cc CompileC Stage1
39 , builderEnvironment "CXX" $ Cc CompileC Stage1
40 , builderEnvironment "LD" Ld
41 , builderEnvironment "AR" (Ar Unpack Stage1)
42 , builderEnvironment "NM" Nm
43 , builderEnvironment "RANLIB" Ranlib
44 , return . AddEnv "CFLAGS" $ unwords cFlags ++ " -w"
45 , return . AddEnv "LDFLAGS" $ unwords ldFlags ++ " -w" ]
46
47 libffiRules :: Rules ()
48 libffiRules = do
49 fmap ("//rts" -/-) libffiDependencies &%> \_ -> do
50 libffiPath <- libffiBuildPath
51 need [libffiPath -/- libffiLibrary]
52
53 "//" ++ libffiLibrary %> \_ -> do
54 useSystemFfi <- flag UseSystemFfi
55 rtsPath <- rtsBuildPath
56 if useSystemFfi
57 then do
58 ffiIncludeDir <- setting FfiIncludeDir
59 putBuild "| System supplied FFI library will be used"
60 forM_ ["ffi.h", "ffitarget.h"] $ \file ->
61 copyFile (ffiIncludeDir -/- file) (rtsPath -/- file)
62 putSuccess "| Successfully copied system FFI library header files"
63 else do
64 libffiPath <- libffiBuildPath
65 build $ target libffiContext (Make libffiPath) [] []
66
67 hs <- getDirectoryFiles "" [libffiPath -/- "inst/include/*"]
68 forM_ hs $ \header ->
69 copyFile header (rtsPath -/- takeFileName header)
70
71 ways <- interpretInContext libffiContext (getLibraryWays <> getRtsWays)
72 forM_ (nubOrd ways) $ \way -> do
73 rtsLib <- rtsLibffiLibrary way
74 copyFileUntracked (libffiPath -/- libffiLibrary) rtsLib
75
76 putSuccess "| Successfully built custom library 'libffi'"
77
78 "//libffi/Makefile.in" %> \mkIn -> do
79 libffiPath <- libffiBuildPath
80 removeDirectory libffiPath
81 tarball <- unifyPath . fromSingleton "Exactly one LibFFI tarball is expected"
82 <$> getDirectoryFiles "" ["libffi-tarballs/libffi*.tar.gz"]
83
84 need [tarball]
85 -- Go from 'libffi-3.99999+git20171002+77e130c.tar.gz' to 'libffi-3.99999'
86 let libname = takeWhile (/= '+') $ takeFileName tarball
87
88 root <- buildRoot
89 removeDirectory (root -/- libname)
90 -- TODO: Simplify.
91 actionFinally (do
92 build $ target libffiContext (Tar Extract) [tarball] [root]
93 moveDirectory (root -/- libname) libffiPath) $
94 removeFiles root [libname <//> "*"]
95
96 top <- topDirectory
97 fixFile mkIn (fixLibffiMakefile top)
98
99 -- TODO: Get rid of hard-coded @libffi@.
100 "//libffi/Makefile" %> \mk -> do
101 need [mk <.> "in"]
102 libffiPath <- libffiBuildPath
103 forM_ ["config.guess", "config.sub"] $ \file ->
104 copyFile file (libffiPath -/- file)
105
106 env <- configureEnvironment
107 buildWithCmdOptions env $
108 target libffiContext (Configure libffiPath) [mk <.> "in"] [mk]