66
77module Distribution.Simple.GHC.Build.ExtraSources where
88
9- import Control.Monad
9+ import Control.Monad ( forM , when )
1010import Data.Foldable
1111import Distribution.Simple.Flag
1212import qualified Distribution.Simple.GHC.Internal as Internal
@@ -16,6 +16,7 @@ import Distribution.Utils.NubList
1616
1717import Distribution.Types.BuildInfo
1818import Distribution.Types.Component
19+ import Distribution.Types.ParStrat
1920import Distribution.Types.TargetInfo
2021
2122import Distribution.Simple.Build.Inputs
@@ -32,7 +33,8 @@ import Distribution.Verbosity (Verbosity)
3233-- | An action that builds all the extra build sources of a component, i.e. C,
3334-- C++, Js, Asm, C-- sources.
3435buildAllExtraSources
35- :: Maybe (SymbolicPath Pkg File )
36+ :: Flag ParStrat
37+ -> Maybe (SymbolicPath Pkg File )
3638 -- ^ An optional non-Haskell Main file
3739 -> ConfiguredProgram
3840 -- ^ The GHC configured program
@@ -58,7 +60,8 @@ buildCSources
5860 , buildJsSources
5961 , buildAsmSources
6062 , buildCmmSources
61- :: Maybe (SymbolicPath Pkg File )
63+ :: Flag ParStrat
64+ -> Maybe (SymbolicPath Pkg File )
6265 -- ^ An optional non-Haskell Main file
6366 -> ConfiguredProgram
6467 -- ^ The GHC configured program
@@ -70,7 +73,7 @@ buildCSources
7073 -- ^ The context and component being built in it.
7174 -> IO (NubListR (SymbolicPath Pkg File ))
7275 -- ^ Returns the list of extra sources that were built
73- buildCSources mbMainFile =
76+ buildCSources parStrat mbMainFile =
7477 buildExtraSources
7578 " C Sources"
7679 Internal. componentCcGhcOptions
@@ -83,7 +86,8 @@ buildCSources mbMainFile =
8386 cFiles ++ [main]
8487 _otherwise -> cFiles
8588 )
86- buildCxxSources mbMainFile =
89+ parStrat
90+ buildCxxSources parStrat mbMainFile =
8791 buildExtraSources
8892 " C++ Sources"
8993 Internal. componentCxxGhcOptions
@@ -96,7 +100,8 @@ buildCxxSources mbMainFile =
96100 cxxFiles ++ [main]
97101 _otherwise -> cxxFiles
98102 )
99- buildJsSources _mbMainFile ghcProg buildTargetDir neededWays = do
103+ parStrat
104+ buildJsSources parStrat _mbMainFile ghcProg buildTargetDir neededWays = do
100105 Platform hostArch _ <- hostPlatform <$> localBuildInfo
101106 let hasJsSupport = hostArch == JavaScript
102107 buildExtraSources
@@ -111,19 +116,22 @@ buildJsSources _mbMainFile ghcProg buildTargetDir neededWays = do
111116 jsSources (componentBuildInfo c)
112117 else mempty
113118 )
119+ parStrat
114120 ghcProg
115121 buildTargetDir
116122 neededWays
117- buildAsmSources _mbMainFile =
123+ buildAsmSources parStrat _mbMainFile =
118124 buildExtraSources
119125 " Assembler Sources"
120126 Internal. componentAsmGhcOptions
121127 (asmSources . componentBuildInfo)
122- buildCmmSources _mbMainFile =
128+ parStrat
129+ buildCmmSources parStrat _mbMainFile =
123130 buildExtraSources
124131 " C-- Sources"
125132 Internal. componentCmmGhcOptions
126133 (cmmSources . componentBuildInfo)
134+ parStrat
127135
128136-- | Create 'PreBuildComponentRules' for a given type of extra build sources
129137-- which are compiled via a GHC invocation with the given options. Used to
@@ -136,7 +144,6 @@ buildExtraSources
136144 -> BuildInfo
137145 -> ComponentLocalBuildInfo
138146 -> SymbolicPath Pkg (Dir Artifacts )
139- -> SymbolicPath Pkg File
140147 -> GhcOptions
141148 )
142149 -- ^ Function to determine the @'GhcOptions'@ for the
@@ -149,6 +156,7 @@ buildExtraSources
149156 -- @'Executable'@ components might additionally add the
150157 -- program entry point (@main-is@ file) to the extra sources,
151158 -- if it should be compiled as the rest of them.
159+ -> Flag ParStrat
152160 -> ConfiguredProgram
153161 -- ^ The GHC configured program
154162 -> SymbolicPath Pkg (Dir Artifacts )
@@ -163,6 +171,7 @@ buildExtraSources
163171 description
164172 componentSourceGhcOptions
165173 viewSources
174+ parStrat
166175 ghcProg
167176 buildTargetDir
168177 (neededLibWays, neededFLibWay, neededExeWay) =
@@ -189,84 +198,82 @@ buildExtraSources
189198 platform
190199 mbWorkDir
191200
192- buildAction :: SymbolicPath Pkg File -> IO ()
193- buildAction sourceFile = do
201+ buildAction :: [ SymbolicPath Pkg File ] -> IO ()
202+ buildAction sourceFiles = do
194203 let baseSrcOpts =
195204 componentSourceGhcOptions
196205 verbosity
197206 lbi
198207 bi
199208 clbi
200209 buildTargetDir
201- sourceFile
202210 vanillaSrcOpts =
203- -- -fPIC is used in case you are using the repl
204- -- of a dynamically linked GHC
205- baseSrcOpts{ghcOptFPic = toFlag True }
211+ baseSrcOpts
212+ { ghcOptFPic = toFlag True
213+ , -- -fPIC is always used in case you are using the repl of a
214+ -- dynamically linked GHC
215+ ghcOptNumJobs = parStrat
216+ }
206217 profSrcOpts =
207218 vanillaSrcOpts
208- `mappend` mempty
209- { ghcOptProfilingMode = toFlag True
210- }
219+ { ghcOptProfilingMode = toFlag True
220+ , ghcOptObjSuffix = toFlag " p_o "
221+ }
211222 sharedSrcOpts =
212223 vanillaSrcOpts
213- `mappend` mempty
214- { ghcOptFPic = toFlag True
215- , ghcOptDynLinkMode = toFlag GhcDynamicOnly
216- }
224+ { ghcOptDynLinkMode = toFlag GhcDynamicOnly
225+ , ghcOptObjSuffix = toFlag " dyn_o"
226+ }
217227 profSharedSrcOpts =
218228 vanillaSrcOpts
219- `mappend` mempty
220- { ghcOptProfilingMode = toFlag True
221- , ghcOptFPic = toFlag True
222- , ghcOptDynLinkMode = toFlag GhcDynamicOnly
223- }
229+ { ghcOptProfilingMode = toFlag True
230+ , ghcOptDynLinkMode = toFlag GhcDynamicOnly
231+ , ghcOptObjSuffix = toFlag " p_dyn_o"
232+ }
224233 -- TODO: Placing all Haskell, C, & C++ objects in a single directory
225234 -- Has the potential for file collisions. In general we would
226235 -- consider this a user error. However, we should strive to
227236 -- add a warning if this occurs.
228237 odir = fromFlag (ghcOptObjDir vanillaSrcOpts)
229238
230- compileIfNeeded :: GhcOptions -> IO ()
231- compileIfNeeded opts = do
232- needsRecomp <- checkNeedsRecompilation mbWorkDir sourceFile opts
233- when needsRecomp $ runGhcProg opts
234-
235239 createDirectoryIfMissingVerbose verbosity True (i odir)
236- case targetComponent targetInfo of
237- -- For libraries, we compile extra objects in the four ways: vanilla, shared, profiled and profiled shared.
238- -- We suffix shared objects with `.dyn_o`, profiled ones with `.p_o` and profiled shared ones with `.p_dyn_o`.
239- CLib _lib
240- -- Unless for repl, in which case we only need the vanilla way
241- | BuildRepl _ <- buildingWhat ->
242- compileIfNeeded vanillaSrcOpts
243- | otherwise ->
244- do
245- forM_ (neededLibWays isIndef) $ \ case
246- StaticWay -> compileIfNeeded vanillaSrcOpts
247- DynWay -> compileIfNeeded sharedSrcOpts{ghcOptObjSuffix = toFlag " dyn_o" }
248- ProfWay -> compileIfNeeded profSrcOpts{ghcOptObjSuffix = toFlag " p_o" }
249- ProfDynWay -> compileIfNeeded profSharedSrcOpts{ghcOptObjSuffix = toFlag " p_dyn_o" }
250- CFLib flib ->
251- case neededFLibWay (withDynFLib flib) of
252- StaticWay -> compileIfNeeded vanillaSrcOpts
253- DynWay -> compileIfNeeded sharedSrcOpts
254- ProfWay -> compileIfNeeded profSrcOpts
255- ProfDynWay -> compileIfNeeded profSharedSrcOpts
256- -- For the remaining component types (Exec, Test, Bench), we also
257- -- determine with which options to build the objects (vanilla vs shared vs
258- -- profiled), but predicate is the same for the three kinds.
259- _exeLike ->
260- case neededExeWay of
261- StaticWay -> compileIfNeeded vanillaSrcOpts
262- DynWay -> compileIfNeeded sharedSrcOpts
263- ProfWay -> compileIfNeeded profSrcOpts
264- ProfDynWay -> compileIfNeeded profSharedSrcOpts
240+ let optsForWay = \ case
241+ StaticWay -> vanillaSrcOpts
242+ DynWay -> sharedSrcOpts
243+ ProfWay -> profSrcOpts
244+ ProfDynWay -> profSharedSrcOpts
245+ -- we don't tell GHC to suffix the filenames of objects produced from
246+ -- extra-sources for executables or foreign libraries
247+ let stripObjectSuffix opts =
248+ opts{ghcOptObjSuffix = ghcOptObjSuffix baseSrcOpts}
265249
250+ let optsForNeededWays =
251+ case targetComponent targetInfo of
252+ -- For libraries (foreign or not), we compile extra objects in the four ways: vanilla, shared,
253+ -- profiled and profiled shared. We suffix shared objects with `.dyn_o`, profiled ones with `.p_o`
254+ -- and profiled shared ones with `.p_dyn_o`.
255+ CLib _lib
256+ -- Unless for repl, in which case we only need the vanilla way
257+ | BuildRepl _ <- buildingWhat ->
258+ [vanillaSrcOpts]
259+ | otherwise ->
260+ optsForWay <$> neededLibWays isIndef
261+ CFLib flib ->
262+ [stripObjectSuffix (optsForWay (neededFLibWay (withDynFLib flib)))]
263+ -- For the remaining component types (Exec, Test, Bench) we
264+ -- only need to build them with one set of options.
265+ _exeLike ->
266+ [stripObjectSuffix (optsForWay neededExeWay)]
267+ forM_ optsForNeededWays $ \ opts -> do
268+ files <- fmap concat $ forM sourceFiles $ \ sourceFile -> do
269+ needsRecomp <- checkNeedsRecompilation mbWorkDir sourceFile opts
270+ return [sourceFile | needsRecomp]
271+ when (not (null files)) $
272+ runGhcProg opts{ghcOptInputFiles = toNubListR files}
266273 -- build any sources
267274 if (null sources || componentIsIndefinite clbi)
268275 then return mempty
269276 else do
270277 info verbosity (" Building " ++ description ++ " ..." )
271- traverse_ buildAction sources
278+ buildAction sources
272279 return (toNubListR sources)
0 commit comments