Build and copy libffi shared libraries correctly and enable dynamically linking ghc.
[ghc.git] / hadrian / src / Settings / Builders / Ghc.hs
1 module Settings.Builders.Ghc (ghcBuilderArgs, haddockGhcArgs) where
2
3 import Hadrian.Haskell.Cabal
4 import Hadrian.Haskell.Cabal.Type
5
6 import Flavour
7 import Packages
8 import Settings.Builders.Common
9 import Settings.Warnings
10 import qualified Context as Context
11 import Rules.Libffi (libffiName)
12
13 ghcBuilderArgs :: Args
14 ghcBuilderArgs = mconcat [compileAndLinkHs, compileC, findHsDependencies]
15
16 compileAndLinkHs :: Args
17 compileAndLinkHs = (builder (Ghc CompileHs) ||^ builder (Ghc LinkHs)) ? do
18 mconcat [ arg "-Wall"
19 , commonGhcArgs
20 , splitObjects <$> flavour ? arg "-split-objs"
21 , ghcLinkArgs
22 , defaultGhcWarningsArgs
23 , builder (Ghc CompileHs) ? arg "-c"
24 , getInputs
25 , arg "-o", arg =<< getOutput ]
26
27 compileC :: Args
28 compileC = builder (Ghc CompileCWithGhc) ? do
29 way <- getWay
30 let ccArgs = [ getContextData ccOpts
31 , getStagedSettingList ConfCcArgs
32 , cIncludeArgs
33 , Dynamic `wayUnit` way ? pure [ "-fPIC", "-DDYNAMIC" ] ]
34 mconcat [ arg "-Wall"
35 , ghcLinkArgs
36 , commonGhcArgs
37 , mconcat (map (map ("-optc" ++) <$>) ccArgs)
38 , defaultGhcWarningsArgs
39 , arg "-c"
40 , getInputs
41 , arg "-o"
42 , arg =<< getOutput ]
43
44 ghcLinkArgs :: Args
45 ghcLinkArgs = builder (Ghc LinkHs) ? do
46 pkg <- getPackage
47 libs <- getContextData extraLibs
48 libDirs <- getContextData extraLibDirs
49 fmwks <- getContextData frameworks
50 darwin <- expr osxHost
51 way <- getWay
52
53 -- Relative path from the output (rpath $ORIGIN).
54 originPath <- dropFileName <$> getOutput
55 context <- getContext
56 libPath' <- expr (libPath context)
57 distDir <- expr Context.distDir
58
59 useSystemFfi <- expr (flag UseSystemFfi)
60 buildPath <- getBuildPath
61 libffiName' <- libffiName
62
63 let
64 dynamic = Dynamic `wayUnit` way
65 distPath = libPath' -/- distDir
66 originToLibsDir = makeRelativeNoSysLink originPath distPath
67 rpath | darwin = "@loader_path" -/- originToLibsDir
68 | otherwise = "$ORIGIN" -/- originToLibsDir
69
70 -- TODO: an alternative would be to generalize by linking with extra
71 -- bundled libraries, but currently the rts is the only use case. It is
72 -- a special case when `useSystemFfi == True`: the ffi library files
73 -- are not actually bundled with the rts. Perhaps ffi should be part of
74 -- rts's extra libraries instead of extra bundled libraries in that
75 -- case. Care should be take as to not break the make build.
76 rtsFfiArg = package rts ? not useSystemFfi ? mconcat
77 [ arg ("-L" ++ buildPath)
78 , arg ("-l" ++ libffiName')
79 ]
80
81 mconcat [ dynamic ? mconcat
82 [ arg "-dynamic"
83 -- TODO what about windows?
84 , isLibrary pkg ? pure [ "-shared", "-dynload", "deploy" ]
85 , notStage0 ?
86 hostSupportsRPaths ? arg ("-optl-Wl,-rpath," ++ rpath)
87 ]
88 , arg "-no-auto-link-packages"
89 , nonHsMainPackage pkg ? arg "-no-hs-main"
90 , not (nonHsMainPackage pkg) ? arg "-rtsopts"
91 , pure [ "-l" ++ lib | lib <- libs ]
92 , pure [ "-L" ++ libDir | libDir <- libDirs ]
93 , rtsFfiArg
94 , darwin ? pure (concat [ ["-framework", fmwk] | fmwk <- fmwks ])
95 ]
96
97 findHsDependencies :: Args
98 findHsDependencies = builder (Ghc FindHsDependencies) ? do
99 ways <- getLibraryWays
100 mconcat [ arg "-M"
101 , commonGhcArgs
102 , arg "-include-pkg-deps"
103 , arg "-dep-makefile", arg =<< getOutput
104 , pure $ concat [ ["-dep-suffix", wayPrefix w] | w <- ways ]
105 , getInputs ]
106
107 haddockGhcArgs :: Args
108 haddockGhcArgs = mconcat [ commonGhcArgs
109 , getContextData hcOpts
110 , ghcWarningsArgs ]
111
112 -- | Common GHC command line arguments used in 'ghcBuilderArgs',
113 -- 'ghcCBuilderArgs', 'ghcMBuilderArgs' and 'haddockGhcArgs'.
114 commonGhcArgs :: Args
115 commonGhcArgs = do
116 way <- getWay
117 path <- getBuildPath
118 ghcVersion <- expr ghcVersionH
119 mconcat [ arg "-hisuf", arg $ hisuf way
120 , arg "-osuf" , arg $ osuf way
121 , arg "-hcsuf", arg $ hcsuf way
122 , wayGhcArgs
123 , packageGhcArgs
124 , includeGhcArgs
125 -- When compiling RTS for Stage1 or Stage2 we do not have it (yet)
126 -- in the package database. We therefore explicity supply the path
127 -- to the @ghc-version@ file, to prevent GHC from trying to open the
128 -- RTS package in the package database and failing.
129 , package rts ? notStage0 ? arg ("-ghcversion-file=" ++ ghcVersion)
130 , map ("-optc" ++) <$> getStagedSettingList ConfCcArgs
131 , map ("-optP" ++) <$> getStagedSettingList ConfCppArgs
132 , map ("-optP" ++) <$> getContextData cppOpts
133 , arg "-outputdir", arg path ]
134
135 -- TODO: Do '-ticky' in all debug ways?
136 wayGhcArgs :: Args
137 wayGhcArgs = do
138 way <- getWay
139 mconcat [ if Dynamic `wayUnit` way
140 then pure ["-fPIC", "-dynamic"]
141 else arg "-static"
142 , (Threaded `wayUnit` way) ? arg "-optc-DTHREADED_RTS"
143 , (Debug `wayUnit` way) ? arg "-optc-DDEBUG"
144 , (Profiling `wayUnit` way) ? arg "-prof"
145 , (Logging `wayUnit` way) ? arg "-eventlog"
146 , (way == debug || way == debugDynamic) ?
147 pure ["-ticky", "-DTICKY_TICKY"] ]
148
149 packageGhcArgs :: Args
150 packageGhcArgs = do
151 package <- getPackage
152 pkgId <- expr $ pkgIdentifier package
153 mconcat [ arg "-hide-all-packages"
154 , arg "-no-user-package-db"
155 , packageDatabaseArgs
156 , libraryPackage ? arg ("-this-unit-id " ++ pkgId)
157 , map ("-package-id " ++) <$> getContextData depIds ]
158
159 includeGhcArgs :: Args
160 includeGhcArgs = do
161 pkg <- getPackage
162 path <- getBuildPath
163 root <- getBuildRoot
164 context <- getContext
165 srcDirs <- getContextData srcDirs
166 autogen <- expr $ autogenPath context
167 let cabalMacros = autogen -/- "cabal_macros.h"
168 expr $ need [cabalMacros]
169 mconcat [ arg "-i"
170 , arg $ "-i" ++ path
171 , arg $ "-i" ++ autogen
172 , pure [ "-i" ++ pkgPath pkg -/- dir | dir <- srcDirs ]
173 , cIncludeArgs
174 , arg $ "-I" ++ root -/- generatedDir
175 , arg $ "-optc-I" ++ root -/- generatedDir
176 , pure ["-optP-include", "-optP" ++ cabalMacros] ]