Update Trac ticket URLs to point to GitLab
[ghc.git] / hadrian / src / Rules / Gmp.hs
1 module Rules.Gmp (gmpRules, gmpBuildPath, gmpObjects, gmpLibraryH) where
2
3 import Base
4 import Context
5 import Oracles.Setting
6 import Packages
7 import Target
8 import Utilities
9
10 -- | Build GMP library objects and return their paths.
11 gmpObjects :: Action [FilePath]
12 gmpObjects = do
13 gmpPath <- gmpBuildPath
14 need [gmpPath -/- gmpLibraryH]
15 -- The line below causes a Shake Lint failure on Windows, which forced us to
16 -- disable Lint by default. See more details here:
17 -- https://gitlab.haskell.org/ghc/ghc/issues/15971.
18 map (unifyPath . (gmpPath -/-)) <$>
19 liftIO (getDirectoryFilesIO gmpPath [gmpObjectsDir -/- "*.o"])
20
21 gmpBase :: FilePath
22 gmpBase = pkgPath integerGmp -/- "gmp"
23
24 gmpLibraryInTreeH :: FilePath
25 gmpLibraryInTreeH = "include/gmp.h"
26
27 gmpLibrary :: FilePath
28 gmpLibrary = ".libs/libgmp.a"
29
30 -- | GMP is considered a Stage1 package. This determines GMP build directory.
31 gmpContext :: Context
32 gmpContext = vanillaContext Stage1 integerGmp
33
34 -- TODO: Location of 'gmpBuildPath' is important: it should be outside any
35 -- package build directory, as otherwise GMP's object files will match build
36 -- patterns of 'compilePackage' rules. We could make 'compilePackage' rules
37 -- more precise to avoid such spurious matching.
38 -- | Build directory for in-tree GMP library.
39 gmpBuildPath :: Action FilePath
40 gmpBuildPath = buildRoot <&> (-/- stageString (stage gmpContext) -/- "gmp")
41
42 -- | Like 'gmpBuildPath' but in the 'Rules' monad.
43 gmpBuildPathRules :: Rules FilePath
44 gmpBuildPathRules = buildRootRules <&> (-/- stageString (stage gmpContext) -/- "gmp")
45
46 -- | GMP library header, relative to 'gmpBuildPath'.
47 gmpLibraryH :: FilePath
48 gmpLibraryH = "include/ghc-gmp.h"
49
50 -- | Directory for GMP library object files, relative to 'gmpBuildPath'.
51 gmpObjectsDir :: FilePath
52 gmpObjectsDir = "objs"
53
54 configureEnvironment :: Action [CmdOption]
55 configureEnvironment = sequence [ builderEnvironment "CC" $ Cc CompileC Stage1
56 , builderEnvironment "AR" (Ar Unpack Stage1)
57 , builderEnvironment "NM" Nm ]
58
59 gmpRules :: Rules ()
60 gmpRules = do
61 -- Copy appropriate GMP header and object files
62 gmpPath <- gmpBuildPathRules
63 gmpPath -/- gmpLibraryH %> \header -> do
64 windows <- windowsHost
65 configMk <- readFile' =<< (buildPath gmpContext <&> (-/- "config.mk"))
66 if not windows && -- TODO: We don't use system GMP on Windows. Fix?
67 any (`isInfixOf` configMk) [ "HaveFrameworkGMP = YES", "HaveLibGmp = YES" ]
68 then do
69 putBuild "| GMP library/framework detected and will be used"
70 copyFile (gmpBase -/- "ghc-gmp.h") header
71 else do
72 putBuild "| No GMP library/framework detected; in tree GMP will be built"
73 need [gmpPath -/- gmpLibrary]
74 createDirectory (gmpPath -/- gmpObjectsDir)
75 top <- topDirectory
76 build $ target gmpContext (Ar Unpack Stage1)
77 [top -/- gmpPath -/- gmpLibrary] [gmpPath -/- gmpObjectsDir]
78 objs <- liftIO $ getDirectoryFilesIO "." [gmpPath -/- gmpObjectsDir -/- "*"]
79 produces objs
80 copyFileUntracked (gmpPath -/- "gmp.h") header
81
82 -- Build in-tree GMP library, prioritised so that it matches "before"
83 -- the generic @.a@ library rule in 'Rules.Library'.
84 priority 2.0 $ gmpPath -/- gmpLibrary %> \lib -> do
85 build $ target gmpContext (Make gmpPath) [gmpPath -/- "Makefile"] [lib]
86 putSuccess "| Successfully built custom library 'gmp'"
87
88 gmpPath -/- gmpLibraryInTreeH %> copyFile (gmpPath -/- gmpLibraryH)
89
90 root <- buildRootRules
91 root -/- buildDir gmpContext -/- gmpLibraryH %>
92 copyFile (gmpPath -/- gmpLibraryH)
93
94 -- This file is created when 'integerGmp' is configured.
95 gmpPath -/- "config.mk" %> \_ -> ensureConfigured gmpContext
96
97 -- Run GMP's configure script
98 gmpPath -/- "Makefile" %> \mk -> do
99 env <- configureEnvironment
100 need [mk <.> "in"]
101 buildWithCmdOptions env $
102 target gmpContext (Configure gmpPath) [mk <.> "in"] [mk]
103
104 -- Extract in-tree GMP sources and apply patches
105 fmap (gmpPath -/-) ["Makefile.in", "configure"] &%> \_ -> do
106 top <- topDirectory
107 removeDirectory gmpPath
108 -- Note: We use a tarball like gmp-4.2.4-nodoc.tar.bz2, which is
109 -- gmp-4.2.4.tar.bz2 repacked without the doc/ directory contents.
110 -- That's because the doc/ directory contents are under the GFDL,
111 -- which causes problems for Debian.
112 tarball <- unifyPath . fromSingleton "Exactly one GMP tarball is expected"
113 <$> getDirectoryFiles top [gmpBase -/- "gmp-tarballs/gmp*.tar.bz2"]
114
115 withTempDir $ \dir -> do
116 let tmp = unifyPath dir
117 need [top -/- tarball]
118 build $ target gmpContext (Tar Extract) [top -/- tarball] [tmp]
119
120 let patch = gmpBase -/- "gmpsrc.patch"
121 patchName = takeFileName patch
122 copyFile patch $ tmp -/- patchName
123 applyPatch tmp patchName
124
125 let name = dropExtension . dropExtension $ takeFileName tarball
126 unpack = fromMaybe . error $ "gmpRules: expected suffix "
127 ++ "-nodoc (found: " ++ name ++ ")."
128 libName = unpack $ stripSuffix "-nodoc" name
129
130 moveDirectory (tmp -/- libName) gmpPath