@@ -117,7 +117,7 @@ import Stack.Types.ConfigureOpts
117117import Stack.Types.Curator ( Curator (.. ) )
118118import Stack.Types.DumpPackage ( DumpPackage (.. ) )
119119import Stack.Types.EnvConfig
120- ( HasEnvConfig (.. ), actualCompilerVersionL
120+ ( EnvConfig ( .. ), HasEnvConfig (.. ), actualCompilerVersionL
121121 , appropriateGhcColorFlag
122122 )
123123import Stack.Types.EnvSettings ( EnvSettings (.. ) )
@@ -362,6 +362,10 @@ singleBuild
362362 installedMap
363363 isFinalBuild
364364 = do
365+ cabalVersion <- view $ envConfigL . to (. compilerPaths. cabalVersion)
366+ -- The old version of Cabal (the library) copy did not allow the components
367+ -- to be copied to be specified.
368+ let isOldCabalCopy = cabalVersion < mkVersion [2 , 0 ]
365369 (allDepsMap, cache) <-
366370 getConfigCache ee task installedMap enableTests enableBenchmarks
367371 let bcoSnapInstallRoot = ee. baseConfigOpts. snapInstallRoot
@@ -371,7 +375,7 @@ singleBuild
371375 Just precompiled -> copyPreCompiled ee task pkgId precompiled
372376 Nothing -> do
373377 curator <- view $ buildConfigL . to (. curator)
374- realConfigAndBuild cache curator allDepsMap
378+ realConfigAndBuild isOldCabalCopy cache curator allDepsMap
375379 case minstalled of
376380 Nothing -> pure ()
377381 Just installed -> do
@@ -395,7 +399,7 @@ singleBuild
395399 enableTests = buildingFinals && any isCTest (taskComponents task)
396400 enableBenchmarks = buildingFinals && any isCBench (taskComponents task)
397401
398- annSuffix executableBuildStatuses =
402+ annSuffix isOldCabalCopy executableBuildStatuses =
399403 if result == " " then " " else " (" <> result <> " )"
400404 where
401405 result = T. intercalate " + " $ concat
@@ -410,18 +414,18 @@ singleBuild
410414 let package = lp. package
411415 hasLibrary = hasBuildableMainLibrary package
412416 hasSubLibraries = not $ null package. subLibraries
413- hasExecutables =
414- not . Set. null $ exesToBuild executableBuildStatuses lp
417+ hasExecutables = not . Set. null $
418+ exesToBuild isOldCabalCopy executableBuildStatuses lp
415419 in (hasLibrary, hasSubLibraries, hasExecutables)
416420 -- This isn't true, but we don't want to have this info for upstream deps.
417421 _ -> (False , False , False )
418422
419- realConfigAndBuild cache mcurator allDepsMap =
423+ realConfigAndBuild isOldCabalCopy cache mcurator allDepsMap =
420424 withSingleContext ac ee task. taskType allDepsMap Nothing $
421425 \ package cabalFP pkgDir cabal0 announce _outputType -> do
422426 let cabal = cabal0 CloseOnException
423427 executableBuildStatuses <- getExecutableBuildStatuses package pkgDir
424- when ( not (cabalIsSatisfied executableBuildStatuses)
428+ when ( not (cabalIsSatisfied isOldCabalCopy executableBuildStatuses)
425429 && taskIsTarget task
426430 ) $
427431 prettyInfoL
@@ -437,7 +441,7 @@ singleBuild
437441 ee. buildOpts
438442 ( announce
439443 ( " configure"
440- <> display (annSuffix executableBuildStatuses)
444+ <> display (annSuffix isOldCabalCopy executableBuildStatuses)
441445 )
442446 )
443447 cabal
@@ -459,7 +463,7 @@ singleBuild
459463 -- https://github.com/commercialhaskell/stack/issues/2787
460464 (True , _) | null ac. downstream -> pure Nothing
461465 (_, True ) | null ac. downstream || installedMapHasThisPkg -> do
462- initialBuildSteps executableBuildStatuses cabal announce
466+ initialBuildSteps isOldCabalCopy executableBuildStatuses cabal announce
463467 pure Nothing
464468 _ -> fulfillCuratorBuildExpectations
465469 pname
@@ -468,25 +472,27 @@ singleBuild
468472 enableBenchmarks
469473 Nothing
470474 (Just <$>
471- realBuild cache package pkgDir cabal0 announce executableBuildStatuses)
475+ realBuild isOldCabalCopy cache package pkgDir cabal0 announce executableBuildStatuses)
472476
473- initialBuildSteps executableBuildStatuses cabal announce = do
477+ initialBuildSteps isOldCabalCopy executableBuildStatuses cabal announce = do
474478 announce
475479 ( " initial-build-steps"
476- <> display (annSuffix executableBuildStatuses)
480+ <> display (annSuffix isOldCabalCopy executableBuildStatuses)
477481 )
478482 cabal KeepTHLoading [" repl" , " stack-initial-build-steps" ]
479483
480484 realBuild ::
481- ConfigCache
485+ Bool
486+ -- ^ Is Cabal copy limited to all libraries and executables?
487+ -> ConfigCache
482488 -> Package
483489 -> Path Abs Dir
484490 -> (KeepOutputOpen -> ExcludeTHLoading -> [String ] -> RIO env () )
485491 -> (Utf8Builder -> RIO env () )
486492 -- ^ A plain 'announce' function
487493 -> Map Text ExecutableBuildStatus
488494 -> RIO env Installed
489- realBuild cache package pkgDir cabal0 announce executableBuildStatuses = do
495+ realBuild isOldCabalCopy cache package pkgDir cabal0 announce executableBuildStatuses = do
490496 let cabal = cabal0 CloseOnException
491497 wc <- view $ actualCompilerVersionL . whichCompilerL
492498
@@ -542,7 +548,7 @@ singleBuild
542548 actualCompiler <- view actualCompilerVersionL
543549 () <- announce
544550 ( " build"
545- <> display (annSuffix executableBuildStatuses)
551+ <> display (annSuffix isOldCabalCopy executableBuildStatuses)
546552 <> " with "
547553 <> display actualCompiler
548554 )
@@ -551,16 +557,20 @@ singleBuild
551557 let stripTHLoading
552558 | config. hideTHLoading = ExcludeTHLoading
553559 | otherwise = KeepTHLoading
554- cabal stripTHLoading ((" build" : ) $ (++ extraOpts) $
555- case (task. taskType, task. allInOne, isFinalBuild) of
556- (_, True , True ) -> throwM AllInOneBuildBug
557- (TTLocalMutable lp, False , False ) ->
558- primaryComponentOptions executableBuildStatuses lp
559- (TTLocalMutable lp, False , True ) -> finalComponentOptions lp
560- (TTLocalMutable lp, True , False ) ->
561- primaryComponentOptions executableBuildStatuses lp
562- ++ finalComponentOptions lp
563- (TTRemotePackage {}, _, _) -> [] )
560+ (buildOpts, copyOpts) <-
561+ case (task. taskType, task. allInOne, isFinalBuild) of
562+ (_, True , True ) -> throwM AllInOneBuildBug
563+ (TTLocalMutable lp, False , False ) ->
564+ let componentOpts =
565+ primaryComponentOptions isOldCabalCopy executableBuildStatuses lp
566+ in pure (componentOpts, componentOpts)
567+ (TTLocalMutable lp, False , True ) -> pure (finalComponentOptions lp, [] )
568+ (TTLocalMutable lp, True , False ) ->
569+ let componentOpts =
570+ primaryComponentOptions isOldCabalCopy executableBuildStatuses lp
571+ in pure (componentOpts <> finalComponentOptions lp, componentOpts)
572+ (TTRemotePackage {}, _, _) -> pure ([] , [] )
573+ cabal stripTHLoading (" build" : buildOpts <> extraOpts)
564574 `catch` \ ex -> case ex of
565575 CabalExitedUnsuccessfully {} ->
566576 postBuildCheck False >> prettyThrowM ex
@@ -613,7 +623,8 @@ singleBuild
613623 && (hasLibrary || hasSubLibraries || hasExecutables)
614624 when shouldCopy $ withMVar ee. installLock $ \ () -> do
615625 announce " copy/register"
616- eres <- try $ cabal KeepTHLoading [" copy" ]
626+ let copyArgs = " copy" : if isOldCabalCopy then [] else copyOpts
627+ eres <- try $ cabal KeepTHLoading copyArgs
617628 case eres of
618629 Left err@ CabalExitedUnsuccessfully {} ->
619630 throwM $ CabalCopyFailed
@@ -1249,10 +1260,12 @@ extraBuildOptions wc bopts = do
12491260
12501261-- Library, sub-library, foreign library and executable build components.
12511262primaryComponentOptions ::
1252- Map Text ExecutableBuildStatus
1263+ Bool
1264+ -- ^ Is Cabal copy limited to all libraries and executables?
1265+ -> Map Text ExecutableBuildStatus
12531266 -> LocalPackage
12541267 -> [String ]
1255- primaryComponentOptions executableBuildStatuses lp =
1268+ primaryComponentOptions isOldCabalCopy executableBuildStatuses lp =
12561269 -- TODO: get this information from target parsing instead, which will allow
12571270 -- users to turn off library building if desired
12581271 ( if hasBuildableMainLibrary package
@@ -1268,7 +1281,7 @@ primaryComponentOptions executableBuildStatuses lp =
12681281 (getBuildableListText package. subLibraries)
12691282 ++ map
12701283 (T. unpack . T. append " exe:" )
1271- (Set. toList $ exesToBuild executableBuildStatuses lp)
1284+ (Set. toList $ exesToBuild isOldCabalCopy executableBuildStatuses lp)
12721285 where
12731286 package = lp. package
12741287
@@ -1284,15 +1297,29 @@ primaryComponentOptions executableBuildStatuses lp =
12841297-- behavior below that we build all executables once (modulo success), and
12851298-- thereafter pay attention to user-wanted components.
12861299--
1287- exesToBuild :: Map Text ExecutableBuildStatus -> LocalPackage -> Set Text
1288- exesToBuild executableBuildStatuses lp =
1289- if cabalIsSatisfied executableBuildStatuses && lp. wanted
1300+ -- * The Cabal bug was fixed, in that the copy command of later Cabal versions
1301+ -- allowed components to be specified. Consequently, Cabal may be satisified,
1302+ -- even if all of a package's executables have not yet been built.
1303+ exesToBuild ::
1304+ Bool
1305+ -- ^ Is Cabal copy limited to all libraries and executables?
1306+ -> Map Text ExecutableBuildStatus
1307+ -> LocalPackage
1308+ -> Set Text
1309+ exesToBuild isOldCabalCopy executableBuildStatuses lp =
1310+ if cabalIsSatisfied isOldCabalCopy executableBuildStatuses && lp. wanted
12901311 then exeComponents lp. components
12911312 else buildableExes lp. package
12921313
1293- -- | Do the current executables satisfy Cabal's bugged out requirements?
1294- cabalIsSatisfied :: Map k ExecutableBuildStatus -> Bool
1295- cabalIsSatisfied = all (== ExecutableBuilt ) . Map. elems
1314+ -- | Do the current executables satisfy Cabal's requirements?
1315+ cabalIsSatisfied ::
1316+ Bool
1317+ -- ^ Is Cabal copy limited to all libraries and executables?
1318+ -> Map k ExecutableBuildStatus
1319+ -> Bool
1320+ cabalIsSatisfied False _ = True
1321+ cabalIsSatisfied True executableBuildStatuses =
1322+ all (== ExecutableBuilt ) $ Map. elems executableBuildStatuses
12961323
12971324-- Test-suite and benchmark build components.
12981325finalComponentOptions :: LocalPackage -> [String ]
0 commit comments