9d77814cfbbe62345a44343513cb1145a3c7e1d2
[hadrian.git] / src / Rules / Libffi.hs
1 module Rules.Libffi (libffiRules, libffiDependencies) where
2
3 import Base
4 import Expression
5 import GHC
6 import Oracles
7 import Rules.Actions
8 import Settings.Builders.Common
9 import Settings.Packages.Rts
10 import Settings.TargetDirectory
11 import Settings.User
12
13 rtsBuildPath :: FilePath
14 rtsBuildPath = targetPath Stage1 rts -/- "build"
15
16 libffiDependencies :: [FilePath]
17 libffiDependencies = (rtsBuildPath -/-) <$> [ "ffi.h", "ffitarget.h" ]
18
19 libffiBuild :: FilePath
20 libffiBuild = "libffi/build"
21
22 libffiLibrary :: FilePath
23 libffiLibrary = libffiBuild -/- "inst/lib/libffi.a"
24
25 libffiMakefile :: FilePath
26 libffiMakefile = libffiBuild -/- "Makefile.in"
27
28 fixLibffiMakefile :: String -> String
29 fixLibffiMakefile = unlines . map
30 ( replace "-MD" "-MMD"
31 . replace "@toolexeclibdir@" "$(libdir)"
32 . replace "@INSTALL@" "$(subst ../install-sh,C:/msys/home/chEEtah/ghc/install-sh,@INSTALL@)"
33 ) . lines
34
35 target :: PartialTarget
36 target = PartialTarget Stage0 libffi
37
38 -- TODO: remove code duplication (see Settings/Builders/GhcCabal.hs)
39 configureEnvironment :: Action [CmdOption]
40 configureEnvironment = do
41 cFlags <- interpretPartial target . fromDiffExpr $ mconcat
42 [ cArgs
43 , argStagedSettingList ConfCcArgs ]
44 ldFlags <- interpretPartial target $ fromDiffExpr ldArgs
45 sequence [ builderEnv "CC" $ Gcc Stage1
46 , builderEnv "CXX" $ Gcc Stage1
47 , builderEnv "LD" Ld
48 , builderEnv "AR" Ar
49 , builderEnv "NM" Nm
50 , builderEnv "RANLIB" Ranlib
51 , return . AddEnv "CFLAGS" $ unwords cFlags ++ " -w"
52 , return . AddEnv "LDFLAGS" $ unwords ldFlags ++ " -w" ]
53 where
54 builderEnv var builder = do
55 needBuilder False builder
56 path <- builderPath builder
57 return $ AddEnv var path
58
59 configureArguments :: Action [String]
60 configureArguments = do
61 top <- topDirectory
62 targetPlatform <- setting TargetPlatform
63 return [ "--prefix=" ++ top ++ "/libffi/build/inst"
64 , "--libdir=" ++ top ++ "/libffi/build/inst/lib"
65 , "--enable-static=yes"
66 , "--enable-shared=no" -- TODO: add support for yes
67 , "--host=" ++ targetPlatform ]
68
69 libffiRules :: Rules ()
70 libffiRules = do
71 libffiDependencies &%> \_ -> do
72 when trackBuildSystem $ need [sourcePath -/- "Rules/Libffi.hs"]
73 liftIO $ removeFiles libffiBuild ["//*"]
74 tarballs <- getDirectoryFiles "" ["libffi-tarballs/libffi*.tar.gz"]
75 when (length tarballs /= 1) $
76 putError $ "libffiRules: exactly one libffi tarball expected"
77 ++ "(found: " ++ show tarballs ++ ")."
78
79 need tarballs
80 build $ fullTarget target Tar tarballs ["libffi-tarballs"]
81
82 let libname = dropExtension . dropExtension . takeFileName $ head tarballs
83 moveDirectory ("libffi-tarballs" -/- libname) libffiBuild
84
85 fixFile libffiMakefile fixLibffiMakefile
86
87 forM_ ["config.guess", "config.sub"] $ \file ->
88 copyFile file (libffiBuild -/- file)
89
90 envs <- configureEnvironment
91 args <- configureArguments
92 runConfigure libffiBuild envs args
93
94 runMake libffiBuild ["MAKEFLAGS="]
95 runMake libffiBuild ["MAKEFLAGS=", "install"]
96
97 forM_ ["ffi.h", "ffitarget.h"] $ \file -> do
98 let src = libffiBuild -/- "inst/lib" -/- libname -/- "include" -/- file
99 copyFile src (rtsBuildPath -/- file)
100
101 libffiName <- rtsLibffiLibraryName
102 copyFile libffiLibrary (rtsBuildPath -/- "lib" ++ libffiName <.> "a")
103
104 putSuccess $ "| Successfully built custom library 'libffi'"
105
106 -- chmod +x libffi/ln
107 -- # wc on OS X has spaces in its output, which libffi's Makefile
108 -- # doesn't expect, so we tweak it to sed them out
109 -- mv libffi/build/Makefile libffi/build/Makefile.orig
110 -- sed "s#wc -w#wc -w | sed 's/ //g'#" < libffi/build/Makefile.orig > libffi/build/Makefile