Use Cabal directly in place of ghc-cabal + make build root configurable (#531)
[hadrian.git] / src / Settings / Builders / GhcCabal.hs
1 module Settings.Builders.GhcCabal (
2 ghcCabalBuilderArgs
3 ) where
4
5 import Data.Maybe (fromJust)
6
7 import Builder ( ArMode ( Pack ) )
8 import Context
9 import Flavour
10 import GHC.Packages
11 import Hadrian.Builder (getBuilderPath, needBuilder )
12 import Hadrian.Haskell.Cabal
13 import Settings.Builders.Common
14
15 ghcCabalBuilderArgs :: Args
16 ghcCabalBuilderArgs = mconcat
17 [ builder (GhcCabal Conf) ? do
18 verbosity <- expr getVerbosity
19 top <- expr topDirectory
20 path <- getContextPath
21 stage <- getStage
22 mconcat [ arg "configure"
23 -- don't strip libraries when cross compiling.
24 -- XXX we need to set --with-strip= (stripCmdPath :: Action FilePath), and if it's ':' disable
25 -- stripping as well. As it is now, I believe we might have issues with stripping on
26 -- windows, as I can't see a consumre of `stripCmdPath`.
27 , crossCompiling ? pure [ "--disable-executable-stripping", "--disable-library-stripping" ]
28 , arg "--cabal-file"
29 , arg =<< fromJust . pkgCabalFile <$> getPackage
30 , arg "--distdir"
31 , arg $ top -/- path
32 , arg "--ipid"
33 , arg "$pkg-$version"
34 , arg "--prefix"
35 , arg "${pkgroot}/.."
36 , withStaged $ Ghc CompileHs
37 , withStaged (GhcPkg Update)
38 , withBuilderArgs (GhcPkg Update stage)
39 , bootPackageDatabaseArgs
40 , libraryArgs
41 , configureArgs
42 , bootPackageConstraints
43 , withStaged $ Cc CompileC
44 , notStage0 ? with (Ld stage)
45 , withStaged (Ar Pack)
46 , with Alex
47 , with Happy
48 , verbosity < Chatty ?
49 pure [ "-v0", "--configure-option=--quiet"
50 , "--configure-option=--disable-option-checking"
51 ]
52 ]
53 ]
54
55
56 -- TODO: Isn't vanilla always built? If yes, some conditions are redundant.
57 -- TODO: Need compiler_stage1_CONFIGURE_OPTS += --disable-library-for-ghci?
58 -- TODO: should `elem` be `wayUnit`?
59 libraryArgs :: Args
60 libraryArgs = do
61 ways <- getLibraryWays
62 withGhci <- expr ghcWithInterpreter
63 dynPrograms <- dynamicGhcPrograms <$> expr flavour
64 pure [ if vanilla `elem` ways
65 then "--enable-library-vanilla"
66 else "--disable-library-vanilla"
67 , if vanilla `elem` ways && withGhci && not dynPrograms
68 then "--enable-library-for-ghci"
69 else "--disable-library-for-ghci"
70 , if profiling `elem` ways
71 then "--enable-library-profiling"
72 else "--disable-library-profiling"
73 , if dynamic `elem` ways
74 then "--enable-shared"
75 else "--disable-shared" ]
76
77 -- TODO: LD_OPTS?
78 configureArgs :: Args
79 configureArgs = do
80 top <- expr topDirectory
81 root <- getBuildRoot
82 pkg <- getPackage
83 let conf key expr = do
84 values <- unwords <$> expr
85 not (null values) ?
86 arg ("--configure-option=" ++ key ++ "=" ++ values)
87 cFlags = mconcat [ remove ["-Werror"] cArgs
88 , getStagedSettingList ConfCcArgs
89 , arg $ "-I" ++ top -/- root -/- generatedDir
90 -- See https://github.com/snowleopard/hadrian/issues/523
91 , arg $ "-I" ++ top -/- pkgPath pkg
92 , arg $ "-I" ++ top -/- "includes" ]
93 ldFlags = ldArgs <> (getStagedSettingList ConfGccLinkerArgs)
94 cppFlags = cppArgs <> (getStagedSettingList ConfCppArgs)
95 cldFlags <- unwords <$> (cFlags <> ldFlags)
96 mconcat
97 [ conf "CFLAGS" cFlags
98 , conf "LDFLAGS" ldFlags
99 , conf "CPPFLAGS" cppFlags
100 , not (null cldFlags) ? arg ("--gcc-options=" ++ cldFlags)
101 , conf "--with-iconv-includes" $ arg =<< getSetting IconvIncludeDir
102 , conf "--with-iconv-libraries" $ arg =<< getSetting IconvLibDir
103 , conf "--with-gmp-includes" $ arg =<< getSetting GmpIncludeDir
104 , conf "--with-gmp-libraries" $ arg =<< getSetting GmpLibDir
105 , conf "--with-curses-libraries" $ arg =<< getSetting CursesLibDir
106 , crossCompiling ? (conf "--host" $ arg =<< getSetting TargetPlatformFull)
107 , conf "--with-cc" $ arg =<< getBuilderPath . (Cc CompileC) =<< getStage
108 , notStage0 ? (arg =<< ("--ghc-option=-ghcversion-file=" ++) <$> expr ((-/-) <$> topDirectory <*> ghcVersionH))]
109
110 bootPackageConstraints :: Args
111 bootPackageConstraints = stage0 ? do
112 bootPkgs <- expr $ stagePackages Stage0
113 let pkgs = filter (\p -> p /= compiler && isLibrary p) bootPkgs
114 ctx <- getContext
115 constraints <- expr $ fmap catMaybes $ forM (sort pkgs) $ \pkg -> do
116 version <- pkgVersion (ctx { Context.package = pkg})
117 return $ fmap ((pkgName pkg ++ " == ") ++) version
118 pure $ concat [ ["--constraint", c] | c <- constraints ]
119
120 cppArgs :: Args
121 cppArgs = do
122 root <- getBuildRoot
123 arg $ "-I" ++ root -/- generatedDir
124
125 withBuilderKey :: Builder -> String
126 withBuilderKey b = case b of
127 Ar _ _ -> "--with-ar="
128 Ld _ -> "--with-ld="
129 Cc _ _ -> "--with-gcc="
130 Ghc _ _ -> "--with-ghc="
131 Alex -> "--with-alex="
132 Happy -> "--with-happy="
133 GhcPkg _ _ -> "--with-ghc-pkg="
134 _ -> error $ "withBuilderKey: not supported builder " ++ show b
135
136 -- Adds arguments to builders if needed.
137 withBuilderArgs :: Builder -> Args
138 withBuilderArgs b = case b of
139 GhcPkg _ stage -> do
140 top <- expr topDirectory
141 pkgDb <- expr $ packageDbPath stage
142 notStage0 ? arg ("--ghc-pkg-option=--global-package-db=" ++ top -/- pkgDb)
143 _ -> return [] -- no arguments
144
145
146 -- Expression 'with Alex' appends "--with-alex=/path/to/alex" and needs Alex.
147 with :: Builder -> Args
148 with b = do
149 path <- getBuilderPath b
150 if (null path) then mempty else do
151 top <- expr topDirectory
152 expr $ needBuilder b
153 arg $ withBuilderKey b ++ unifyPath (top </> path)
154
155 withStaged :: (Stage -> Builder) -> Args
156 withStaged sb = with . sb =<< getStage
157
158 stagedBuilderPath :: (Stage -> Builder) -> Args
159 stagedBuilderPath sb = builderPath . sb =<< getStage
160 where builderPath :: Builder -> Args
161 builderPath b = do
162 path <- getBuilderPath b
163 if (null path) then mempty else do
164 top <- expr topDirectory
165 expr $ needBuilder b
166 arg $ unifyPath (top </> path)