1fe6174b1e8bf5a6331dee2c9c6abebe4b237628
[ghc.git] / hadrian / src / Rules / Libffi.hs
1 module Rules.Libffi (libffiRules, libffiDependencies) where
2
3 import Hadrian.Utilities
4
5 import Packages
6 import Settings.Builders.Common
7 import Target
8 import Utilities
9
10 libffiDependencies :: [FilePath]
11 libffiDependencies = ["ffi.h", "ffitarget.h"]
12
13 libffiLibrary :: FilePath
14 libffiLibrary = "inst/lib/libffi.a"
15
16 rtsLibffiLibrary :: Stage -> Way -> Action FilePath
17 rtsLibffiLibrary stage way = do
18 name <- libffiLibraryName
19 suf <- libsuf way
20 rtsPath <- rtsBuildPath stage
21 return $ rtsPath -/- "lib" ++ name ++ suf
22
23 fixLibffiMakefile :: FilePath -> String -> String
24 fixLibffiMakefile top =
25 replace "-MD" "-MMD"
26 . replace "@toolexeclibdir@" "$(libdir)"
27 . replace "@INSTALL@" ("$(subst ../install-sh," ++ top ++ "/install-sh,@INSTALL@)")
28
29 -- TODO: check code duplication w.r.t. ConfCcArgs
30 configureEnvironment :: Stage -> Action [CmdOption]
31 configureEnvironment stage = do
32 cFlags <- interpretInContext (libffiContext stage) $ mconcat
33 [ cArgs
34 , getStagedSettingList ConfCcArgs ]
35 ldFlags <- interpretInContext (libffiContext stage) ldArgs
36 sequence [ builderEnvironment "CC" $ Cc CompileC stage
37 , builderEnvironment "CXX" $ Cc CompileC stage
38 , builderEnvironment "LD" (Ld stage)
39 , builderEnvironment "AR" (Ar Unpack stage)
40 , builderEnvironment "NM" Nm
41 , builderEnvironment "RANLIB" Ranlib
42 , return . AddEnv "CFLAGS" $ unwords cFlags ++ " -w"
43 , return . AddEnv "LDFLAGS" $ unwords ldFlags ++ " -w" ]
44
45 libffiRules :: Rules ()
46 libffiRules = forM_ [Stage1 ..] $ \stage -> do
47 root <- buildRootRules
48 let path = root -/- stageString stage
49 libffiPath = path -/- pkgName libffi -/- "build"
50 libffiOuts = [libffiPath -/- libffiLibrary] ++
51 fmap ((path -/- "rts/build") -/-) libffiDependencies
52
53 -- We set a higher priority because this rule overlaps with the build rule
54 -- for static libraries 'Rules.Library.libraryRules'.
55 priority 2.0 $ libffiOuts &%> \(out : _) -> do
56 useSystemFfi <- flag UseSystemFfi
57 rtsPath <- rtsBuildPath stage
58 if useSystemFfi
59 then do
60 ffiIncludeDir <- setting FfiIncludeDir
61 putBuild "| System supplied FFI library will be used"
62 forM_ ["ffi.h", "ffitarget.h"] $ \file ->
63 copyFile (ffiIncludeDir -/- file) (rtsPath -/- file)
64 putSuccess "| Successfully copied system FFI library header files"
65 else do
66 build $ target (libffiContext stage) (Make libffiPath) [] []
67
68 -- Here we produce 'libffiDependencies'
69 hs <- liftIO $ getDirectoryFilesIO "" [libffiPath -/- "inst/include/*"]
70 forM_ hs $ \header -> do
71 let target = rtsPath -/- takeFileName header
72 copyFileUntracked header target
73 produces [target]
74
75 ways <- interpretInContext (libffiContext stage)
76 (getLibraryWays <> getRtsWays)
77 forM_ (nubOrd ways) $ \way -> do
78 rtsLib <- rtsLibffiLibrary stage way
79 copyFileUntracked out rtsLib
80 produces [rtsLib]
81
82 putSuccess "| Successfully built custom library 'libffi'"
83
84 fmap (libffiPath -/-) ["Makefile.in", "configure" ] &%> \[mkIn, _] -> do
85 removeDirectory libffiPath
86 tarball <- unifyPath . fromSingleton "Exactly one LibFFI tarball is expected"
87 <$> getDirectoryFiles "" ["libffi-tarballs/libffi*.tar.gz"]
88
89 need [tarball]
90 -- Go from 'libffi-3.99999+git20171002+77e130c.tar.gz' to 'libffi-3.99999'
91 let libname = takeWhile (/= '+') $ takeFileName tarball
92
93 root <- buildRoot
94 removeDirectory (root -/- libname)
95 -- TODO: Simplify.
96 actionFinally (do
97 build $ target (libffiContext stage) (Tar Extract) [tarball] [path]
98 moveDirectory (path -/- libname) libffiPath) $
99 -- And finally:
100 removeFiles (path) [libname <//> "*"]
101
102 top <- topDirectory
103 fixFile mkIn (fixLibffiMakefile top)
104
105 files <- liftIO $ getDirectoryFilesIO "." [libffiPath <//> "*"]
106 produces files
107
108 fmap (libffiPath -/-) ["Makefile", "config.guess", "config.sub"] &%> \[mk, _, _] -> do
109 need [mk <.> "in"]
110 forM_ ["config.guess", "config.sub"] $ \file -> do
111 copyFile file (libffiPath -/- file)
112 env <- configureEnvironment stage
113 buildWithCmdOptions env $
114 target (libffiContext stage) (Configure libffiPath) [mk <.> "in"] [mk]
115
116 dir <- setting BuildPlatform
117 files <- liftIO $ getDirectoryFilesIO "." [libffiPath -/- dir <//> "*"]
118 produces files