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