Use Cabal directly in place of ghc-cabal + make build root configurable (#531)
[hadrian.git] / src / Rules / Gmp.hs
1 module Rules.Gmp (
2 gmpRules, gmpBuildPath, gmpObjectsDir, gmpLibraryH
3 ) where
4
5 import Base
6 import Context
7 import GHC
8 import Oracles.Setting
9 import Target
10 import Utilities
11
12 gmpBase :: FilePath
13 gmpBase = pkgPath integerGmp -/- "gmp"
14
15 gmpLibraryInTreeH :: FilePath
16 gmpLibraryInTreeH = "include/gmp.h"
17
18 gmpLibrary :: FilePath
19 gmpLibrary = ".libs/libgmp.a"
20
21 -- | GMP is considered a Stage1 package. This determines GMP build directory.
22 gmpContext :: Context
23 gmpContext = vanillaContext Stage1 integerGmp
24
25 -- | Build directory for in-tree GMP library.
26 gmpBuildPath :: Action FilePath
27 gmpBuildPath = buildRoot <&> (-/- buildDir gmpContext -/- "gmp")
28
29 -- | GMP library header, relative to 'gmpBuildPath'.
30 gmpLibraryH :: FilePath
31 gmpLibraryH = "include/ghc-gmp.h"
32
33 -- | Directory for GMP library object files, relative to 'gmpBuildPath'.
34 gmpObjectsDir :: FilePath
35 gmpObjectsDir = "objs"
36
37 configureEnvironment :: Action [CmdOption]
38 configureEnvironment = sequence [ builderEnvironment "CC" $ Cc CompileC Stage1
39 , builderEnvironment "AR" (Ar Unpack Stage1)
40 , builderEnvironment "NM" Nm ]
41
42 gmpRules :: Rules ()
43 gmpRules = do
44 -- Copy appropriate GMP header and object files
45 root <- buildRootRules
46 root <//> gmpLibraryH %> \header -> do
47 windows <- windowsHost
48 configMk <- readFile' =<< (gmpBuildPath <&> (-/- "config.mk"))
49 if not windows && -- TODO: We don't use system GMP on Windows. Fix?
50 any (`isInfixOf` configMk) [ "HaveFrameworkGMP = YES", "HaveLibGmp = YES" ]
51 then do
52 putBuild "| GMP library/framework detected and will be used"
53 copyFile (gmpBase -/- "ghc-gmp.h") header
54 else do
55 putBuild "| No GMP library/framework detected; in tree GMP will be built"
56 gmpPath <- gmpBuildPath
57 need [gmpPath -/- gmpLibrary]
58 createDirectory (gmpPath -/- gmpObjectsDir)
59 top <- topDirectory
60 build $ target gmpContext (Ar Unpack Stage1)
61 [top -/- gmpPath -/- gmpLibrary] [gmpPath -/- gmpObjectsDir]
62 copyFile (gmpPath -/- "gmp.h") header
63 copyFile (gmpPath -/- "gmp.h") (gmpPath -/- gmpLibraryInTreeH)
64
65 -- Build in-tree GMP library
66 root <//> gmpLibrary %> \lib -> do
67 gmpPath <- gmpBuildPath
68 build $ target gmpContext (Make gmpPath) [gmpPath -/- "Makefile"] [lib]
69 putSuccess "| Successfully built custom library 'gmp'"
70
71 -- In-tree GMP header is built by the gmpLibraryH rule
72 root <//> gmpLibraryInTreeH %> \_ -> do
73 gmpPath <- gmpBuildPath
74 need [gmpPath -/- gmpLibraryH]
75
76 -- This causes integerGmp package to be configured, hence creating the files
77 root <//> "gmp/config.mk" %> \_ -> do
78 -- setup-config, triggers `ghc-cabal configure`
79 -- everything of a package should depend on that
80 -- in the first place.
81 setupConfig <- contextPath gmpContext <&> (-/- "setup-config")
82 need [setupConfig]
83
84 -- Run GMP's configure script
85 -- TODO: Get rid of hard-coded @gmp@.
86 root <//> "gmp/Makefile" %> \mk -> do
87 env <- configureEnvironment
88 gmpPath <- gmpBuildPath
89 need [mk <.> "in"]
90 buildWithCmdOptions env $
91 target gmpContext (Configure gmpPath) [mk <.> "in"] [mk]
92
93 -- Extract in-tree GMP sources and apply patches
94 root <//> "gmp/Makefile.in" %> \_ -> do
95 gmpPath <- gmpBuildPath
96 removeDirectory gmpPath
97 -- Note: We use a tarball like gmp-4.2.4-nodoc.tar.bz2, which is
98 -- gmp-4.2.4.tar.bz2 repacked without the doc/ directory contents.
99 -- That's because the doc/ directory contents are under the GFDL,
100 -- which causes problems for Debian.
101 tarball <- unifyPath . fromSingleton "Exactly one GMP tarball is expected"
102 <$> getDirectoryFiles "" [gmpBase -/- "gmp-tarballs/gmp*.tar.bz2"]
103
104 withTempDir $ \dir -> do
105 let tmp = unifyPath dir
106 need [tarball]
107 build $ target gmpContext (Tar Extract) [tarball] [tmp]
108
109 let patch = gmpBase -/- "gmpsrc.patch"
110 patchName = takeFileName patch
111 copyFile patch $ tmp -/- patchName
112 applyPatch tmp patchName
113
114 let name = dropExtension . dropExtension $ takeFileName tarball
115 unpack = fromMaybe . error $ "gmpRules: expected suffix "
116 ++ "-nodoc (found: " ++ name ++ ")."
117 libName = unpack $ stripSuffix "-nodoc" name
118
119 moveDirectory (tmp -/- libName) gmpPath