diff --git a/Cabal-syntax/src/Distribution/PackageDescription/FieldGrammar.hs b/Cabal-syntax/src/Distribution/PackageDescription/FieldGrammar.hs index db6b7f7607b..4d9ada935af 100644 --- a/Cabal-syntax/src/Distribution/PackageDescription/FieldGrammar.hs +++ b/Cabal-syntax/src/Distribution/PackageDescription/FieldGrammar.hs @@ -673,6 +673,7 @@ buildInfoFieldGrammar = <*> optionsFieldGrammar <*> profOptionsFieldGrammar <*> sharedOptionsFieldGrammar + <*> profSharedOptionsFieldGrammar <*> pure mempty -- static-options ??? <*> prefixedFields "x-" L.customFieldsBI <*> monoidalFieldAla "build-depends" formatDependencyList L.targetBuildDepends @@ -738,6 +739,19 @@ sharedOptionsFieldGrammar = extract :: CompilerFlavor -> ALens' BuildInfo [String] extract flavor = L.sharedOptions . lookupLens flavor +profSharedOptionsFieldGrammar + :: (FieldGrammar c g, Applicative (g BuildInfo), c (List NoCommaFSep Token' String)) + => g BuildInfo (PerCompilerFlavor [String]) +profSharedOptionsFieldGrammar = + PerCompilerFlavor + <$> monoidalFieldAla "ghc-prof-shared-options" (alaList' NoCommaFSep Token') (extract GHC) + ^^^ availableSince CabalSpecV3_14 [] + <*> monoidalFieldAla "ghcjs-prof-shared-options" (alaList' NoCommaFSep Token') (extract GHCJS) + ^^^ availableSince CabalSpecV3_14 [] + where + extract :: CompilerFlavor -> ALens' BuildInfo [String] + extract flavor = L.profSharedOptions . lookupLens flavor + lookupLens :: (Functor f, Monoid v) => CompilerFlavor -> LensLike' f (PerCompilerFlavor v) v lookupLens k f p@(PerCompilerFlavor ghc ghcjs) | k == GHC = (\n -> PerCompilerFlavor n ghcjs) <$> f ghc diff --git a/Cabal-syntax/src/Distribution/Types/BuildInfo.hs b/Cabal-syntax/src/Distribution/Types/BuildInfo.hs index da1f8aea88f..680b9bf49db 100644 --- a/Cabal-syntax/src/Distribution/Types/BuildInfo.hs +++ b/Cabal-syntax/src/Distribution/Types/BuildInfo.hs @@ -12,6 +12,7 @@ module Distribution.Types.BuildInfo , hcOptions , hcProfOptions , hcSharedOptions + , hcProfSharedOptions , hcStaticOptions ) where @@ -133,6 +134,7 @@ data BuildInfo = BuildInfo , options :: PerCompilerFlavor [String] , profOptions :: PerCompilerFlavor [String] , sharedOptions :: PerCompilerFlavor [String] + , profSharedOptions :: PerCompilerFlavor [String] , staticOptions :: PerCompilerFlavor [String] , customFieldsBI :: [(String, String)] -- ^ Custom fields starting @@ -193,6 +195,7 @@ instance Monoid BuildInfo where , options = mempty , profOptions = mempty , sharedOptions = mempty + , profSharedOptions = mempty , staticOptions = mempty , customFieldsBI = [] , targetBuildDepends = [] @@ -245,6 +248,7 @@ instance Semigroup BuildInfo where , options = combine options , profOptions = combine profOptions , sharedOptions = combine sharedOptions + , profSharedOptions = combine profSharedOptions , staticOptions = combine staticOptions , customFieldsBI = combine customFieldsBI , targetBuildDepends = combineNub targetBuildDepends @@ -295,6 +299,9 @@ hcProfOptions = lookupHcOptions profOptions hcSharedOptions :: CompilerFlavor -> BuildInfo -> [String] hcSharedOptions = lookupHcOptions sharedOptions +hcProfSharedOptions :: CompilerFlavor -> BuildInfo -> [String] +hcProfSharedOptions = lookupHcOptions profSharedOptions + hcStaticOptions :: CompilerFlavor -> BuildInfo -> [String] hcStaticOptions = lookupHcOptions staticOptions diff --git a/Cabal-syntax/src/Distribution/Types/BuildInfo/Lens.hs b/Cabal-syntax/src/Distribution/Types/BuildInfo/Lens.hs index 19453a671b9..ac99f3c65a5 100644 --- a/Cabal-syntax/src/Distribution/Types/BuildInfo/Lens.hs +++ b/Cabal-syntax/src/Distribution/Types/BuildInfo/Lens.hs @@ -195,6 +195,10 @@ class HasBuildInfo a where sharedOptions = buildInfo . sharedOptions {-# INLINE sharedOptions #-} + profSharedOptions :: Lens' a (PerCompilerFlavor [String]) + profSharedOptions = buildInfo . profSharedOptions + {-# INLINE profSharedOptions #-} + staticOptions :: Lens' a (PerCompilerFlavor [String]) staticOptions = buildInfo . staticOptions {-# INLINE staticOptions #-} @@ -341,6 +345,9 @@ instance HasBuildInfo BuildInfo where sharedOptions f s = fmap (\x -> s{T.sharedOptions = x}) (f (T.sharedOptions s)) {-# INLINE sharedOptions #-} + profSharedOptions f s = fmap (\x -> s{T.profSharedOptions = x}) (f (T.profSharedOptions s)) + {-# INLINE profSharedOptions #-} + staticOptions f s = fmap (\x -> s{T.staticOptions = x}) (f (T.staticOptions s)) {-# INLINE staticOptions #-} diff --git a/Cabal-tests/tests/ParserTests/regressions/Octree-0.5.expr b/Cabal-tests/tests/ParserTests/regressions/Octree-0.5.expr index 3d03421210b..b3494104aed 100644 --- a/Cabal-tests/tests/ParserTests/regressions/Octree-0.5.expr +++ b/Cabal-tests/tests/ParserTests/regressions/Octree-0.5.expr @@ -132,6 +132,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -238,6 +240,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -339,6 +343,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/anynone.expr b/Cabal-tests/tests/ParserTests/regressions/anynone.expr index 3191425d609..8c9c8879ab4 100644 --- a/Cabal-tests/tests/ParserTests/regressions/anynone.expr +++ b/Cabal-tests/tests/ParserTests/regressions/anynone.expr @@ -95,6 +95,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/big-version.expr b/Cabal-tests/tests/ParserTests/regressions/big-version.expr index e677de20626..d4ef82adf52 100644 --- a/Cabal-tests/tests/ParserTests/regressions/big-version.expr +++ b/Cabal-tests/tests/ParserTests/regressions/big-version.expr @@ -96,6 +96,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/common-conditional.expr b/Cabal-tests/tests/ParserTests/regressions/common-conditional.expr index f6ffe291e59..9cacba2b770 100644 --- a/Cabal-tests/tests/ParserTests/regressions/common-conditional.expr +++ b/Cabal-tests/tests/ParserTests/regressions/common-conditional.expr @@ -112,6 +112,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -187,6 +189,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -278,6 +282,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -356,6 +362,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -432,6 +440,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -501,6 +511,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -593,6 +605,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -670,6 +684,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/common.expr b/Cabal-tests/tests/ParserTests/regressions/common.expr index e0eb4a1dde7..25abadef9e7 100644 --- a/Cabal-tests/tests/ParserTests/regressions/common.expr +++ b/Cabal-tests/tests/ParserTests/regressions/common.expr @@ -110,6 +110,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -186,6 +188,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/common2.expr b/Cabal-tests/tests/ParserTests/regressions/common2.expr index b3cb004eecb..cd501d11cf2 100644 --- a/Cabal-tests/tests/ParserTests/regressions/common2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/common2.expr @@ -106,6 +106,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -205,6 +207,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -285,6 +289,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -386,6 +392,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -462,6 +470,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -562,6 +572,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -639,6 +651,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -716,6 +730,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/common3.expr b/Cabal-tests/tests/ParserTests/regressions/common3.expr index 21b200baa7b..fc1fc155c09 100644 --- a/Cabal-tests/tests/ParserTests/regressions/common3.expr +++ b/Cabal-tests/tests/ParserTests/regressions/common3.expr @@ -110,6 +110,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -186,6 +188,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/elif.expr b/Cabal-tests/tests/ParserTests/regressions/elif.expr index 1315d689467..f17c1e17b88 100644 --- a/Cabal-tests/tests/ParserTests/regressions/elif.expr +++ b/Cabal-tests/tests/ParserTests/regressions/elif.expr @@ -105,6 +105,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -172,6 +174,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/elif2.expr b/Cabal-tests/tests/ParserTests/regressions/elif2.expr index 61f2177cbaa..ec01a92a79d 100644 --- a/Cabal-tests/tests/ParserTests/regressions/elif2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/elif2.expr @@ -105,6 +105,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -172,6 +174,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -245,6 +249,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -312,6 +318,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -385,6 +393,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/encoding-0.8.expr b/Cabal-tests/tests/ParserTests/regressions/encoding-0.8.expr index e1b125e7a32..0d248029a31 100644 --- a/Cabal-tests/tests/ParserTests/regressions/encoding-0.8.expr +++ b/Cabal-tests/tests/ParserTests/regressions/encoding-0.8.expr @@ -114,6 +114,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/generics-sop.expr b/Cabal-tests/tests/ParserTests/regressions/generics-sop.expr index 9084371a614..25786cdfad5 100644 --- a/Cabal-tests/tests/ParserTests/regressions/generics-sop.expr +++ b/Cabal-tests/tests/ParserTests/regressions/generics-sop.expr @@ -242,6 +242,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -373,6 +375,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -457,6 +461,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -561,6 +567,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -631,6 +639,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -702,6 +712,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [ @@ -798,6 +810,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/hasktorch.expr b/Cabal-tests/tests/ParserTests/regressions/hasktorch.expr index 346af927d1b..c68fac467e1 100644 --- a/Cabal-tests/tests/ParserTests/regressions/hasktorch.expr +++ b/Cabal-tests/tests/ParserTests/regressions/hasktorch.expr @@ -322,6 +322,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -642,6 +644,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -884,6 +888,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -1084,6 +1090,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -1438,6 +1446,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -2740,6 +2750,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -2829,6 +2841,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -5072,6 +5086,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -6424,6 +6440,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -6514,6 +6532,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -8182,6 +8202,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -8670,6 +8692,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -9433,6 +9457,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -9554,6 +9580,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -9659,6 +9687,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -9764,6 +9794,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -9858,6 +9890,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -9978,6 +10012,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/hidden-main-lib.expr b/Cabal-tests/tests/ParserTests/regressions/hidden-main-lib.expr index fba99528b53..b51b4adacb2 100644 --- a/Cabal-tests/tests/ParserTests/regressions/hidden-main-lib.expr +++ b/Cabal-tests/tests/ParserTests/regressions/hidden-main-lib.expr @@ -97,6 +97,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/indentation.expr b/Cabal-tests/tests/ParserTests/regressions/indentation.expr index e5b106dc5cd..c97630ddb00 100644 --- a/Cabal-tests/tests/ParserTests/regressions/indentation.expr +++ b/Cabal-tests/tests/ParserTests/regressions/indentation.expr @@ -106,6 +106,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/indentation2.expr b/Cabal-tests/tests/ParserTests/regressions/indentation2.expr index 46f24105f0f..605cba525d1 100644 --- a/Cabal-tests/tests/ParserTests/regressions/indentation2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/indentation2.expr @@ -99,6 +99,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/indentation3.expr b/Cabal-tests/tests/ParserTests/regressions/indentation3.expr index 0191d063f6e..55d0533c3fe 100644 --- a/Cabal-tests/tests/ParserTests/regressions/indentation3.expr +++ b/Cabal-tests/tests/ParserTests/regressions/indentation3.expr @@ -101,6 +101,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-5055.expr b/Cabal-tests/tests/ParserTests/regressions/issue-5055.expr index 07c04ec6cb9..3b5092639e4 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-5055.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-5055.expr @@ -100,6 +100,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -183,6 +185,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -267,6 +271,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-5846.expr b/Cabal-tests/tests/ParserTests/regressions/issue-5846.expr index 2ff7de7917e..61a7b7d2ca1 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-5846.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-5846.expr @@ -94,6 +94,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-6083-a.expr b/Cabal-tests/tests/ParserTests/regressions/issue-6083-a.expr index 43c345dd170..c9c57785ac6 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-6083-a.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-6083-a.expr @@ -94,6 +94,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -189,6 +191,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -255,6 +259,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -335,6 +341,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-6083-b.expr b/Cabal-tests/tests/ParserTests/regressions/issue-6083-b.expr index e6606851627..b0ed19062fc 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-6083-b.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-6083-b.expr @@ -94,6 +94,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -189,6 +191,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -255,6 +259,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -345,6 +351,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-6083-c.expr b/Cabal-tests/tests/ParserTests/regressions/issue-6083-c.expr index 7435b0d59b4..c901eebc8ce 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-6083-c.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-6083-c.expr @@ -94,6 +94,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -189,6 +191,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-6083-pkg-pkg.expr b/Cabal-tests/tests/ParserTests/regressions/issue-6083-pkg-pkg.expr index a221632efa4..62ed5fd2fb9 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-6083-pkg-pkg.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-6083-pkg-pkg.expr @@ -94,6 +94,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/issue-774.expr b/Cabal-tests/tests/ParserTests/regressions/issue-774.expr index e1ffb85dceb..2f58de4eb00 100644 --- a/Cabal-tests/tests/ParserTests/regressions/issue-774.expr +++ b/Cabal-tests/tests/ParserTests/regressions/issue-774.expr @@ -108,6 +108,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/jaeger-flamegraph.expr b/Cabal-tests/tests/ParserTests/regressions/jaeger-flamegraph.expr index c9e675ceb76..9994c9b72c1 100644 --- a/Cabal-tests/tests/ParserTests/regressions/jaeger-flamegraph.expr +++ b/Cabal-tests/tests/ParserTests/regressions/jaeger-flamegraph.expr @@ -139,6 +139,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -238,6 +240,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -403,6 +407,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/leading-comma-2.expr b/Cabal-tests/tests/ParserTests/regressions/leading-comma-2.expr index 0bb5556b2f4..99f7cddf881 100644 --- a/Cabal-tests/tests/ParserTests/regressions/leading-comma-2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/leading-comma-2.expr @@ -104,6 +104,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/leading-comma.expr b/Cabal-tests/tests/ParserTests/regressions/leading-comma.expr index b1ba1b282f4..441fe75261d 100644 --- a/Cabal-tests/tests/ParserTests/regressions/leading-comma.expr +++ b/Cabal-tests/tests/ParserTests/regressions/leading-comma.expr @@ -97,6 +97,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/libpq1.expr b/Cabal-tests/tests/ParserTests/regressions/libpq1.expr index 8906a91f63b..2e0bc309f9f 100644 --- a/Cabal-tests/tests/ParserTests/regressions/libpq1.expr +++ b/Cabal-tests/tests/ParserTests/regressions/libpq1.expr @@ -190,6 +190,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -289,6 +291,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -373,6 +377,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -464,6 +470,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -529,6 +537,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -596,6 +606,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -661,6 +673,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -728,6 +742,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/libpq2.expr b/Cabal-tests/tests/ParserTests/regressions/libpq2.expr index 3c26ece45ad..b74143af0b9 100644 --- a/Cabal-tests/tests/ParserTests/regressions/libpq2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/libpq2.expr @@ -195,6 +195,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -294,6 +296,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -378,6 +382,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -466,6 +472,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -531,6 +539,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -598,6 +608,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -663,6 +675,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -730,6 +744,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/mixin-1.expr b/Cabal-tests/tests/ParserTests/regressions/mixin-1.expr index de8a15f04c0..77821302ddf 100644 --- a/Cabal-tests/tests/ParserTests/regressions/mixin-1.expr +++ b/Cabal-tests/tests/ParserTests/regressions/mixin-1.expr @@ -98,6 +98,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/mixin-2.expr b/Cabal-tests/tests/ParserTests/regressions/mixin-2.expr index 3bf06bc9c3b..d8b58ff5a0b 100644 --- a/Cabal-tests/tests/ParserTests/regressions/mixin-2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/mixin-2.expr @@ -98,6 +98,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/mixin-3.expr b/Cabal-tests/tests/ParserTests/regressions/mixin-3.expr index 0c0fc57a8b8..c0cbfe921ad 100644 --- a/Cabal-tests/tests/ParserTests/regressions/mixin-3.expr +++ b/Cabal-tests/tests/ParserTests/regressions/mixin-3.expr @@ -98,6 +98,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/monad-param.expr b/Cabal-tests/tests/ParserTests/regressions/monad-param.expr index 28d57c1e3b0..e450672e868 100644 --- a/Cabal-tests/tests/ParserTests/regressions/monad-param.expr +++ b/Cabal-tests/tests/ParserTests/regressions/monad-param.expr @@ -120,6 +120,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/multiple-libs-2.expr b/Cabal-tests/tests/ParserTests/regressions/multiple-libs-2.expr index a8c6b0c0c4a..aa7d6954637 100644 --- a/Cabal-tests/tests/ParserTests/regressions/multiple-libs-2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/multiple-libs-2.expr @@ -97,6 +97,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -175,6 +177,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/noVersion.expr b/Cabal-tests/tests/ParserTests/regressions/noVersion.expr index 8187272c2c0..dfe79d768fb 100644 --- a/Cabal-tests/tests/ParserTests/regressions/noVersion.expr +++ b/Cabal-tests/tests/ParserTests/regressions/noVersion.expr @@ -97,6 +97,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/nothing-unicode.expr b/Cabal-tests/tests/ParserTests/regressions/nothing-unicode.expr index 2f2663733c6..2ed17f6d557 100644 --- a/Cabal-tests/tests/ParserTests/regressions/nothing-unicode.expr +++ b/Cabal-tests/tests/ParserTests/regressions/nothing-unicode.expr @@ -112,6 +112,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -179,6 +181,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/shake.expr b/Cabal-tests/tests/ParserTests/regressions/shake.expr index 8dd849d75bd..4dd37e84de0 100644 --- a/Cabal-tests/tests/ParserTests/regressions/shake.expr +++ b/Cabal-tests/tests/ParserTests/regressions/shake.expr @@ -306,6 +306,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -519,6 +521,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -586,6 +590,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -660,6 +666,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -727,6 +735,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -805,6 +815,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -982,6 +994,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -1206,6 +1220,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -1271,6 +1287,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -1335,6 +1353,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -1406,6 +1426,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -1470,6 +1492,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -1545,6 +1569,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -1764,6 +1790,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -1992,6 +2020,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -2061,6 +2091,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -2130,6 +2162,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -2198,6 +2232,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -2273,6 +2309,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -2341,6 +2379,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -2420,6 +2460,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/spdx-1.expr b/Cabal-tests/tests/ParserTests/regressions/spdx-1.expr index 2ca07bf2322..ddeaf37cbe4 100644 --- a/Cabal-tests/tests/ParserTests/regressions/spdx-1.expr +++ b/Cabal-tests/tests/ParserTests/regressions/spdx-1.expr @@ -95,6 +95,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/spdx-2.expr b/Cabal-tests/tests/ParserTests/regressions/spdx-2.expr index 9c50edd4864..b865b1f31db 100644 --- a/Cabal-tests/tests/ParserTests/regressions/spdx-2.expr +++ b/Cabal-tests/tests/ParserTests/regressions/spdx-2.expr @@ -99,6 +99,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/spdx-3.expr b/Cabal-tests/tests/ParserTests/regressions/spdx-3.expr index 944faa4c0c0..dc8f3f922b9 100644 --- a/Cabal-tests/tests/ParserTests/regressions/spdx-3.expr +++ b/Cabal-tests/tests/ParserTests/regressions/spdx-3.expr @@ -99,6 +99,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/th-lift-instances.expr b/Cabal-tests/tests/ParserTests/regressions/th-lift-instances.expr index 8f2edf09a36..5e781597f30 100644 --- a/Cabal-tests/tests/ParserTests/regressions/th-lift-instances.expr +++ b/Cabal-tests/tests/ParserTests/regressions/th-lift-instances.expr @@ -127,6 +127,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -298,6 +300,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -473,6 +477,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -577,6 +583,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/version-sets.expr b/Cabal-tests/tests/ParserTests/regressions/version-sets.expr index b134e4584ad..3244bc1cc45 100644 --- a/Cabal-tests/tests/ParserTests/regressions/version-sets.expr +++ b/Cabal-tests/tests/ParserTests/regressions/version-sets.expr @@ -121,6 +121,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/ParserTests/regressions/wl-pprint-indef.expr b/Cabal-tests/tests/ParserTests/regressions/wl-pprint-indef.expr index 03959b195c0..6e718e3e685 100644 --- a/Cabal-tests/tests/ParserTests/regressions/wl-pprint-indef.expr +++ b/Cabal-tests/tests/ParserTests/regressions/wl-pprint-indef.expr @@ -114,6 +114,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], @@ -202,6 +204,8 @@ GenericPackageDescription { [], sharedOptions = PerCompilerFlavor [] [], + profSharedOptions = + PerCompilerFlavor [] [], staticOptions = PerCompilerFlavor [] [], customFieldsBI = [], diff --git a/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs b/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs index 54624a617c3..d600a51fa05 100644 --- a/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs +++ b/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs @@ -33,15 +33,15 @@ md5Check proxy md5Int = structureHash proxy @?= md5FromInteger md5Int md5CheckGenericPackageDescription :: Proxy GenericPackageDescription -> Assertion md5CheckGenericPackageDescription proxy = md5Check proxy #if MIN_VERSION_base(4,19,0) - 0x44f8430d7366cf849e09669627573040 + 0xe28f08e7ac644f836d8b3fe7f9428dcf #else - 0x8ed837568017bde3abb4fcee244b9c9f + 0x3442058190aa48c2f795b83ee995f702 #endif md5CheckLocalBuildInfo :: Proxy LocalBuildInfo -> Assertion md5CheckLocalBuildInfo proxy = md5Check proxy #if MIN_VERSION_base(4,19,0) - 0xdff58fe5e7f9568c67cd982eaba7edc2 + 0x31b94dc3e61eb01fea1a1c3c73d984ee #else - 0x4e50a4a95779b862edde3d6696797251 + 0xdc2f5e7a9c696a4e0bd64f02a0140b74 #endif diff --git a/Cabal/Cabal.cabal b/Cabal/Cabal.cabal index e6a978234c2..deaad72cef1 100644 --- a/Cabal/Cabal.cabal +++ b/Cabal/Cabal.cabal @@ -101,6 +101,7 @@ library Distribution.Simple.BuildPaths Distribution.Simple.BuildTarget Distribution.Simple.BuildToolDepends + Distribution.Simple.BuildWay Distribution.Simple.CCompiler Distribution.Simple.Command Distribution.Simple.Compiler diff --git a/Cabal/src/Distribution/Simple/BuildPaths.hs b/Cabal/src/Distribution/Simple/BuildPaths.hs index 4c44bd380f2..05a9c6c190f 100644 --- a/Cabal/src/Distribution/Simple/BuildPaths.hs +++ b/Cabal/src/Distribution/Simple/BuildPaths.hs @@ -32,6 +32,7 @@ module Distribution.Simple.BuildPaths , mkProfLibName , mkGenericSharedLibName , mkSharedLibName + , mkProfSharedLibName , mkStaticLibName , mkGenericSharedBundledLibName , exeExtension @@ -283,6 +284,10 @@ mkSharedLibName :: Platform -> CompilerId -> UnitId -> String mkSharedLibName platform comp lib = mkGenericSharedLibName platform comp (getHSLibraryName lib) +mkProfSharedLibName :: Platform -> CompilerId -> UnitId -> String +mkProfSharedLibName platform comp lib = + mkGenericSharedLibName platform comp (getHSLibraryName lib ++ "_p") + -- Static libs are named the same as shared libraries, only with -- a different extension. mkStaticLibName :: Platform -> CompilerId -> UnitId -> String diff --git a/Cabal/src/Distribution/Simple/BuildWay.hs b/Cabal/src/Distribution/Simple/BuildWay.hs new file mode 100644 index 00000000000..614c229d462 --- /dev/null +++ b/Cabal/src/Distribution/Simple/BuildWay.hs @@ -0,0 +1,14 @@ +{-# LANGUAGE LambdaCase #-} + +module Distribution.Simple.BuildWay where + +data BuildWay = StaticWay | DynWay | ProfWay | ProfDynWay + deriving (Eq, Ord, Show, Read, Enum) + +-- | Returns the object/interface extension prefix for the given build way (e.g. "dyn_" for 'DynWay') +buildWayPrefix :: BuildWay -> String +buildWayPrefix = \case + StaticWay -> "" + ProfWay -> "p_" + DynWay -> "dyn_" + ProfDynWay -> "p_dyn_" diff --git a/Cabal/src/Distribution/Simple/Compiler.hs b/Cabal/src/Distribution/Simple/Compiler.hs index ae8d1c05136..7b9f2ac8059 100644 --- a/Cabal/src/Distribution/Simple/Compiler.hs +++ b/Cabal/src/Distribution/Simple/Compiler.hs @@ -63,6 +63,11 @@ module Distribution.Simple.Compiler , unitIdSupported , coverageSupported , profilingSupported + , profilingDynamicSupported + , profilingDynamicSupportedOrUnknown + , profilingVanillaSupported + , profilingVanillaSupportedOrUnknown + , dynamicSupported , backpackSupported , arResponseFilesSupported , arDashLSupported @@ -428,6 +433,49 @@ profilingSupported comp = GHCJS -> True _ -> False +-- | Returns Just if we can certainly determine whether a way is supported +-- if we don't know, return Nothing +waySupported :: String -> Compiler -> Maybe Bool +waySupported way comp = + case compilerFlavor comp of + GHC -> + -- Infomation about compiler ways is only accurately reported after + -- 9.10.1. Which is useful as this is before profiling dynamic support + -- was introduced. (See GHC #24881) + if compilerVersion comp >= mkVersion [9, 10, 1] + then case Map.lookup "RTS ways" (compilerProperties comp) of + Just ways -> Just (way `elem` words ways) + Nothing -> Just False + else Nothing + _ -> Nothing + +-- | Either profiling is definitely supported or we don't know (so assume +-- it is) +profilingVanillaSupportedOrUnknown :: Compiler -> Bool +profilingVanillaSupportedOrUnknown comp = profilingVanillaSupported comp `elem` [Just True, Nothing] + +-- | Is the compiler distributed with profiling libraries +profilingVanillaSupported :: Compiler -> Maybe Bool +profilingVanillaSupported comp = waySupported "p" comp + +-- | Is the compiler distributed with profiling dynamic libraries +profilingDynamicSupported :: Compiler -> Maybe Bool +profilingDynamicSupported comp = + -- Certainly not before this version, as it was not implemented yet. + if compilerVersion comp <= mkVersion [9, 11, 0] + then Just False + else waySupported "p_dyn" comp + +-- | Either profiling dynamic is definitely supported or we don't know (so assume +-- it is) +profilingDynamicSupportedOrUnknown :: Compiler -> Bool +profilingDynamicSupportedOrUnknown comp = + profilingDynamicSupported comp `elem` [Just True, Nothing] + +-- | Is the compiler distributed with dynamic libraries +dynamicSupported :: Compiler -> Maybe Bool +dynamicSupported comp = waySupported "dyn" comp + -- | Does this compiler support a package database entry with: -- "visibility"? libraryVisibilitySupported :: Compiler -> Bool diff --git a/Cabal/src/Distribution/Simple/Configure.hs b/Cabal/src/Distribution/Simple/Configure.hs index 8d90b0d8822..aa0e2a3a438 100644 --- a/Cabal/src/Distribution/Simple/Configure.hs +++ b/Cabal/src/Distribution/Simple/Configure.hs @@ -81,6 +81,7 @@ import Distribution.PackageDescription.Configuration import Distribution.PackageDescription.PrettyPrint import Distribution.Simple.BuildTarget import Distribution.Simple.BuildToolDepends +import Distribution.Simple.BuildWay import Distribution.Simple.Compiler import Distribution.Simple.LocalBuildInfo import Distribution.Simple.PackageIndex (InstalledPackageIndex, lookupUnitId) @@ -709,7 +710,7 @@ computeLocalBuildConfig cfg comp programDb = do -- rely on them. By the time that bug was fixed, ghci had -- been changed to read shared libraries instead of archive -- files (see next code block). - not (GHC.isDynamic comp) + not (GHC.compilerBuildWay comp `elem` [DynWay, ProfDynWay]) CompilerId GHCJS _ -> not (GHCJS.isDynamic comp) _ -> False @@ -734,7 +735,7 @@ computeLocalBuildConfig cfg comp programDb = do CompilerId GHC _ -> -- if ghc is dynamic, then ghci needs a shared -- library, so we build one by default. - GHC.isDynamic comp + GHC.compilerBuildWay comp == DynWay CompilerId GHCJS _ -> GHCJS.isDynamic comp _ -> False @@ -754,12 +755,6 @@ computeLocalBuildConfig cfg comp programDb = do withFullyStaticExe_ = fromFlag $ configFullyStaticExe cfg - when (withDynExe_ && not withSharedLib_) $ - warn verbosity $ - "Executables will use dynamic linking, but a shared library " - ++ "is not being built. Linking will fail if any executables " - ++ "depend on the library." - setProfiling <- configureProfiling verbosity cfg comp setCoverage <- configureCoverage verbosity cfg comp @@ -792,6 +787,7 @@ computeLocalBuildConfig cfg comp programDb = do , withDynExe = withDynExe_ , withFullyStaticExe = withFullyStaticExe_ , withProfLib = False + , withProfLibShared = False , withProfLibDetail = ProfDetailNone , withProfExe = False , withProfExeDetail = ProfDetailNone @@ -807,6 +803,20 @@ computeLocalBuildConfig cfg comp programDb = do , relocatable = fromFlagOrDefault False $ configRelocatable cfg } + -- Dynamic executable, but no shared vanilla libraries + when (LBC.withDynExe buildOptions && not (LBC.withProfExe buildOptions) && not (LBC.withSharedLib buildOptions)) $ + warn verbosity $ + "Executables will use dynamic linking, but a shared library " + ++ "is not being built. Linking will fail if any executables " + ++ "depend on the library." + + -- Profiled dynamic executable, but no shared profiling libraries + when (LBC.withDynExe buildOptions && LBC.withProfExe buildOptions && not (LBC.withProfLibShared buildOptions)) $ + warn verbosity $ + "Executables will use profiled dynamic linking, but a profiled shared library " + ++ "is not being built. Linking will fail if any executables " + ++ "depend on the library." + return $ LBC.LocalBuildConfig { extraConfigArgs = [] -- Currently configure does not @@ -1732,7 +1742,7 @@ configureCoverage verbosity cfg comp = do -- -- Note that @--enable-executable-profiling@ also affects profiling -- of benchmarks and (non-detailed) test suites. -computeEffectiveProfiling :: ConfigFlags -> (Bool {- lib -}, Bool {- exe -}) +computeEffectiveProfiling :: ConfigFlags -> (Bool {- lib vanilla-}, Bool {- lib shared -}, Bool {- exe -}) computeEffectiveProfiling cfg = -- The --profiling flag sets the default for both libs and exes, -- but can be overridden by --library-profiling, or the old deprecated @@ -1740,15 +1750,20 @@ computeEffectiveProfiling cfg = -- -- The --profiling-detail and --library-profiling-detail flags behave -- similarly - let tryExeProfiling = + let dynamicExe = fromFlagOrDefault False (configDynExe cfg) + tryExeProfiling = fromFlagOrDefault False (mappend (configProf cfg) (configProfExe cfg)) tryLibProfiling = fromFlagOrDefault - tryExeProfiling - (mappend (configProf cfg) (configProfLib cfg)) - in (tryLibProfiling, tryExeProfiling) + (tryExeProfiling && not dynamicExe) + (configProfLib cfg) + tryLibProfilingShared = + fromFlagOrDefault + (tryExeProfiling && dynamicExe) + (configProfShared cfg) + in (tryLibProfiling, tryLibProfilingShared, tryExeProfiling) -- | Select and apply profiling settings for the build based on the -- 'ConfigFlags' and 'Compiler'. @@ -1758,7 +1773,7 @@ configureProfiling -> Compiler -> IO (LBC.BuildOptions -> LBC.BuildOptions) configureProfiling verbosity cfg comp = do - let (tryLibProfiling, tryExeProfiling) = computeEffectiveProfiling cfg + let (tryLibProfiling, tryLibProfilingShared, tryExeProfiling) = computeEffectiveProfiling cfg tryExeProfileLevel = fromFlagOrDefault @@ -1785,8 +1800,8 @@ configureProfiling verbosity cfg comp = do return ProfDetailDefault checkProfileLevel other = return other - (exeProfWithoutLibProf, applyProfiling) <- - if profilingSupported comp + applyProfiling <- + if profilingSupported comp && (profilingVanillaSupportedOrUnknown comp || profilingDynamicSupportedOrUnknown comp) then do exeLevel <- checkProfileLevel tryExeProfileLevel libLevel <- checkProfileLevel tryLibProfileLevel @@ -1797,11 +1812,46 @@ configureProfiling verbosity cfg comp = do , LBC.withProfExe = tryExeProfiling , LBC.withProfExeDetail = exeLevel } - return (tryExeProfiling && not tryLibProfiling, apply) + let compilerSupportsProfilingDynamic = profilingDynamicSupportedOrUnknown comp + apply2 <- + if compilerSupportsProfilingDynamic + then -- Case 1: We support profiled shared libraries so turn on shared profiling + -- libraries if the user asked for it. + return $ \buildOptions -> apply buildOptions{LBC.withProfLibShared = tryLibProfilingShared} + else -- Case 2: Compiler doesn't support profiling shared so turn them off + do + -- If we wanted to enable profiling shared libraries.. tell the + -- user we couldn't. + when (profilingVanillaSupportedOrUnknown comp && tryLibProfilingShared) $ + warn + verbosity + ( "The compiler " + ++ showCompilerId comp + ++ " does not support " + ++ "profiling shared objects. Static profiled objects " + ++ "will be built." + ) + return $ \buildOptions -> + let original_options = apply buildOptions + in original_options + { LBC.withProfLibShared = False + , LBC.withProfLib = profilingVanillaSupportedOrUnknown comp && (tryLibProfilingShared || LBC.withProfLib original_options) + , LBC.withDynExe = if LBC.withProfExe original_options then False else LBC.withDynExe original_options + } + + when (tryExeProfiling && not (tryLibProfiling || tryLibProfilingShared)) $ do + warn + verbosity + ( "Executables will be built with profiling, but library " + ++ "profiling is disabled. Linking will fail if any executables " + ++ "depend on the library." + ) + return apply2 else do let apply buildOptions = buildOptions { LBC.withProfLib = False + , LBC.withProfLibShared = False , LBC.withProfLibDetail = ProfDetailNone , LBC.withProfExe = False , LBC.withProfExeDetail = ProfDetailNone @@ -1814,15 +1864,7 @@ configureProfiling verbosity cfg comp = do ++ " does not support " ++ "profiling. Profiling has been disabled." ) - return (False, apply) - - when exeProfWithoutLibProf $ - warn - verbosity - ( "Executables will be built with profiling, but library " - ++ "profiling is disabled. Linking will fail if any executables " - ++ "depend on the library." - ) + return apply return applyProfiling diff --git a/Cabal/src/Distribution/Simple/GHC.hs b/Cabal/src/Distribution/Simple/GHC.hs index 095e657264e..8d7dda4de34 100644 --- a/Cabal/src/Distribution/Simple/GHC.hs +++ b/Cabal/src/Distribution/Simple/GHC.hs @@ -61,7 +61,7 @@ module Distribution.Simple.GHC , Internal.componentCcGhcOptions , getGhcAppDir , getLibDir - , isDynamic + , compilerBuildWay , getGlobalPackageDB , pkgRoot @@ -98,6 +98,7 @@ import Distribution.Simple.BuildPaths import Distribution.Simple.Compiler import Distribution.Simple.Errors import qualified Distribution.Simple.GHC.Build as GHC +import Distribution.Simple.GHC.Build.Modules (BuildWay (..)) import Distribution.Simple.GHC.Build.Utils import Distribution.Simple.GHC.EnvironmentParser import Distribution.Simple.GHC.ImplInfo @@ -747,11 +748,28 @@ libAbiHash verbosity _pkg_descr lbi lib clbi = do , ghcOptObjSuffix = toFlag "p_o" , ghcOptExtra = hcProfOptions GHC libBi } - ghcArgs - | withVanillaLib lbi = vanillaArgs - | withSharedLib lbi = sharedArgs - | withProfLib lbi = profArgs - | otherwise = error "libAbiHash: Can't find an enabled library way" + profDynArgs = + vanillaArgs + `mappend` mempty + { ghcOptProfilingMode = toFlag True + , ghcOptProfilingAuto = + Internal.profDetailLevelFlag + True + (withProfLibDetail lbi) + , ghcOptDynLinkMode = toFlag GhcDynamicOnly + , ghcOptFPic = toFlag True + , ghcOptHiSuffix = toFlag "p_dyn_hi" + , ghcOptObjSuffix = toFlag "p_dyn_o" + , ghcOptExtra = hcProfSharedOptions GHC libBi + } + ghcArgs = + let (libWays, _, _) = buildWays lbi + in case libWays (componentIsIndefinite clbi) of + (ProfDynWay : _) -> profDynArgs + (ProfWay : _) -> profArgs + (StaticWay : _) -> vanillaArgs + (DynWay : _) -> sharedArgs + _ -> error "libAbiHash: Can't find an enabled library way" (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi) @@ -870,75 +888,90 @@ installLib -> ComponentLocalBuildInfo -> IO () installLib verbosity lbi targetDir dynlibTargetDir _builtDir pkg lib clbi = do + let + (wantedLibWays, _, _) = buildWays lbi + isIndef = componentIsIndefinite clbi + libWays = wantedLibWays isIndef + + info verbosity ("Wanted install ways: " ++ show libWays) + -- copy .hi files over: - whenVanilla $ copyModuleFiles $ Suffix "hi" - whenProf $ copyModuleFiles $ Suffix "p_hi" - whenShared $ copyModuleFiles $ Suffix "dyn_hi" + forM_ (wantedLibWays isIndef) $ \w -> case w of + StaticWay -> copyModuleFiles (Suffix "hi") + DynWay -> copyModuleFiles (Suffix "dyn_hi") + ProfWay -> copyModuleFiles (Suffix "p_hi") + ProfDynWay -> copyModuleFiles (Suffix "p_dyn_hi") -- copy extra compilation artifacts that ghc plugins may produce copyDirectoryIfExists extraCompilationArtifacts -- copy the built library files over: - whenHasCode $ do - whenVanilla $ do - sequence_ - [ installOrdinary + when (has_code && hasLib) $ do + forM_ libWays $ \w -> case w of + StaticWay -> do + sequence_ + [ installOrdinary + builtDir + targetDir + (mkGenericStaticLibName (l ++ f)) + | l <- + getHSLibraryName + (componentUnitId clbi) + : (extraBundledLibs (libBuildInfo lib)) + , f <- "" : extraLibFlavours (libBuildInfo lib) + ] + whenGHCi $ installOrdinary builtDir targetDir ghciLibName + ProfWay -> do + installOrdinary builtDir targetDir profileLibName + whenGHCi $ installOrdinary builtDir targetDir ghciProfLibName + ProfDynWay -> do + installShared builtDir - targetDir - (mkGenericStaticLibName (l ++ f)) - | l <- - getHSLibraryName - (componentUnitId clbi) - : (extraBundledLibs (libBuildInfo lib)) - , f <- "" : extraLibFlavours (libBuildInfo lib) - ] - whenGHCi $ installOrdinary builtDir targetDir ghciLibName - whenProf $ do - installOrdinary builtDir targetDir profileLibName - whenGHCi $ installOrdinary builtDir targetDir ghciProfLibName - whenShared $ - if - -- The behavior for "extra-bundled-libraries" changed in version 2.5.0. - -- See ghc issue #15837 and Cabal PR #5855. - | specVersion pkg < CabalSpecV3_0 -> do - sequence_ - [ installShared - builtDir - dynlibTargetDir - (mkGenericSharedLibName platform compiler_id (l ++ f)) - | l <- getHSLibraryName uid : extraBundledLibs (libBuildInfo lib) - , f <- "" : extraDynLibFlavours (libBuildInfo lib) - ] - | otherwise -> do - sequence_ - [ installShared - builtDir - dynlibTargetDir - ( mkGenericSharedLibName - platform - compiler_id - (getHSLibraryName uid ++ f) - ) - | f <- "" : extraDynLibFlavours (libBuildInfo lib) - ] - sequence_ - [ do - files <- getDirectoryContents (i builtDir) - let l' = - mkGenericSharedBundledLibName - platform - compiler_id - l - forM_ files $ \file -> - when (l' `isPrefixOf` file) $ do - isFile <- doesFileExist (i $ builtDir makeRelativePathEx file) - when isFile $ do - installShared - builtDir - dynlibTargetDir - file - | l <- extraBundledLibs (libBuildInfo lib) - ] + dynlibTargetDir + (mkProfSharedLibName platform compiler_id uid) + DynWay -> do + if + -- The behavior for "extra-bundled-libraries" changed in version 2.5.0. + -- See ghc issue #15837 and Cabal PR #5855. + | specVersion pkg < CabalSpecV3_0 -> do + sequence_ + [ installShared + builtDir + dynlibTargetDir + (mkGenericSharedLibName platform compiler_id (l ++ f)) + | l <- getHSLibraryName uid : extraBundledLibs (libBuildInfo lib) + , f <- "" : extraDynLibFlavours (libBuildInfo lib) + ] + | otherwise -> do + sequence_ + [ installShared + builtDir + dynlibTargetDir + ( mkGenericSharedLibName + platform + compiler_id + (getHSLibraryName uid ++ f) + ) + | f <- "" : extraDynLibFlavours (libBuildInfo lib) + ] + sequence_ + [ do + files <- getDirectoryContents (i builtDir) + let l' = + mkGenericSharedBundledLibName + platform + compiler_id + l + forM_ files $ \file -> + when (l' `isPrefixOf` file) $ do + isFile <- doesFileExist (i $ builtDir makeRelativePathEx file) + when isFile $ do + installShared + builtDir + dynlibTargetDir + file + | l <- extraBundledLibs (libBuildInfo lib) + ] where -- See Note [Symbolic paths] in Distribution.Utils.Path i = interpretSymbolicPathLBI lbi @@ -997,11 +1030,7 @@ installLib verbosity lbi targetDir dynlibTargetDir _builtDir pkg lib clbi = do Platform JavaScript _ -> True _ -> False has_code = not (componentIsIndefinite clbi) - whenHasCode = when has_code - whenVanilla = when (hasLib && withVanillaLib lbi) - whenProf = when (hasLib && withProfLib lbi && has_code) whenGHCi = when (hasLib && withGHCiLib lbi && has_code) - whenShared = when (hasLib && withSharedLib lbi && has_code) -- ----------------------------------------------------------------------------- -- Registering diff --git a/Cabal/src/Distribution/Simple/GHC/Build.hs b/Cabal/src/Distribution/Simple/GHC/Build.hs index 51f7d650338..1f88f07552b 100644 --- a/Cabal/src/Distribution/Simple/GHC/Build.hs +++ b/Cabal/src/Distribution/Simple/GHC/Build.hs @@ -6,19 +6,17 @@ import Distribution.Compat.Prelude import Prelude () import Control.Monad.IO.Class -import qualified Data.Set as Set import Distribution.PackageDescription as PD hiding (buildInfo) import Distribution.Simple.Build.Inputs import Distribution.Simple.Flag (Flag) import Distribution.Simple.GHC.Build.ExtraSources import Distribution.Simple.GHC.Build.Link import Distribution.Simple.GHC.Build.Modules -import Distribution.Simple.GHC.Build.Utils (withDynFLib) import Distribution.Simple.LocalBuildInfo import Distribution.Simple.Program.Builtin (ghcProgram) import Distribution.Simple.Program.Db (requireProgram) import Distribution.Simple.Utils -import Distribution.Types.ComponentLocalBuildInfo (componentIsIndefinite) +import Distribution.Types.ComponentLocalBuildInfo import Distribution.Types.ParStrat import Distribution.Utils.NubList (fromNubListR) import Distribution.Utils.Path @@ -70,10 +68,10 @@ build build numJobs pkg_descr pbci = do let verbosity = buildVerbosity pbci - component = buildComponent pbci isLib = buildIsLib pbci lbi = localBuildInfo pbci clbi = buildCLBI pbci + isIndef = componentIsIndefinite clbi mbWorkDir = mbWorkDirLBI lbi i = interpretSymbolicPathLBI lbi -- See Note [Symbolic paths] in Distribution.Utils.Path @@ -110,41 +108,14 @@ build numJobs pkg_descr pbci = do (ghcProg, _) <- liftIO $ requireProgram verbosity ghcProgram (withPrograms lbi) - -- Determine in which ways we want to build the component - let - wantVanilla = if isLib then withVanillaLib lbi else False - -- Arguably, wantStatic should be "withFullyStaticExe lbi" for executables, - -- but it was not before the refactor. - wantStatic = if isLib then withStaticLib lbi else not (wantDynamic || wantProf) - wantDynamic = case component of - CLib{} -> withSharedLib lbi - CFLib flib -> withDynFLib flib - CExe{} -> withDynExe lbi - CTest{} -> withDynExe lbi - CBench{} -> withDynExe lbi - wantProf = if isLib then withProfLib lbi else withProfExe lbi - - -- See also Note [Building Haskell Modules accounting for TH] in Distribution.Simple.GHC.Build.Modules - -- We build static by default if no other way is wanted. - -- For executables and foreign libraries, there should only be one wanted way. - wantedWays = - Set.fromList $ - -- If building a library, we accumulate all the ways, - -- otherwise, we take just one. - (if isLib then id else take 1) $ - [ProfWay | wantProf] - -- I don't see why we shouldn't build with dynamic - -- indefinite components. - <> [DynWay | wantDynamic && not (componentIsIndefinite clbi)] - <> [StaticWay | wantStatic || wantVanilla || not (wantDynamic || wantProf)] - - liftIO $ info verbosity ("Wanted build ways: " ++ show (Set.toList wantedWays)) + let wantedWays@(wantedLibWays, _, wantedExeWay) = buildWays lbi + liftIO $ info verbosity ("Wanted build ways(" ++ show isLib ++ "): " ++ show (if isLib then wantedLibWays isIndef else [wantedExeWay])) -- We need a separate build and link phase, and C sources must be compiled -- after Haskell modules, because C sources may depend on stub headers -- generated from compiling Haskell modules (#842, #3294). - buildOpts <- buildHaskellModules numJobs ghcProg pkg_descr buildTargetDir wantedWays pbci - extraSources <- buildAllExtraSources ghcProg buildTargetDir pbci + buildOpts <- buildHaskellModules numJobs ghcProg pkg_descr buildTargetDir (wantedLibWays isIndef) pbci + extraSources <- buildAllExtraSources ghcProg buildTargetDir wantedWays pbci linkOrLoadComponent ghcProg pkg_descr diff --git a/Cabal/src/Distribution/Simple/GHC/Build/ExtraSources.hs b/Cabal/src/Distribution/Simple/GHC/Build/ExtraSources.hs index fc204cda30a..83bcf9a6bca 100644 --- a/Cabal/src/Distribution/Simple/GHC/Build/ExtraSources.hs +++ b/Cabal/src/Distribution/Simple/GHC/Build/ExtraSources.hs @@ -19,6 +19,7 @@ import Distribution.Types.Component import Distribution.Types.TargetInfo import Distribution.Simple.Build.Inputs +import Distribution.Simple.GHC.Build.Modules import Distribution.Simple.GHC.Build.Utils import Distribution.Simple.LocalBuildInfo import Distribution.Simple.Program.Types @@ -35,6 +36,8 @@ buildAllExtraSources -- ^ The GHC configured program -> SymbolicPath Pkg (Dir Artifacts) -- ^ The build directory for this target + -> (Bool -> [BuildWay], Bool -> BuildWay, BuildWay) + -- ^ Needed build ways -> PreBuildComponentInputs -- ^ The context and component being built in it. -> IO (NubListR (SymbolicPath Pkg File)) @@ -57,6 +60,8 @@ buildCSources -- ^ The GHC configured program -> SymbolicPath Pkg (Dir Artifacts) -- ^ The build directory for this target + -> (Bool -> [BuildWay], Bool -> BuildWay, BuildWay) + -- ^ Needed build ways -> PreBuildComponentInputs -- ^ The context and component being built in it. -> IO (NubListR (SymbolicPath Pkg File)) @@ -65,7 +70,6 @@ buildCSources = buildExtraSources "C Sources" Internal.componentCcGhcOptions - True ( \c -> do let cFiles = cSources (componentBuildInfo c) case c of @@ -81,7 +85,6 @@ buildCxxSources = buildExtraSources "C++ Sources" Internal.componentCxxGhcOptions - True ( \c -> do let cxxFiles = cxxSources (componentBuildInfo c) case c of @@ -93,13 +96,12 @@ buildCxxSources = -- is relative to the package. _otherwise -> cxxFiles ) -buildJsSources ghcProg buildTargetDir = do +buildJsSources ghcProg buildTargetDir neededWays = do Platform hostArch _ <- hostPlatform <$> localBuildInfo let hasJsSupport = hostArch == JavaScript buildExtraSources "JS Sources" Internal.componentJsGhcOptions - False ( \c -> if hasJsSupport then -- JS files are C-like with GHC's JS backend: they are @@ -111,17 +113,16 @@ buildJsSources ghcProg buildTargetDir = do ) ghcProg buildTargetDir + neededWays buildAsmSources = buildExtraSources "Assembler Sources" Internal.componentAsmGhcOptions - True (asmSources . componentBuildInfo) buildCmmSources = buildExtraSources "C-- Sources" Internal.componentCmmGhcOptions - True (cmmSources . componentBuildInfo) -- | Create 'PreBuildComponentRules' for a given type of extra build sources @@ -142,10 +143,6 @@ buildExtraSources -- invocation of GHC when compiling these extra sources (e.g. -- @'Internal.componentCxxGhcOptions'@, -- @'Internal.componentCmmGhcOptions'@) - -> Bool - -- ^ Some types of build sources should not be built in the dynamic way, namely, JS sources. - -- I'm not entirely sure this remains true after we migrate to supporting GHC's JS backend rather than GHCJS. - -- Boolean for "do we allow building these sources the dynamic way?" -> (Component -> [SymbolicPath Pkg File]) -- ^ View the extra sources of a component, typically from -- the build info (e.g. @'asmSources'@, @'cSources'@). @@ -156,108 +153,109 @@ buildExtraSources -- ^ The GHC configured program -> SymbolicPath Pkg (Dir Artifacts) -- ^ The build directory for this target + -> (Bool -> [BuildWay], Bool -> BuildWay, BuildWay) + -- ^ Needed build ways -> PreBuildComponentInputs -- ^ The context and component being built in it. -> IO (NubListR (SymbolicPath Pkg File)) -- ^ Returns the list of extra sources that were built -buildExtraSources description componentSourceGhcOptions wantDyn viewSources ghcProg buildTargetDir = - \PreBuildComponentInputs{buildingWhat, localBuildInfo = lbi, targetInfo} -> do - let - bi = componentBuildInfo (targetComponent targetInfo) - verbosity = buildingWhatVerbosity buildingWhat - clbi = targetCLBI targetInfo - mbWorkDir = mbWorkDirLBI lbi - i = interpretSymbolicPath mbWorkDir - sources = viewSources (targetComponent targetInfo) - comp = compiler lbi - platform = hostPlatform lbi - -- Instead of keeping this logic here, we really just want to - -- receive as an input the `neededWays` from GHC/Build.build and build - -- accordingly, since we've already determined the extra needed ways - -- needed for e.g. template haskell. Although we'd have to account for 'wantDyn'. - isGhcDynamic = isDynamic comp - doingTH = usesTemplateHaskellOrQQ bi - forceSharedLib = doingTH && isGhcDynamic - runGhcProg = runGHC verbosity ghcProg comp platform +buildExtraSources + description + componentSourceGhcOptions + viewSources + ghcProg + buildTargetDir + (neededLibWays, neededFLibWay, neededExeWay) = + \PreBuildComponentInputs{buildingWhat, localBuildInfo = lbi, targetInfo} -> do + let + bi = componentBuildInfo (targetComponent targetInfo) + verbosity = buildingWhatVerbosity buildingWhat + clbi = targetCLBI targetInfo + isIndef = componentIsIndefinite clbi + mbWorkDir = mbWorkDirLBI lbi + i = interpretSymbolicPath mbWorkDir + sources = viewSources (targetComponent targetInfo) + comp = compiler lbi + platform = hostPlatform lbi + runGhcProg = runGHC verbosity ghcProg comp platform - buildAction :: SymbolicPath Pkg File -> IO () - buildAction sourceFile = do - let baseSrcOpts = - componentSourceGhcOptions - verbosity - lbi - bi - clbi - buildTargetDir - sourceFile - vanillaSrcOpts - -- Dynamic GHC requires C sources to be built - -- with -fPIC for REPL to work. See #2207. - | isGhcDynamic && wantDyn = baseSrcOpts{ghcOptFPic = toFlag True} - | otherwise = baseSrcOpts - profSrcOpts = - vanillaSrcOpts - `mappend` mempty - { ghcOptProfilingMode = toFlag True - } - sharedSrcOpts = - vanillaSrcOpts - `mappend` mempty - { ghcOptFPic = toFlag True - , ghcOptDynLinkMode = toFlag GhcDynamicOnly - } - -- TODO: Placing all Haskell, C, & C++ objects in a single directory - -- Has the potential for file collisions. In general we would - -- consider this a user error. However, we should strive to - -- add a warning if this occurs. - odir = fromFlag (ghcOptObjDir vanillaSrcOpts) + buildAction :: SymbolicPath Pkg File -> IO () + buildAction sourceFile = do + let baseSrcOpts = + componentSourceGhcOptions + verbosity + lbi + bi + clbi + buildTargetDir + sourceFile + vanillaSrcOpts = + -- -fPIC is used in case you are using the repl + -- of a dynamically linked GHC + baseSrcOpts{ghcOptFPic = toFlag True} + profSrcOpts = + vanillaSrcOpts + `mappend` mempty + { ghcOptProfilingMode = toFlag True + } + sharedSrcOpts = + vanillaSrcOpts + `mappend` mempty + { ghcOptFPic = toFlag True + , ghcOptDynLinkMode = toFlag GhcDynamicOnly + } + profSharedSrcOpts = + vanillaSrcOpts + `mappend` mempty + { ghcOptProfilingMode = toFlag True + , ghcOptFPic = toFlag True + , ghcOptDynLinkMode = toFlag GhcDynamicOnly + } + -- TODO: Placing all Haskell, C, & C++ objects in a single directory + -- Has the potential for file collisions. In general we would + -- consider this a user error. However, we should strive to + -- add a warning if this occurs. + odir = fromFlag (ghcOptObjDir vanillaSrcOpts) - compileIfNeeded :: GhcOptions -> IO () - compileIfNeeded opts = do - needsRecomp <- checkNeedsRecompilation mbWorkDir sourceFile opts - when needsRecomp $ runGhcProg mbWorkDir opts + compileIfNeeded :: GhcOptions -> IO () + compileIfNeeded opts = do + needsRecomp <- checkNeedsRecompilation mbWorkDir sourceFile opts + when needsRecomp $ runGhcProg mbWorkDir opts - -- TODO: This whole section can be streamlined to the - -- wantedWays+neededWays logic used in Build/Modules.hs - createDirectoryIfMissingVerbose verbosity True (i odir) - case targetComponent targetInfo of - -- For libraries, we compile extra objects in the three ways: vanilla, shared, and profiled. - -- We suffix shared objects with .dyn_o and profiled ones with .p_o. - CLib _lib - -- Unless for repl, in which case we only need the vanilla way - | BuildRepl _ <- buildingWhat -> - compileIfNeeded vanillaSrcOpts - | otherwise -> - do + createDirectoryIfMissingVerbose verbosity True (i odir) + case targetComponent targetInfo of + -- For libraries, we compile extra objects in the four ways: vanilla, shared, profiled and profiled shared. + -- We suffix shared objects with `.dyn_o`, profiled ones with `.p_o` and profiled shared ones with `.p_dyn_o`. + CLib _lib + -- Unless for repl, in which case we only need the vanilla way + | BuildRepl _ <- buildingWhat -> compileIfNeeded vanillaSrcOpts - when (wantDyn && (forceSharedLib || withSharedLib lbi)) $ - compileIfNeeded sharedSrcOpts{ghcOptObjSuffix = toFlag "dyn_o"} - when (withProfLib lbi) $ - compileIfNeeded profSrcOpts{ghcOptObjSuffix = toFlag "p_o"} - - -- For foreign libraries, we determine with which options to build the - -- objects (vanilla vs shared vs profiled) - CFLib flib - | withProfExe lbi -> -- It doesn't sound right to query "ProfExe" for a foreign library... - compileIfNeeded profSrcOpts - | withDynFLib flib && wantDyn -> - compileIfNeeded sharedSrcOpts - | otherwise -> - compileIfNeeded vanillaSrcOpts - -- For the remaining component types (Exec, Test, Bench), we also - -- determine with which options to build the objects (vanilla vs shared vs - -- profiled), but predicate is the same for the three kinds. - _exeLike - | withProfExe lbi -> - compileIfNeeded profSrcOpts - | withDynExe lbi && wantDyn -> - compileIfNeeded sharedSrcOpts - | otherwise -> - compileIfNeeded vanillaSrcOpts - -- build any sources - if (null sources || componentIsIndefinite clbi) - then return mempty - else do - info verbosity ("Building " ++ description ++ "...") - traverse_ buildAction sources - return (toNubListR sources) + | otherwise -> + do + forM_ (neededLibWays isIndef) $ \case + StaticWay -> compileIfNeeded vanillaSrcOpts + DynWay -> compileIfNeeded sharedSrcOpts{ghcOptObjSuffix = toFlag "dyn_o"} + ProfWay -> compileIfNeeded profSrcOpts{ghcOptObjSuffix = toFlag "p_o"} + ProfDynWay -> compileIfNeeded profSharedSrcOpts{ghcOptObjSuffix = toFlag "p_dyn_o"} + CFLib flib -> + case neededFLibWay (withDynFLib flib) of + StaticWay -> compileIfNeeded vanillaSrcOpts + DynWay -> compileIfNeeded sharedSrcOpts + ProfWay -> compileIfNeeded profSrcOpts + ProfDynWay -> compileIfNeeded profSharedSrcOpts + -- For the remaining component types (Exec, Test, Bench), we also + -- determine with which options to build the objects (vanilla vs shared vs + -- profiled), but predicate is the same for the three kinds. + _exeLike -> + case neededExeWay of + StaticWay -> compileIfNeeded vanillaSrcOpts + DynWay -> compileIfNeeded sharedSrcOpts + ProfWay -> compileIfNeeded profSrcOpts + ProfDynWay -> compileIfNeeded profSharedSrcOpts + -- build any sources + if (null sources || componentIsIndefinite clbi) + then return mempty + else do + info verbosity ("Building " ++ description ++ "...") + traverse_ buildAction sources + return (toNubListR sources) diff --git a/Cabal/src/Distribution/Simple/GHC/Build/Link.hs b/Cabal/src/Distribution/Simple/GHC/Build/Link.hs index ee0f21ffa6d..3f9f00c9d28 100644 --- a/Cabal/src/Distribution/Simple/GHC/Build/Link.hs +++ b/Cabal/src/Distribution/Simple/GHC/Build/Link.hs @@ -8,8 +8,6 @@ module Distribution.Simple.GHC.Build.Link where import Distribution.Compat.Prelude import Prelude () -import Control.Exception (assert) -import Control.Monad (forM_) import Control.Monad.IO.Class import qualified Data.ByteString.Lazy.Char8 as BS import qualified Data.Set as Set @@ -76,128 +74,148 @@ linkOrLoadComponent -> (SymbolicPath Pkg (Dir Artifacts), SymbolicPath Pkg (Dir Build)) -- ^ The build target dir, and the target dir. -- See Note [Build Target Dir vs Target Dir] in Distribution.Simple.GHC.Build - -> (Set.Set BuildWay, BuildWay -> GhcOptions) + -> ((Bool -> [BuildWay], Bool -> BuildWay, BuildWay), BuildWay -> GhcOptions) -- ^ The set of build ways wanted based on the user opts, and a function to -- convert a build way into the set of ghc options that were used to build -- that way. -> PreBuildComponentInputs -- ^ The context and component being built in it. -> IO () -linkOrLoadComponent ghcProg pkg_descr extraSources (buildTargetDir, targetDir) (wantedWays, buildOpts) pbci = do - let - verbosity = buildVerbosity pbci - target = targetInfo pbci - component = buildComponent pbci - what = buildingWhat pbci - lbi = localBuildInfo pbci - bi = buildBI pbci - clbi = buildCLBI pbci - mbWorkDir = mbWorkDirLBI lbi +linkOrLoadComponent + ghcProg + pkg_descr + extraSources + (buildTargetDir, targetDir) + ((wantedLibWays, wantedFLibWay, wantedExeWay), buildOpts) + pbci = do + let + verbosity = buildVerbosity pbci + target = targetInfo pbci + component = buildComponent pbci + what = buildingWhat pbci + lbi = localBuildInfo pbci + bi = buildBI pbci + clbi = buildCLBI pbci + isIndef = componentIsIndefinite clbi + mbWorkDir = mbWorkDirLBI lbi - -- See Note [Symbolic paths] in Distribution.Utils.Path - i = interpretSymbolicPathLBI lbi + -- See Note [Symbolic paths] in Distribution.Utils.Path + i = interpretSymbolicPathLBI lbi - -- ensure extra lib dirs exist before passing to ghc - cleanedExtraLibDirs <- liftIO $ filterM (doesDirectoryExist . i) (extraLibDirs bi) - cleanedExtraLibDirsStatic <- liftIO $ filterM (doesDirectoryExist . i) (extraLibDirsStatic bi) + -- ensure extra lib dirs exist before passing to ghc + cleanedExtraLibDirs <- liftIO $ filterM (doesDirectoryExist . i) (extraLibDirs bi) + cleanedExtraLibDirsStatic <- liftIO $ filterM (doesDirectoryExist . i) (extraLibDirsStatic bi) - let - extraSourcesObjs :: [RelativePath Artifacts File] - extraSourcesObjs = - [ makeRelativePathEx $ getSymbolicPath src `replaceExtension` objExtension - | src <- extraSources - ] - - -- TODO: Shouldn't we use withStaticLib for libraries and something else - -- for foreign libs in the three cases where we use `withFullyStaticExe` below? - linkerOpts rpaths = - mempty - { ghcOptLinkOptions = - PD.ldOptions bi - ++ [ "-static" - | withFullyStaticExe lbi - ] - -- Pass extra `ld-options` given - -- through to GHC's linker. - ++ maybe - [] - programOverrideArgs - (lookupProgram ldProgram (withPrograms lbi)) - , ghcOptLinkLibs = - if withFullyStaticExe lbi - then extraLibsStatic bi - else extraLibs bi - , ghcOptLinkLibPath = - toNubListR $ + let + extraSourcesObjs :: [RelativePath Artifacts File] + extraSourcesObjs = + [ makeRelativePathEx $ getSymbolicPath src `replaceExtension` objExtension + | src <- extraSources + ] + + -- TODO: Shouldn't we use withStaticLib for libraries and something else + -- for foreign libs in the three cases where we use `withFullyStaticExe` below? + linkerOpts rpaths = + mempty + { ghcOptLinkOptions = + PD.ldOptions bi + ++ [ "-static" + | withFullyStaticExe lbi + ] + -- Pass extra `ld-options` given + -- through to GHC's linker. + ++ maybe + [] + programOverrideArgs + (lookupProgram ldProgram (withPrograms lbi)) + , ghcOptLinkLibs = if withFullyStaticExe lbi - then cleanedExtraLibDirsStatic - else cleanedExtraLibDirs - , ghcOptLinkFrameworks = toNubListR $ map getSymbolicPath $ PD.frameworks bi - , ghcOptLinkFrameworkDirs = toNubListR $ PD.extraFrameworkDirs bi - , ghcOptInputFiles = - toNubListR - [ coerceSymbolicPath $ buildTargetDir obj - | obj <- extraSourcesObjs - ] - , ghcOptNoLink = Flag False - , ghcOptRPaths = rpaths - } - case what of - BuildRepl replFlags -> liftIO $ do - let - -- For repl we use the vanilla (static) ghc options - staticOpts = buildOpts StaticWay - replOpts = - staticOpts - { -- Repl options use Static as the base, but doesn't need to pass -static. - -- However, it maybe should, for uniformity. - ghcOptDynLinkMode = NoFlag - , ghcOptExtra = - Internal.filterGhciFlags - (ghcOptExtra staticOpts) - <> replOptionsFlags (replReplOptions replFlags) - , ghcOptInputModules = replNoLoad (replReplOptions replFlags) (ghcOptInputModules staticOpts) - , ghcOptInputFiles = replNoLoad (replReplOptions replFlags) (ghcOptInputFiles staticOpts) - } - -- For a normal compile we do separate invocations of ghc for - -- compiling as for linking. But for repl we have to do just - -- the one invocation, so that one has to include all the - -- linker stuff too, like -l flags and any .o files from C - -- files etc. - -- - -- TODO: The repl doesn't use the runtime paths from linkerOpts - -- (ghcOptRPaths), which looks like a bug. After the refactor we - -- can fix this. - `mappend` linkerOpts mempty - `mappend` mempty - { ghcOptMode = toFlag GhcModeInteractive - , ghcOptOptimisation = toFlag GhcNoOptimisation + then extraLibsStatic bi + else extraLibs bi + , ghcOptLinkLibPath = + toNubListR $ + if withFullyStaticExe lbi + then cleanedExtraLibDirsStatic + else cleanedExtraLibDirs + , ghcOptLinkFrameworks = toNubListR $ map getSymbolicPath $ PD.frameworks bi + , ghcOptLinkFrameworkDirs = toNubListR $ PD.extraFrameworkDirs bi + , ghcOptInputFiles = + toNubListR + [ coerceSymbolicPath $ buildTargetDir obj + | obj <- extraSourcesObjs + ] + , ghcOptNoLink = Flag False + , ghcOptRPaths = rpaths + } + + case what of + BuildRepl replFlags -> liftIO $ do + let + -- For repl we use the vanilla (static) ghc options + staticOpts = buildOpts StaticWay + replOpts = + staticOpts + { -- Repl options use Static as the base, but doesn't need to pass -static. + -- However, it maybe should, for uniformity. + ghcOptDynLinkMode = NoFlag + , ghcOptExtra = + Internal.filterGhciFlags + (ghcOptExtra staticOpts) + <> replOptionsFlags (replReplOptions replFlags) + } + -- For a normal compile we do separate invocations of ghc for + -- compiling as for linking. But for repl we have to do just + -- the one invocation, so that one has to include all the + -- linker stuff too, like -l flags and any .o files from C + -- files etc. + -- + -- TODO: The repl doesn't use the runtime paths from linkerOpts + -- (ghcOptRPaths), which looks like a bug. After the refactor we + -- can fix this. + `mappend` linkerOpts mempty + `mappend` mempty + { ghcOptMode = toFlag GhcModeInteractive + , ghcOptOptimisation = toFlag GhcNoOptimisation + } + replOpts_final = + replOpts + { ghcOptInputModules = replNoLoad (replReplOptions replFlags) (ghcOptInputModules replOpts) + , ghcOptInputFiles = replNoLoad (replReplOptions replFlags) (ghcOptInputFiles replOpts) } - -- TODO: problem here is we need the .c files built first, so we can load them - -- with ghci, but .c files can depend on .h files generated by ghc by ffi - -- exports. - when (case component of CLib lib -> null (allLibModules lib clbi); _ -> False) $ - warn verbosity "No exposed modules" - runReplOrWriteFlags ghcProg lbi replFlags replOpts (pkgName (PD.package pkg_descr)) target - _otherwise -> - let - runGhcProg = runGHC verbosity ghcProg comp platform mbWorkDir - platform = hostPlatform lbi - comp = compiler lbi - in - when (not $ componentIsIndefinite clbi) $ do - -- If not building dynamically, we don't pass any runtime paths. - rpaths <- if DynWay `Set.member` wantedWays then getRPaths pbci else return (toNubListR []) - liftIO $ do - info verbosity "Linking..." - let linkExeLike name = linkExecutable (linkerOpts rpaths) (wantedWays, buildOpts) targetDir name runGhcProg lbi - case component of - CLib lib -> linkLibrary buildTargetDir cleanedExtraLibDirs pkg_descr verbosity runGhcProg lib lbi clbi extraSources rpaths wantedWays - CFLib flib -> linkFLib flib bi lbi (linkerOpts rpaths) (wantedWays, buildOpts) targetDir runGhcProg - CExe exe -> linkExeLike (exeName exe) - CTest test -> linkExeLike (testName test) - CBench bench -> linkExeLike (benchmarkName bench) + -- TODO: problem here is we need the .c files built first, so we can load them + -- with ghci, but .c files can depend on .h files generated by ghc by ffi + -- exports. + when (case component of CLib lib -> null (allLibModules lib clbi); _ -> False) $ + warn verbosity "No exposed modules" + runReplOrWriteFlags ghcProg lbi replFlags replOpts_final (pkgName (PD.package pkg_descr)) target + _otherwise -> + let + runGhcProg = runGHC verbosity ghcProg comp platform mbWorkDir + platform = hostPlatform lbi + comp = compiler lbi + get_rpaths ways = + if DynWay `Set.member` ways then getRPaths pbci else return (toNubListR []) + in + when (not $ componentIsIndefinite clbi) $ do + -- If not building dynamically, we don't pass any runtime paths. + liftIO $ do + info verbosity "Linking..." + let linkExeLike name = do + rpaths <- get_rpaths (Set.singleton wantedExeWay) + linkExecutable (linkerOpts rpaths) (wantedExeWay, buildOpts) targetDir name runGhcProg lbi + case component of + CLib lib -> do + let libWays = wantedLibWays isIndef + rpaths <- get_rpaths (Set.fromList libWays) + linkLibrary buildTargetDir cleanedExtraLibDirs pkg_descr verbosity runGhcProg lib lbi clbi extraSources rpaths libWays + CFLib flib -> do + let flib_way = wantedFLibWay (withDynFLib flib) + rpaths <- get_rpaths (Set.singleton flib_way) + linkFLib flib bi lbi (linkerOpts rpaths) (flib_way, buildOpts) targetDir runGhcProg + CExe exe -> linkExeLike (exeName exe) + CTest test -> linkExeLike (testName test) + CBench bench -> linkExeLike (benchmarkName bench) -- | Link a library component linkLibrary @@ -217,7 +235,7 @@ linkLibrary -- ^ Extra build sources (that were compiled to objects) -> NubListR FilePath -- ^ A list with the runtime-paths (rpaths), or empty if not linking dynamically - -> Set.Set BuildWay + -> [BuildWay] -- ^ Wanted build ways and corresponding build options -> IO () linkLibrary buildTargetDir cleanedExtraLibDirs pkg_descr verbosity runGhcProg lib lbi clbi extraSources rpaths wantedWays = do @@ -237,6 +255,9 @@ linkLibrary buildTargetDir cleanedExtraLibDirs pkg_descr verbosity runGhcProg li sharedLibFilePath = buildTargetDir makeRelativePathEx (mkSharedLibName (hostPlatform lbi) compiler_id uid) + profSharedLibFilePath = + buildTargetDir + makeRelativePathEx (mkProfSharedLibName (hostPlatform lbi) compiler_id uid) staticLibFilePath = buildTargetDir makeRelativePathEx (mkStaticLibName (hostPlatform lbi) compiler_id uid) @@ -252,6 +273,9 @@ linkLibrary buildTargetDir cleanedExtraLibDirs pkg_descr verbosity runGhcProg li sharedLibInstallPath = libInstallPath mkSharedLibName (hostPlatform lbi) compiler_id uid + profSharedLibInstallPath = + libInstallPath + mkProfSharedLibName (hostPlatform lbi) compiler_id uid getObjFiles :: BuildWay -> IO [SymbolicPath Pkg File] getObjFiles way = @@ -358,6 +382,32 @@ linkLibrary buildTargetDir cleanedExtraLibDirs pkg_descr verbosity runGhcProg li toNubListR $ PD.extraFrameworkDirs libBi , ghcOptRPaths = rpaths } + ghcProfSharedLinkArgs pdynObjectFiles = + ghcBaseLinkArgs + { ghcOptShared = toFlag True + , ghcOptProfilingMode = toFlag True + , ghcOptProfilingAuto = + Internal.profDetailLevelFlag + True + (withProfLibDetail lbi) + , ghcOptDynLinkMode = toFlag GhcDynamicOnly + , ghcOptInputFiles = toNubListR pdynObjectFiles + , ghcOptOutputFile = toFlag profSharedLibFilePath + , -- For dynamic libs, Mac OS/X needs to know the install location + -- at build time. This only applies to GHC < 7.8 - see the + -- discussion in #1660. + ghcOptDylibName = + if hostOS == OSX + && ghcVersion < mkVersion [7, 8] + then toFlag profSharedLibInstallPath + else mempty + , ghcOptLinkLibs = extraLibs libBi + , ghcOptLinkLibPath = toNubListR $ cleanedExtraLibDirs + , ghcOptLinkFrameworks = toNubListR $ map getSymbolicPath $ PD.frameworks libBi + , ghcOptLinkFrameworkDirs = + toNubListR $ PD.extraFrameworkDirs libBi + , ghcOptRPaths = rpaths + } ghcStaticLinkArgs staticObjectFiles = ghcBaseLinkArgs { ghcOptStaticLib = toFlag True @@ -371,6 +421,7 @@ linkLibrary buildTargetDir cleanedExtraLibDirs pkg_descr verbosity runGhcProg li staticObjectFiles <- getObjFiles StaticWay profObjectFiles <- getObjFiles ProfWay dynamicObjectFiles <- getObjFiles DynWay + profDynamicObjectFiles <- getObjFiles ProfDynWay let linkWay = \case @@ -384,6 +435,8 @@ linkLibrary buildTargetDir cleanedExtraLibDirs pkg_descr verbosity runGhcProg li ldProg ghciProfLibFilePath profObjectFiles + ProfDynWay -> do + runGhcProg $ ghcProfSharedLinkArgs profDynamicObjectFiles DynWay -> do runGhcProg $ ghcSharedLinkArgs dynamicObjectFiles StaticWay -> do @@ -413,7 +466,7 @@ linkLibrary buildTargetDir cleanedExtraLibDirs pkg_descr verbosity runGhcProg li linkExecutable :: (GhcOptions) -- ^ The linker-specific GHC options - -> (Set.Set BuildWay, BuildWay -> GhcOptions) + -> (BuildWay, BuildWay -> GhcOptions) -- ^ The wanted build ways and corresponding GhcOptions that were -- used to compile the modules in that way. -> SymbolicPath Pkg (Dir Build) @@ -425,30 +478,27 @@ linkExecutable -- ^ Run the configured GHC program -> LocalBuildInfo -> IO () -linkExecutable linkerOpts (wantedWays, buildOpts) targetDir targetName runGhcProg lbi = do - -- When building an executable, we should only "want" one build way. - assert (Set.size wantedWays == 1) $ - forM_ wantedWays $ \way -> do - let baseOpts = buildOpts way - linkOpts = - baseOpts - `mappend` linkerOpts - `mappend` mempty - { -- If there are no input Haskell files we pass -no-hs-main, and - -- assume there is a main function in another non-haskell object - ghcOptLinkNoHsMain = toFlag (ghcOptInputFiles baseOpts == mempty && ghcOptInputScripts baseOpts == mempty) - } - comp = compiler lbi +linkExecutable linkerOpts (way, buildOpts) targetDir targetName runGhcProg lbi = do + let baseOpts = buildOpts way + linkOpts = + baseOpts + `mappend` linkerOpts + `mappend` mempty + { -- If there are no input Haskell files we pass -no-hs-main, and + -- assume there is a main function in another non-haskell object + ghcOptLinkNoHsMain = toFlag (ghcOptInputFiles baseOpts == mempty && ghcOptInputScripts baseOpts == mempty) + } + comp = compiler lbi - -- Work around old GHCs not relinking in this - -- situation, see #3294 - let target = - targetDir makeRelativePathEx (exeTargetName (hostPlatform lbi) targetName) - when (compilerVersion comp < mkVersion [7, 7]) $ do - let targetPath = interpretSymbolicPathLBI lbi target - e <- doesFileExist targetPath - when e (removeFile targetPath) - runGhcProg linkOpts{ghcOptOutputFile = toFlag target} + -- Work around old GHCs not relinking in this + -- situation, see #3294 + let target = + targetDir makeRelativePathEx (exeTargetName (hostPlatform lbi) targetName) + when (compilerVersion comp < mkVersion [7, 7]) $ do + let targetPath = interpretSymbolicPathLBI lbi target + e <- doesFileExist targetPath + when e (removeFile targetPath) + runGhcProg linkOpts{ghcOptOutputFile = toFlag target} -- | Link a foreign library component linkFLib @@ -457,7 +507,7 @@ linkFLib -> LocalBuildInfo -> (GhcOptions) -- ^ The linker-specific GHC options - -> (Set.Set BuildWay, BuildWay -> GhcOptions) + -> (BuildWay, BuildWay -> GhcOptions) -- ^ The wanted build ways and corresponding GhcOptions that were -- used to compile the modules in that way. -> SymbolicPath Pkg (Dir Build) @@ -466,7 +516,7 @@ linkFLib -> (GhcOptions -> IO ()) -- ^ Run the configured GHC program -> IO () -linkFLib flib bi lbi linkerOpts (wantedWays, buildOpts) targetDir runGhcProg = do +linkFLib flib bi lbi linkerOpts (way, buildOpts) targetDir runGhcProg = do let comp = compiler lbi @@ -498,8 +548,8 @@ linkFLib flib bi lbi linkerOpts (wantedWays, buildOpts) targetDir runGhcProg = d else statRtsVanillaLib (rtsStaticInfo rtsInfo) ] - linkOpts :: BuildWay -> GhcOptions - linkOpts way = case foreignLibType flib of + linkOpts :: GhcOptions + linkOpts = case foreignLibType flib of ForeignLibNativeShared -> (buildOpts way) `mappend` linkerOpts @@ -521,13 +571,10 @@ linkFLib flib bi lbi linkerOpts (wantedWays, buildOpts) targetDir runGhcProg = d -- soname on supported platforms. See also the note for -- @flibBuildName@. let buildName = flibBuildName lbi flib - -- There should not be more than one wanted way when building an flib - assert (Set.size wantedWays == 1) $ - forM_ wantedWays $ \way -> do - let outFile = targetDir makeRelativePathEx buildName - runGhcProg (linkOpts way){ghcOptOutputFile = toFlag outFile} - let i = interpretSymbolicPathLBI lbi - renameFile (i outFile) (i targetDir flibTargetName lbi flib) + let outFile = targetDir makeRelativePathEx buildName + runGhcProg linkOpts{ghcOptOutputFile = toFlag outFile} + let i = interpretSymbolicPathLBI lbi + renameFile (i outFile) (i targetDir flibTargetName lbi flib) -- | Calculate the RPATHs for the component we are building. -- diff --git a/Cabal/src/Distribution/Simple/GHC/Build/Modules.hs b/Cabal/src/Distribution/Simple/GHC/Build/Modules.hs index 9c9e55a03bf..0c89d860a1b 100644 --- a/Cabal/src/Distribution/Simple/GHC/Build/Modules.hs +++ b/Cabal/src/Distribution/Simple/GHC/Build/Modules.hs @@ -17,6 +17,7 @@ import Distribution.ModuleName (ModuleName) import qualified Distribution.PackageDescription as PD import Distribution.Pretty import Distribution.Simple.Build.Inputs +import Distribution.Simple.BuildWay import Distribution.Simple.Compiler import Distribution.Simple.GHC.Build.Utils import qualified Distribution.Simple.GHC.Internal as Internal @@ -102,8 +103,8 @@ buildHaskellModules -> SymbolicPath Pkg ('Dir Artifacts) -- ^ The path to the build directory for this target, which -- has already been created. - -> Set.Set BuildWay - -- ^ The set of wanted build ways according to user options + -> [BuildWay] + -- ^ The set of needed build ways according to user options -> PreBuildComponentInputs -- ^ The context and component being built in it. -> IO (BuildWay -> GhcOptions) @@ -111,7 +112,7 @@ buildHaskellModules -- invocation used to compile the component in that 'BuildWay'. -- This can be useful in, eg, a linker invocation, in which we want to use the -- same options and list the same inputs as those used for building. -buildHaskellModules numJobs ghcProg pkg_descr buildTargetDir wantedWays pbci = do +buildHaskellModules numJobs ghcProg pkg_descr buildTargetDir neededLibWays pbci = do -- See Note [Building Haskell Modules accounting for TH] let @@ -147,9 +148,6 @@ buildHaskellModules numJobs ghcProg pkg_descr buildTargetDir wantedWays pbci = d runGhcProg = runGHC verbosity ghcProg comp platform mbWorkDir platform = hostPlatform lbi - -- See Note [Building Haskell Modules accounting for TH] - doingTH = usesTemplateHaskellOrQQ bi - -- We define the base opts which are shared across different build ways in -- 'buildHaskellModules' baseOpts way = @@ -200,6 +198,18 @@ buildHaskellModules numJobs ghcProg pkg_descr buildTargetDir wantedWays pbci = d (if isLib then True else False) ((if isLib then withProfLibDetail else withProfExeDetail) lbi) } + profDynOpts = + (baseOpts ProfDynWay) + { ghcOptDynLinkMode = toFlag GhcDynamicOnly -- use -dynamic + , -- TODO: Does it hurt to set -fPIC for executables? + ghcOptFPic = toFlag True -- use -fPIC + , ghcOptProfilingMode = toFlag True + , ghcOptProfilingAuto = + Internal.profDetailLevelFlag + (if isLib then True else False) + ((if isLib then withProfLibDetail else withProfExeDetail) lbi) + } + -- Options for building both static and dynamic way at the same time, using -- the GHC flag -static and -dynamic-too dynTooOpts = @@ -212,45 +222,84 @@ buildHaskellModules numJobs ghcProg pkg_descr buildTargetDir wantedWays pbci = d -- (Note that `baseOtps StaticWay = hcStaticOptions`, not hcSharedOpts) } + profDynTooOpts = + (baseOpts ProfWay) + { ghcOptDynLinkMode = toFlag GhcStaticAndDynamic -- use -dynamic-too + , -- TODO: Does it hurt to set -fPIC for executables? + ghcOptFPic = toFlag True -- use -fPIC + , ghcOptProfilingMode = toFlag True + , ghcOptProfilingAuto = + Internal.profDetailLevelFlag + (if isLib then True else False) + ((if isLib then withProfLibDetail else withProfExeDetail) lbi) + , ghcOptDynHiSuffix = toFlag (buildWayPrefix ProfDynWay ++ "hi") + , ghcOptDynObjSuffix = toFlag (buildWayPrefix ProfDynWay ++ "o") + , ghcOptHPCDir = hpcdir Hpc.ProfDyn + -- Should we pass hcSharedOpts in the -dynamic-too ghc invocation? + -- (Note that `baseOtps StaticWay = hcStaticOptions`, not hcSharedOpts) + } + -- Determines how to build for each way, also serves as the base options -- for loading modules in 'linkOrLoadComponent' buildOpts way = case way of StaticWay -> staticOpts DynWay -> dynOpts ProfWay -> profOpts - - defaultGhcWay = if isDynamic comp then DynWay else StaticWay + ProfDynWay -> profDynOpts -- If there aren't modules, or if we're loading the modules in repl, don't build. unless (forRepl || (null inputFiles && null inputModules)) $ liftIO $ do -- See Note [Building Haskell Modules accounting for TH] let - neededWays = - wantedWays - <> Set.fromList - -- TODO: You also don't need to build the GHC way when doing TH if - -- you are using an external interpreter!! - [defaultGhcWay | doingTH && defaultGhcWay `Set.notMember` wantedWays] + neededLibWaysSet = Set.fromList neededLibWays -- If we need both static and dynamic, use dynamic-too instead of -- compiling twice (if we support it) useDynamicToo = - StaticWay `Set.member` neededWays - && DynWay `Set.member` neededWays + StaticWay `Set.member` neededLibWaysSet + && DynWay `Set.member` neededLibWaysSet + && supportsDynamicToo comp + && null (hcSharedOptions GHC bi) + + useProfDynamicToo = + ProfWay `Set.member` neededLibWaysSet + && ProfDynWay `Set.member` neededLibWaysSet && supportsDynamicToo comp && null (hcSharedOptions GHC bi) + defaultGhcWay = compilerBuildWay comp + + order w + | w == defaultGhcWay = 0 + | otherwise = fromEnum w + 1 + -- The ways we'll build, in order orderedBuilds - -- If we can use dynamic-too, do it first. The default GHC way can only - -- be static or dynamic, so, if we build both right away, any modules - -- possibly needed by TH later (e.g. if building profiled) are already built. + -- We need to make sure that the way which is the way the compiler is built + -- is built first so that Template Haskell works. + | useProfDynamicToo && useDynamicToo = + if defaultGhcWay `elem` [ProfDynWay, ProfWay] + then [buildProfAndProfDynamicToo, buildStaticAndDynamicToo] + else [buildStaticAndDynamicToo, buildProfAndProfDynamicToo] + | useProfDynamicToo && not useDynamicToo = + if defaultGhcWay `elem` [ProfDynWay, ProfWay] + then + [buildProfAndProfDynamicToo] + ++ (runGhcProg . buildOpts <$> neededLibWays \\ [ProfDynWay, ProfWay]) + else + (runGhcProg . buildOpts <$> neededLibWays \\ [ProfDynWay, ProfWay]) + ++ [buildProfAndProfDynamicToo] | useDynamicToo = - [buildStaticAndDynamicToo] - ++ (runGhcProg . buildOpts <$> Set.toList neededWays \\ [StaticWay, DynWay]) + if defaultGhcWay `elem` [StaticWay, DynWay] + then + [buildStaticAndDynamicToo] + ++ (runGhcProg . buildOpts <$> neededLibWays \\ [StaticWay, DynWay]) + else + (runGhcProg . buildOpts <$> neededLibWays \\ [StaticWay, DynWay]) + ++ [buildStaticAndDynamicToo] -- Otherwise, we need to ensure the defaultGhcWay is built first | otherwise = - runGhcProg . buildOpts <$> sortOn (\w -> if w == defaultGhcWay then 0 else fromEnum w + 1) (Set.toList neededWays) + runGhcProg . buildOpts <$> sortOn order neededLibWays buildStaticAndDynamicToo = do runGhcProg dynTooOpts @@ -264,27 +313,31 @@ buildHaskellModules numJobs ghcProg pkg_descr buildTargetDir wantedWays pbci = d -- both ways. copyDirectoryRecursive verbosity (i dynDir) (i vanillaDir) _ -> return () + + buildProfAndProfDynamicToo = do + runGhcProg profDynTooOpts + case (hpcdir Hpc.ProfDyn, hpcdir Hpc.Prof) of + (Flag profDynDir, Flag profDir) -> + -- When the vanilla and shared library builds are done + -- in one pass, only one set of HPC module interfaces + -- are generated. This set should suffice for both + -- static and dynamically linked executables. We copy + -- the modules interfaces so they are available under + -- both ways. + copyDirectoryRecursive verbosity (i profDynDir) (i profDir) + _ -> return () in -- REVIEW:ADD? info verbosity "Building Haskell Sources..." sequence_ orderedBuilds return buildOpts -data BuildWay = StaticWay | DynWay | ProfWay - deriving (Eq, Ord, Show, Enum) - --- | Returns the object/interface extension prefix for the given build way (e.g. "dyn_" for 'DynWay') -buildWayPrefix :: BuildWay -> String -buildWayPrefix = \case - StaticWay -> "" - ProfWay -> "p_" - DynWay -> "dyn_" - -- | Returns the corresponding 'Hpc.Way' for a 'BuildWay' buildWayHpcWay :: BuildWay -> Hpc.Way buildWayHpcWay = \case StaticWay -> Hpc.Vanilla ProfWay -> Hpc.Prof DynWay -> Hpc.Dyn + ProfDynWay -> Hpc.ProfDyn -- | Returns a function to extract the extra haskell compiler options from a -- 'BuildInfo' and 'CompilerFlavor' @@ -293,6 +346,7 @@ buildWayExtraHcOptions = \case StaticWay -> hcStaticOptions ProfWay -> hcProfOptions DynWay -> hcSharedOptions + ProfDynWay -> hcProfSharedOptions -- | Returns a pair of the Haskell input files and Haskell modules of the -- component being built. diff --git a/Cabal/src/Distribution/Simple/GHC/Build/Utils.hs b/Cabal/src/Distribution/Simple/GHC/Build/Utils.hs index fb8bd21351a..c87d074c202 100644 --- a/Cabal/src/Distribution/Simple/GHC/Build/Utils.hs +++ b/Cabal/src/Distribution/Simple/GHC/Build/Utils.hs @@ -13,6 +13,7 @@ import qualified Distribution.ModuleName as ModuleName import Distribution.PackageDescription as PD import Distribution.PackageDescription.Utils (cabalBug) import Distribution.Simple.BuildPaths +import Distribution.Simple.BuildWay import Distribution.Simple.Compiler import qualified Distribution.Simple.GHC.Internal as Internal import Distribution.Simple.Program.GHC @@ -47,10 +48,21 @@ findExecutableMain verbosity mbWorkDir buildDir (bnfo, modPath) = supportsDynamicToo :: Compiler -> Bool supportsDynamicToo = Internal.ghcLookupProperty "Support dynamic-too" +compilerBuildWay :: Compiler -> BuildWay +compilerBuildWay c = + case (isDynamic c, isProfiled c) of + (True, True) -> ProfDynWay + (True, False) -> DynWay + (False, True) -> ProfWay + (False, False) -> StaticWay + -- | Is this compiler's RTS dynamically linked? isDynamic :: Compiler -> Bool isDynamic = Internal.ghcLookupProperty "GHC Dynamic" +isProfiled :: Compiler -> Bool +isProfiled = Internal.ghcLookupProperty "GHC Profiled" + -- | Should we dynamically link the foreign library, based on its 'foreignLibType'? withDynFLib :: ForeignLib -> Bool withDynFLib flib = diff --git a/Cabal/src/Distribution/Simple/Hpc.hs b/Cabal/src/Distribution/Simple/Hpc.hs index ea1c1368057..4198d7a66ba 100644 --- a/Cabal/src/Distribution/Simple/Hpc.hs +++ b/Cabal/src/Distribution/Simple/Hpc.hs @@ -58,7 +58,7 @@ import System.Directory (createDirectoryIfMissing, doesFileExist) -- ------------------------------------------------------------------------- -- Haskell Program Coverage -data Way = Vanilla | Prof | Dyn +data Way = Vanilla | Prof | Dyn | ProfDyn deriving (Bounded, Enum, Eq, Read, Show) hpcDir @@ -73,6 +73,7 @@ hpcDir distPref way = distPref makeRelativePathEx ("hpc" wayDir) Vanilla -> "vanilla" Prof -> "prof" Dyn -> "dyn" + ProfDyn -> "prof_dyn" mixDir :: SymbolicPath Pkg (Dir Dist) diff --git a/Cabal/src/Distribution/Simple/LocalBuildInfo.hs b/Cabal/src/Distribution/Simple/LocalBuildInfo.hs index 35681ee5908..dce6ff0f8bb 100644 --- a/Cabal/src/Distribution/Simple/LocalBuildInfo.hs +++ b/Cabal/src/Distribution/Simple/LocalBuildInfo.hs @@ -36,6 +36,7 @@ module Distribution.Simple.LocalBuildInfo , interpretSymbolicPathLBI , mbWorkDirLBI , absoluteWorkingDirLBI + , buildWays -- * Buildable package components , Component (..) diff --git a/Cabal/src/Distribution/Simple/Setup/Config.hs b/Cabal/src/Distribution/Simple/Setup/Config.hs index 14e76c7d769..88c970e162f 100644 --- a/Cabal/src/Distribution/Simple/Setup/Config.hs +++ b/Cabal/src/Distribution/Simple/Setup/Config.hs @@ -127,6 +127,8 @@ data ConfigFlags = ConfigFlags , configProf :: Flag Bool -- ^ Enable profiling in the library -- and executables. + , configProfShared :: Flag Bool + -- ^ Enable shared profiling objects , configProfDetail :: Flag ProfDetailLevel -- ^ Profiling detail level -- in the library and executables. @@ -286,6 +288,7 @@ instance Eq ConfigFlags where && equal configProfExe && equal configProf && equal configProfDetail + && equal configProfShared && equal configProfLibDetail && equal configConfigureArgs && equal configOptimization @@ -518,6 +521,13 @@ configureOptions showOrParseArgs = configProf (\v flags -> flags{configProf = v}) (boolOpt [] []) + , option + "" + ["profiling-shared"] + "Build profiling shared libraries" + configProfShared + (\v flags -> flags{configProfShared = v}) + (boolOpt [] []) , option "" ["executable-profiling"] diff --git a/Cabal/src/Distribution/Types/LocalBuildConfig.hs b/Cabal/src/Distribution/Types/LocalBuildConfig.hs index 9126d92f1eb..ce9064b2f43 100644 --- a/Cabal/src/Distribution/Types/LocalBuildConfig.hs +++ b/Cabal/src/Distribution/Types/LocalBuildConfig.hs @@ -151,6 +151,8 @@ data BuildOptions = BuildOptions { withVanillaLib :: Bool -- ^ Whether to build normal libs. , withProfLib :: Bool + -- ^ Whether to build normal libs. + , withProfLibShared :: Bool -- ^ Whether to build profiling versions of libs. , withSharedLib :: Bool -- ^ Whether to build shared versions of libs. @@ -211,6 +213,7 @@ buildOptionsConfigFlags (BuildOptions{..}) = , configGHCiLib = toFlag $ withGHCiLib , configProfExe = toFlag $ withProfExe , configProfLib = toFlag $ withProfLib + , configProfShared = toFlag $ withProfLibShared , configProf = mempty , -- configProfDetail is for exe+lib, but overridden by configProfLibDetail -- so we specify both so we can specify independently diff --git a/Cabal/src/Distribution/Types/LocalBuildInfo.hs b/Cabal/src/Distribution/Types/LocalBuildInfo.hs index 3f9d8d74268..f6af8c29c77 100644 --- a/Cabal/src/Distribution/Types/LocalBuildInfo.hs +++ b/Cabal/src/Distribution/Types/LocalBuildInfo.hs @@ -28,11 +28,12 @@ module Distribution.Types.LocalBuildInfo , withPackageDB , withVanillaLib , withProfLib - , withSharedLib - , withStaticLib + , withProfLibShared , withDynExe , withFullyStaticExe , withProfExe + , withSharedLib + , withStaticLib , withProfLibDetail , withProfExeDetail , withOptimization @@ -82,6 +83,7 @@ module Distribution.Types.LocalBuildInfo , neededTargetsInBuildOrder' , withNeededTargetsInBuildOrder' , testCoverage + , buildWays -- * Functions you SHOULD NOT USE (yet), but are defined here to @@ -111,6 +113,7 @@ import Distribution.Utils.Path import Distribution.PackageDescription import Distribution.Pretty +import Distribution.Simple.BuildWay import Distribution.Simple.Compiler import Distribution.Simple.Flag import Distribution.Simple.InstallDirs hiding @@ -169,6 +172,7 @@ pattern LocalBuildInfo -> Bool -> Bool -> Bool + -> Bool -> ProfDetailLevel -> ProfDetailLevel -> OptimisationLevel @@ -201,6 +205,7 @@ pattern LocalBuildInfo , withPackageDB , withVanillaLib , withProfLib + , withProfLibShared , withSharedLib , withStaticLib , withDynExe @@ -252,6 +257,7 @@ pattern LocalBuildInfo LBC.BuildOptions { withVanillaLib , withProfLib + , withProfLibShared , withSharedLib , withStaticLib , withDynExe @@ -429,6 +435,49 @@ testCoverage :: LocalBuildInfo -> Bool testCoverage (LocalBuildInfo{exeCoverage = exes, libCoverage = libs}) = exes && libs +-- | Returns a list of ways, in the order which they should be built, and the +-- way we build executable and foreign library components. +-- +-- Ideally all this info should be fixed at configure time and not dependent on +-- additional info but `LocalBuildInfo` is per package (not per component) so it's +-- currently not possible to configure components to be built in certain ways. +buildWays :: LocalBuildInfo -> (Bool -> [BuildWay], Bool -> BuildWay, BuildWay) +buildWays lbi = + let + -- enable-library-profiling (enable (static profiling way)) .p_o + -- enable-shared (enabled dynamic way) .dyn_o + -- enable-profiling-shared (enable dyanmic profilng way) .p_dyn_o + -- enable-library-vanilla (enable vanilla way) .o + -- + -- enable-executable-dynamic => build dynamic executables + -- => --enable-profiling + --enable-executable-dynamic => build dynamic profiled executables + -- => --enable-profiling => build vanilla profiled executables + + wantedLibWays is_indef = + [ProfDynWay | withProfLibShared lbi && not is_indef] + <> [ProfWay | withProfLib lbi] + -- I don't see why we shouldn't build with dynamic-- indefinite components. + <> [DynWay | withSharedLib lbi && not is_indef] + -- MP: Ideally we should have `BuildOptions` on a per component basis, in + -- which case this `is_indef` check could be moved to configure time. + <> [StaticWay | withVanillaLib lbi || withStaticLib lbi] + + wantedFLibWay is_dyn_flib = + case (is_dyn_flib, withProfExe lbi) of + (True, True) -> ProfDynWay + (False, True) -> ProfWay + (True, False) -> DynWay + (False, False) -> StaticWay + + wantedExeWay = + case (withDynExe lbi, withProfExe lbi) of + (True, True) -> ProfDynWay + (True, False) -> DynWay + (False, True) -> ProfWay + (False, False) -> StaticWay + in + (wantedLibWays, wantedFLibWay, wantedExeWay) + ------------------------------------------------------------------------------- -- Stub functions to prevent someone from accidentally defining them diff --git a/cabal-install-solver/src/Distribution/Solver/Types/ConstraintSource.hs b/cabal-install-solver/src/Distribution/Solver/Types/ConstraintSource.hs index 3fdf64bde89..55b35212d3c 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/ConstraintSource.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/ConstraintSource.hs @@ -41,6 +41,10 @@ data ConstraintSource = -- from Cabal >= 3.11 | ConstraintSourceMultiRepl + | ConstraintSourceProfiledDynamic + -- | Constraint introduced by --enable-profiling-shared, which requires features + -- from Cabal >= 3.13 + -- | The source of the constraint is not specified. | ConstraintSourceUnknown @@ -72,6 +76,8 @@ showConstraintSource ConstraintSourceConfigFlagOrTarget = "config file, command line flag, or user target" showConstraintSource ConstraintSourceMultiRepl = "--enable-multi-repl" +showConstraintSource ConstraintSourceProfiledDynamic = + "--enable-profiling-shared" showConstraintSource ConstraintSourceUnknown = "unknown source" showConstraintSource ConstraintSetupCabalMinVersion = "minimum version of Cabal used by Setup.hs" diff --git a/cabal-install/src/Distribution/Client/Config.hs b/cabal-install/src/Distribution/Client/Config.hs index d9b91c959d0..5930ca98c13 100644 --- a/cabal-install/src/Distribution/Client/Config.hs +++ b/cabal-install/src/Distribution/Client/Config.hs @@ -490,6 +490,7 @@ instance Semigroup SavedConfig where , configVanillaLib = combine configVanillaLib , configProfLib = combine configProfLib , configProf = combine configProf + , configProfShared = combine configProfShared , configSharedLib = combine configSharedLib , configStaticLib = combine configStaticLib , configDynExe = combine configDynExe diff --git a/cabal-install/src/Distribution/Client/Dependency.hs b/cabal-install/src/Distribution/Client/Dependency.hs index 3f6a7fea32a..2949b4d21d1 100644 --- a/cabal-install/src/Distribution/Client/Dependency.hs +++ b/cabal-install/src/Distribution/Client/Dependency.hs @@ -64,6 +64,7 @@ module Distribution.Client.Dependency , addDefaultSetupDependencies , addSetupCabalMinVersionConstraint , addSetupCabalMaxVersionConstraint + , addSetupCabalProfiledDynamic ) where import Distribution.Client.Compat.Prelude @@ -671,6 +672,22 @@ addSetupCabalMaxVersionConstraint maxVersion = where cabalPkgname = mkPackageName "Cabal" +-- | Add an a lower bound @setup.Cabal >= 3.13@ labeled with 'ConstraintSourceProfiledDynamic' +addSetupCabalProfiledDynamic + :: DepResolverParams + -> DepResolverParams +addSetupCabalProfiledDynamic = + addConstraints + [ LabeledPackageConstraint + ( PackageConstraint + (ScopeAnySetupQualifier cabalPkgname) + (PackagePropertyVersion $ orLaterVersion (mkVersion [3, 13, 0])) + ) + ConstraintSourceProfiledDynamic + ] + where + cabalPkgname = mkPackageName "Cabal" + upgradeDependencies :: DepResolverParams -> DepResolverParams upgradeDependencies = setPreferenceDefault PreferAllLatest diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index 99dde932037..cec000b6a9b 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -102,9 +102,8 @@ import Distribution.Client.HttpUtils import Distribution.Client.Types import Distribution.Client.Utils.Parsec (renderParseError) +import Distribution.Solver.Types.ConstraintSource import Distribution.Solver.Types.PackageConstraint - ( PackageProperty (..) - ) import Distribution.Solver.Types.Settings import Distribution.Solver.Types.SourcePackage @@ -116,6 +115,7 @@ import Distribution.Client.Setup import Distribution.Client.SrcDist ( packageDirToSdist ) +import Distribution.Client.Targets import Distribution.Client.Types.SourceRepo ( SourceRepoList , SourceRepositoryPackage (..) @@ -136,11 +136,6 @@ import Distribution.Fields , showPWarning ) import Distribution.Package - ( PackageId - , PackageName - , UnitId - , packageId - ) import Distribution.PackageDescription.Parsec ( parseGenericPackageDescription ) @@ -195,8 +190,6 @@ import Distribution.Verbosity , verbose ) import Distribution.Version - ( Version - ) import qualified Codec.Archive.Tar as Tar import qualified Codec.Archive.Tar.Entry as Tar @@ -317,9 +310,34 @@ resolveSolverSettings where -- TODO: [required eventually] some of these settings need validation, e.g. -- the flag assignments need checking. + cabalPkgname = mkPackageName "Cabal" + + profilingDynamicConstraint = + ( UserConstraint + (UserAnySetupQualifier cabalPkgname) + (PackagePropertyVersion $ orLaterVersion (mkVersion [3, 13, 0])) + , ConstraintSourceProfiledDynamic + ) + + profDynEnabledGlobally = fromFlagOrDefault False (packageConfigProfShared projectConfigLocalPackages) + + profDynEnabledAnyLocally = + or + [ fromFlagOrDefault False (packageConfigProfShared ppc) + | (_, ppc) <- Map.toList (getMapMappend projectConfigSpecificPackage) + ] + + -- Add a setup.Cabal >= 3.13 constraint if prof+dyn is enabled globally + -- or any package in the project enables it. + -- Ideally we'd apply this constraint only on the closure of packages requiring prof+dyn, + -- but that would require another solver run for marginal advantages that + -- will further shrink as 3.13 is adopted. + solverCabalLibConstraints = + [profilingDynamicConstraint | profDynEnabledGlobally || profDynEnabledAnyLocally] + solverSettingRemoteRepos = fromNubList projectConfigRemoteRepos solverSettingLocalNoIndexRepos = fromNubList projectConfigLocalNoIndexRepos - solverSettingConstraints = projectConfigConstraints + solverSettingConstraints = solverCabalLibConstraints ++ projectConfigConstraints solverSettingPreferences = projectConfigPreferences solverSettingFlagAssignment = packageConfigFlagAssignment projectConfigLocalPackages solverSettingFlagAssignments = diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs index ddb6f615264..3d4dc29d8a0 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs @@ -768,6 +768,7 @@ convertLegacyPerPackageFlags , configFullyStaticExe = packageConfigFullyStaticExe , configProfExe = packageConfigProfExe , configProf = packageConfigProf + , configProfShared = packageConfigProfShared , configProfDetail = packageConfigProfDetail , configProfLibDetail = packageConfigProfLibDetail , configConfigureArgs = packageConfigConfigureArgs @@ -1074,6 +1075,7 @@ convertToLegacyAllPackageConfig , configFullyStaticExe = mempty , configProfExe = mempty , configProf = mempty + , configProfShared = mempty , configProfDetail = mempty , configProfLibDetail = mempty , configConfigureArgs = mempty @@ -1150,6 +1152,7 @@ convertToLegacyPerPackageConfig PackageConfig{..} = , configFullyStaticExe = packageConfigFullyStaticExe , configProfExe = packageConfigProfExe , configProf = packageConfigProf + , configProfShared = packageConfigProfShared , configProfDetail = packageConfigProfDetail , configProfLibDetail = packageConfigProfLibDetail , configConfigureArgs = packageConfigConfigureArgs @@ -1545,11 +1548,13 @@ legacyPackageConfigFieldDescrs = , "program-suffix" , "library-vanilla" , "library-profiling" + , "library-vanilla" , "shared" , "static" , "executable-dynamic" , "executable-static" , "profiling" + , "profiling-shared" , "executable-profiling" , "profiling-detail" , "library-profiling-detail" diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs index 2a6f9589cbb..08c27b00a3d 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs @@ -265,6 +265,7 @@ data PackageConfig = PackageConfig , packageConfigFullyStaticExe :: Flag Bool , packageConfigProf :: Flag Bool -- TODO: [code cleanup] sort out , packageConfigProfLib :: Flag Bool -- this duplication + , packageConfigProfShared :: Flag Bool , packageConfigProfExe :: Flag Bool -- and consistency , packageConfigProfDetail :: Flag ProfDetailLevel , packageConfigProfLibDetail :: Flag ProfDetailLevel diff --git a/cabal-install/src/Distribution/Client/ProjectOrchestration.hs b/cabal-install/src/Distribution/Client/ProjectOrchestration.hs index 2d963b0e07f..7f26ac12382 100644 --- a/cabal-install/src/Distribution/Client/ProjectOrchestration.hs +++ b/cabal-install/src/Distribution/Client/ProjectOrchestration.hs @@ -1061,7 +1061,7 @@ printPlan nubFlag x (Setup.Flag x') | x == x' = Setup.NoFlag nubFlag _ f = f - (tryLibProfiling, tryExeProfiling) = + (tryLibProfiling, tryLibProfilingShared, tryExeProfiling) = computeEffectiveProfiling fullConfigureFlags partialConfigureFlags = @@ -1072,7 +1072,8 @@ printPlan nubFlag tryExeProfiling (configProfExe fullConfigureFlags) , configProfLib = nubFlag tryLibProfiling (configProfLib fullConfigureFlags) - -- Maybe there are more we can add + , configProfShared = + nubFlag tryLibProfilingShared (configProfShared fullConfigureFlags) } in -- Not necessary to "escape" it, it's just for user output unwords . ("" :) $ diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index efc4ebbd1e4..d0f696be957 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -165,6 +165,8 @@ import Distribution.Simple.LocalBuildInfo , componentName , pkgComponents ) + +import Distribution.Simple.BuildWay import Distribution.Simple.PackageIndex (InstalledPackageIndex) import Distribution.Simple.Program import Distribution.Simple.Program.Db @@ -1627,13 +1629,18 @@ elaborateInstallPlan (map fst src_comps) let whyNotPerComp = why_not_per_component src_comps case NE.nonEmpty whyNotPerComp of - Nothing -> return comps + Nothing -> do + elaborationWarnings + return comps Just notPerCompReasons -> do checkPerPackageOk comps notPerCompReasons - return - [ elaborateSolverToPackage notPerCompReasons spkg g $ - comps ++ maybeToList setupComponent - ] + pkgComp <- + elaborateSolverToPackage + notPerCompReasons + spkg + g + (comps ++ maybeToList setupComponent) + return [pkgComp] Left cns -> dieProgress $ hang @@ -1696,7 +1703,7 @@ elaborateInstallPlan <+> fsep (punctuate comma $ map (text . whyNotPerComponent) $ toList reasons) -- TODO: Maybe exclude Backpack too - elab0 = elaborateSolverToCommon spkg + (elab0, elaborationWarnings) = elaborateSolverToCommon spkg pkgid = elabPkgSourceId elab0 pd = elabPkgDescription elab0 @@ -1992,7 +1999,7 @@ elaborateInstallPlan -> SolverPackage UnresolvedPkgLoc -> ComponentsGraph -> [ElaboratedConfiguredPackage] - -> ElaboratedConfiguredPackage + -> LogProgress ElaboratedConfiguredPackage elaborateSolverToPackage pkgWhyNotPerComponent pkg@( SolverPackage @@ -2003,13 +2010,14 @@ elaborateInstallPlan _exe_deps0 ) compGraph - comps = + comps = do -- Knot tying: the final elab includes the -- pkgInstalledId, which is calculated by hashing many -- of the other fields of the elaboratedPackage. - elab + elaborationWarnings + return elab where - elab0@ElaboratedConfiguredPackage{..} = + (elab0@ElaboratedConfiguredPackage{..}, elaborationWarnings) = elaborateSolverToCommon pkg elab1 = @@ -2095,7 +2103,7 @@ elaborateInstallPlan elaborateSolverToCommon :: SolverPackage UnresolvedPkgLoc - -> ElaboratedConfiguredPackage + -> (ElaboratedConfiguredPackage, LogProgress ()) elaborateSolverToCommon pkg@( SolverPackage (SourcePackage pkgid gdesc srcloc descOverride) @@ -2104,7 +2112,7 @@ elaborateInstallPlan deps0 _exe_deps0 ) = - elaboratedPackage + (elaboratedPackage, wayWarnings pkgid) where elaboratedPackage = ElaboratedConfiguredPackage{..} @@ -2212,13 +2220,14 @@ elaborateInstallPlan elabBuildOptions = LBC.BuildOptions { withVanillaLib = perPkgOptionFlag pkgid True packageConfigVanillaLib -- TODO: [required feature]: also needs to be handled recursively - , withSharedLib = pkgid `Set.member` pkgsUseSharedLibrary + , withSharedLib = canBuildSharedLibs && pkgid `Set.member` pkgsUseSharedLibrary , withStaticLib = perPkgOptionFlag pkgid False packageConfigStaticLib , withDynExe = perPkgOptionFlag pkgid False packageConfigDynExe , withFullyStaticExe = perPkgOptionFlag pkgid False packageConfigFullyStaticExe , withGHCiLib = perPkgOptionFlag pkgid False packageConfigGHCiLib -- TODO: [required feature] needs to default to enabled on windows still , withProfExe = perPkgOptionFlag pkgid False packageConfigProf - , withProfLib = pkgid `Set.member` pkgsUseProfilingLibrary + , withProfLib = canBuildProfilingLibs && pkgid `Set.member` pkgsUseProfilingLibrary + , withProfLibShared = canBuildProfilingSharedLibs && pkgid `Set.member` pkgsUseProfilingLibraryShared , exeCoverage = perPkgOptionFlag pkgid False packageConfigCoverage , libCoverage = perPkgOptionFlag pkgid False packageConfigCoverage , withOptimization = perPkgOptionFlag pkgid NormalOptimisation packageConfigOptimization @@ -2377,35 +2386,112 @@ elaborateInstallPlan pkgsUseSharedLibrary :: Set PackageId pkgsUseSharedLibrary = packagesWithLibDepsDownwardClosedProperty needsSharedLib + + needsSharedLib pkgid = + fromMaybe + compilerShouldUseSharedLibByDefault + -- Case 1: --enable-shared or --disable-shared is passed explicitly, honour that. + ( case pkgSharedLib of + Just v -> Just v + Nothing -> case pkgDynExe of + -- case 2: If --enable-executable-dynamic is passed then turn on + -- shared library generation. + Just True -> + -- Case 3: If --enable-profiling is passed, then we are going to + -- build profiled dynamic, so no need for shared libraries. + case pkgProf of + Just True -> if canBuildProfilingSharedLibs then Nothing else Just True + _ -> Just True + -- But don't necessarily turn off shared library generation if + -- --disable-executable-dynamic is passed. The shared objects might + -- be needed for something different. + _ -> Nothing + ) where - needsSharedLib pkg = - fromMaybe - compilerShouldUseSharedLibByDefault - (liftM2 (||) pkgSharedLib pkgDynExe) - where - pkgid = packageId pkg - pkgSharedLib = perPkgOptionMaybe pkgid packageConfigSharedLib - pkgDynExe = perPkgOptionMaybe pkgid packageConfigDynExe + pkgSharedLib = perPkgOptionMaybe pkgid packageConfigSharedLib + pkgDynExe = perPkgOptionMaybe pkgid packageConfigDynExe + pkgProf = perPkgOptionMaybe pkgid packageConfigProf -- TODO: [code cleanup] move this into the Cabal lib. It's currently open -- coded in Distribution.Simple.Configure, but should be made a proper -- function of the Compiler or CompilerInfo. compilerShouldUseSharedLibByDefault = case compilerFlavor compiler of - GHC -> GHC.isDynamic compiler + GHC -> GHC.compilerBuildWay compiler == DynWay && canBuildSharedLibs GHCJS -> GHCJS.isDynamic compiler _ -> False + compilerShouldUseProfilingLibByDefault = + case compilerFlavor compiler of + GHC -> GHC.compilerBuildWay compiler == ProfWay && canBuildProfilingLibs + _ -> False + + compilerShouldUseProfilingSharedLibByDefault = + case compilerFlavor compiler of + GHC -> GHC.compilerBuildWay compiler == ProfDynWay && canBuildProfilingSharedLibs + _ -> False + + -- Returns False if we definitely can't build shared libs + canBuildWayLibs predicate = case predicate compiler of + Just can_build -> can_build + -- If we don't know for certain, just assume we can + -- which matches behaviour in previous cabal releases + Nothing -> True + + canBuildSharedLibs = canBuildWayLibs dynamicSupported + canBuildProfilingLibs = canBuildWayLibs profilingVanillaSupported + canBuildProfilingSharedLibs = canBuildWayLibs profilingDynamicSupported + + wayWarnings pkg = do + when + (needsProfilingLib pkg && not canBuildProfilingLibs) + (warnProgress (text "Compiler does not support building p libraries, profiling is disabled")) + when + (needsSharedLib pkg && not canBuildSharedLibs) + (warnProgress (text "Compiler does not support building dyn libraries, dynamic libraries are disabled")) + when + (needsProfilingLibShared pkg && not canBuildProfilingSharedLibs) + (warnProgress (text "Compiler does not support building p_dyn libraries, profiling dynamic libraries are disabled.")) + pkgsUseProfilingLibrary :: Set PackageId pkgsUseProfilingLibrary = packagesWithLibDepsDownwardClosedProperty needsProfilingLib + + needsProfilingLib pkg = + fromFlagOrDefault compilerShouldUseProfilingLibByDefault (profBothFlag <> profLibFlag) where - needsProfilingLib pkg = - fromFlagOrDefault False (profBothFlag <> profLibFlag) - where - pkgid = packageId pkg - profBothFlag = lookupPerPkgOption pkgid packageConfigProf - profLibFlag = lookupPerPkgOption pkgid packageConfigProfLib + pkgid = packageId pkg + profBothFlag = lookupPerPkgOption pkgid packageConfigProf + profLibFlag = lookupPerPkgOption pkgid packageConfigProfLib + + pkgsUseProfilingLibraryShared :: Set PackageId + pkgsUseProfilingLibraryShared = + packagesWithLibDepsDownwardClosedProperty needsProfilingLibShared + + needsProfilingLibShared pkg = + fromMaybe + compilerShouldUseProfilingSharedLibByDefault + -- case 1: If --enable-profiling-shared is passed explicitly, honour that + ( case profLibSharedFlag of + Just v -> Just v + Nothing -> case pkgDynExe of + Just True -> + case pkgProf of + -- case 2: --enable-executable-dynamic + --enable-profiling + -- turn on shared profiling libraries + Just True -> if canBuildProfilingSharedLibs then Just True else Nothing + _ -> Nothing + -- But don't necessarily turn off shared library generation is + -- --disable-executable-dynamic is passed. The shared objects might + -- be needed for something different. + _ -> Nothing + ) + where + pkgid = packageId pkg + profLibSharedFlag = perPkgOptionMaybe pkgid packageConfigProfShared + pkgDynExe = perPkgOptionMaybe pkgid packageConfigDynExe + pkgProf = perPkgOptionMaybe pkgid packageConfigProf + -- TODO: [code cleanup] unused: the old deprecated packageConfigProfExe libDepGraph = @@ -2422,7 +2508,7 @@ elaborateInstallPlan libDepGraph [ Graph.nodeKey pkg | pkg <- SolverInstallPlan.toList solverPlan - , property pkg -- just the packages that satisfy the property + , property (packageId pkg) -- just the packages that satisfy the property -- TODO: [nice to have] this does not check the config consistency, -- e.g. a package explicitly turning off profiling, but something -- depending on it that needs profiling. This really needs a separate @@ -3837,7 +3923,7 @@ setupHsConfigureFlags sanityCheckElaboratedConfiguredPackage sharedConfig elab - (Cabal.ConfigFlags{..}) + Cabal.ConfigFlags{..} where Cabal.ConfigFlags { configVanillaLib @@ -3848,6 +3934,7 @@ setupHsConfigureFlags , configGHCiLib , -- , configProfExe -- overridden configProfLib + , configProfShared , -- , configProf -- overridden configProfDetail , configProfLibDetail diff --git a/cabal-install/src/Distribution/Client/Setup.hs b/cabal-install/src/Distribution/Client/Setup.hs index 8fea76bae3b..0df20fb4569 100644 --- a/cabal-install/src/Distribution/Client/Setup.hs +++ b/cabal-install/src/Distribution/Client/Setup.hs @@ -679,7 +679,7 @@ filterConfigureFlags' :: ConfigFlags -> Version -> ConfigFlags filterConfigureFlags' flags cabalLibVersion -- NB: we expect the latest version to be the most common case, -- so test it first. - | cabalLibVersion >= mkVersion [3, 11, 0] = flags_latest + | cabalLibVersion >= mkVersion [3, 13, 0] = flags_latest -- The naming convention is that flags_version gives flags with -- all flags *introduced* in version eliminated. -- It is NOT the latest version of Cabal library that @@ -701,6 +701,7 @@ filterConfigureFlags' flags cabalLibVersion | cabalLibVersion < mkVersion [2, 5, 0] = flags_2_5_0 | cabalLibVersion < mkVersion [3, 7, 0] = flags_3_7_0 | cabalLibVersion < mkVersion [3, 11, 0] = flags_3_11_0 + | cabalLibVersion < mkVersion [3, 13, 0] = flags_3_13_0 | otherwise = error "the impossible just happened" -- see first guard where flags_latest = @@ -712,8 +713,15 @@ filterConfigureFlags' flags cabalLibVersion configConstraints = [] } - flags_3_11_0 = + flags_3_13_0 = + -- Earlier Cabal versions don't understand about .. flags_latest + { -- Building profiled shared libraries + configProfShared = NoFlag + } + + flags_3_11_0 = + flags_3_13_0 { -- It's too late to convert configPromisedDependencies to anything -- meaningful, so we just assert that it's empty. -- We add a Cabal>=3.11 constraint before solving when multi-repl is @@ -783,7 +791,7 @@ filterConfigureFlags' flags cabalLibVersion -- Cabal < 1.23 doesn't know about '--profiling-detail'. -- Cabal < 1.23 has a hacked up version of 'enable-profiling' -- which we shouldn't use. - (tryLibProfiling, tryExeProfiling) = computeEffectiveProfiling flags + (tryLibProfiling, _tryLibProfilingShared, tryExeProfiling) = computeEffectiveProfiling flags flags_1_23_0 = flags_1_25_0 { configProfDetail = NoFlag diff --git a/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs b/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs index 946e0bf48fd..2c4de05a9a2 100644 --- a/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs @@ -683,6 +683,7 @@ instance Arbitrary PackageConfig where <*> arbitrary <*> arbitrary <*> arbitrary + <*> arbitrary <*> shortListOf 5 arbitraryShortToken <*> arbitrary <*> arbitrary @@ -751,6 +752,7 @@ instance Arbitrary PackageConfig where , packageConfigFullyStaticExe = x50 , packageConfigProf = x07 , packageConfigProfLib = x08 + , packageConfigProfShared = x08_1 , packageConfigProfExe = x09 , packageConfigProfDetail = x10 , packageConfigProfLibDetail = x11 @@ -814,6 +816,7 @@ instance Arbitrary PackageConfig where , packageConfigFullyStaticExe = x50' , packageConfigProf = x07' , packageConfigProfLib = x08' + , packageConfigProfShared = x08_1' , packageConfigProfExe = x09' , packageConfigProfDetail = x10' , packageConfigProfLibDetail = x11' @@ -866,7 +869,7 @@ instance Arbitrary PackageConfig where , packageConfigBenchmarkOptions = x52' } | ( ( (x00', x01', x02', x03', x04') - , (x05', x42', x06', x50', x07', x08', x09') + , (x05', x42', x06', x50', x07', x08', x08_1', x09') , (x10', x11', x12', x13', x14') , (x15', x16', x53', x17', x18', x19') ) @@ -883,7 +886,7 @@ instance Arbitrary PackageConfig where shrink ( ( (preShrink_Paths x00, preShrink_Args x01, x02, x03, x04) - , (x05, x42, x06, x50, x07, x08, x09) + , (x05, x42, x06, x50, x07, x08, x08_1, x09) , (x10, x11, map NonEmpty x12, x13, x14) , ( x15 diff --git a/cabal-testsuite/PackageTests/ProfShared/Lib.hs b/cabal-testsuite/PackageTests/ProfShared/Lib.hs new file mode 100644 index 00000000000..516d174a825 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProfShared/Lib.hs @@ -0,0 +1,3 @@ +module Lib where + +lib = 10 diff --git a/cabal-testsuite/PackageTests/ProfShared/exe/Prof.hs b/cabal-testsuite/PackageTests/ProfShared/exe/Prof.hs new file mode 100644 index 00000000000..200915ffefa --- /dev/null +++ b/cabal-testsuite/PackageTests/ProfShared/exe/Prof.hs @@ -0,0 +1,5 @@ +module Main where + +import Lib + +main = print lib diff --git a/cabal-testsuite/PackageTests/ProfShared/profShared.cabal b/cabal-testsuite/PackageTests/ProfShared/profShared.cabal new file mode 100644 index 00000000000..ef348cfecc6 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProfShared/profShared.cabal @@ -0,0 +1,13 @@ +Cabal-Version: 3.8 +Name: prof-shared +Version: 0.1 +Build-Type: Simple + +library + exposed-modules: Lib + Build-Depends: base + +executable Prof + main-is: Prof.hs + hs-source-dirs: exe + build-depends: base, prof-shared diff --git a/cabal-testsuite/PackageTests/ProfShared/setup.test.hs b/cabal-testsuite/PackageTests/ProfShared/setup.test.hs new file mode 100644 index 00000000000..754ff7a290d --- /dev/null +++ b/cabal-testsuite/PackageTests/ProfShared/setup.test.hs @@ -0,0 +1,145 @@ +import Test.Cabal.Prelude +import Data.List +import Data.Bifunctor + +data BuildWay = StaticWay | DynWay | ProfWay | ProfDynWay + deriving (Eq, Ord, Show, Read, Enum) + +-- Test building with profiling shared support +main = do + setupTest $ recordMode DoNotRecord $ do + has_prof_shared <- hasProfiledSharedLibraries + has_shared <- hasSharedLibraries + -- Tests are not robust against missing dynamic libraries yet. Would + -- be better to fix this. + skipUnless "Missing shared libraries" has_shared + + let analyse_result expected r = do + + let ls = lines (resultOutput r) + + library_prefix = "Wanted build ways(True): " + executable_prefix = "Wanted build ways(False): " + + get_ways prefix = map (drop (length prefix)) (filter (prefix `isPrefixOf`) ls) + library_ways = read_ways (get_ways library_prefix) + executable_ways = read_ways (get_ways executable_prefix) + + read_ways raw_ways = + case raw_ways of + -- There should only be one + [x] -> (read :: String -> [BuildWay]) x + -- Unless there are none, when we don't built the executable for example + [] -> [] + xs -> error "Unexpected number of log lines" + + way = (library_ways, executable_ways) + + unless (bimap (nub . sort) (nub . sort) expected == bimap (nub . sort) (nub . sort) way) $ + assertFailure $ "Expected:" ++ show expected ++ "\n" ++ "Got:" ++ show way + + requireSuccess r + setupTest $ recordMode DoNotRecord $ do + + has_prof_shared <- hasProfiledSharedLibraries + has_shared <- hasSharedLibraries + + let v = [ StaticWay ] + dyn = [ DynWay | has_shared ] + p_dyn = if has_prof_shared then [ProfDynWay] else p + p = [ ProfWay ] + none = [] + + let run_test args expected = do + setup "configure" args + res <- setup' "build" [] + analyse_result expected res + setup "clean" [] + + + run_test [] + (v <> dyn, v) + + + run_test ["--disable-library-vanilla", "--enable-executable-dynamic"] + (dyn, dyn) + + run_test ["--enable-profiling-shared"] + (v <> dyn <> p_dyn, v) + + run_test ["--enable-profiling-shared", "--enable-executable-dynamic"] + (v <> dyn <> p_dyn, dyn) + + run_test ["--enable-executable-dynamic", "--disable-library-vanilla"] + (dyn, dyn) + + run_test ["--enable-profiling"] + (v <> dyn <> p, p) + + run_test ["--enable-executable-profiling"] + (v <> dyn <> p, p) + + run_test ["--enable-executable-profiling", "--enable-executable-dynamic"] + (v <> dyn <> p_dyn, p_dyn) + + run_test ["--enable-profiling", "--enable-executable-dynamic"] + (v <> dyn <> p_dyn, p_dyn) + + --v dyn p (p exe) + run_test ["--enable-library-profiling", "--enable-executable-profiling"] + (v <> dyn <> p, p) + + run_test ["prof-shared", "--enable-profiling-shared", "--disable-library-vanilla", "--disable-shared"] + (p_dyn, none) + + -- p p_dyn + run_test ["prof-shared", "--enable-profiling-shared", "--enable-library-profiling", "--disable-library-vanilla", "--disable-shared"] + (p <> p_dyn, []) + + -- v p p_dyn + run_test ["prof-shared","--enable-profiling-shared", "--enable-library-profiling", "--enable-library-vanilla", "--disable-shared"] + (v <> p <> p_dyn, none) + + -- v dyn p p_dyn + run_test ["prof-shared", "--enable-profiling-shared", "--enable-library-profiling", "--enable-library-vanilla", "--enable-shared"] + (v <> dyn <> p <> p_dyn, none) + + let run_cabal_test args expected = cabalTest $ recordMode DoNotRecord $ do + has_prof_shared <- hasProfiledSharedLibraries + has_shared <- hasSharedLibraries + -- See GHC commit e400b9babdcf11669f963aeec20078fe7ccfca0d + -- Only installing profiled library is broken on very old ghc-pkg versions + broken_ghc_pkg <- isGhcVersion "<= 8.6.5" + + let cvt_l StaticWay = [ StaticWay ] + cvt_l DynWay = [ DynWay | has_shared ] + cvt_l ProfDynWay = [ProfDynWay | has_prof_shared ] + cvt_l ProfWay = [ ProfWay ] + + let cvt_e StaticWay = StaticWay + cvt_e DynWay = if has_shared then DynWay else error "DynWay" + cvt_e ProfDynWay = if has_prof_shared then ProfDynWay else ProfWay + cvt_e ProfWay = ProfWay + + unless (broken_ghc_pkg && (fst expected == [ProfWay])) $ do + res <- cabal' "v2-build" args + void $ analyse_result (bimap (concatMap cvt_l) (map cvt_e) expected) res + + run_cabal_test ["--disable-shared"] ([StaticWay], [StaticWay]) + run_cabal_test ["--disable-shared", "--disable-executable-dynamic"] ([StaticWay], [StaticWay]) + run_cabal_test ["--enable-shared"] ([DynWay, StaticWay], [StaticWay]) + run_cabal_test ["--enable-executable-dynamic"] ([DynWay, StaticWay], [DynWay]) + run_cabal_test ["--enable-shared", "--disable-library-vanilla", "--enable-executable-dynamic"] ([DynWay], [DynWay]) + + run_cabal_test ["--disable-shared", "--disable-library-vanilla", "--enable-profiling"] ([ProfWay], [ProfWay]) + + run_cabal_test ["--disable-shared", "--enable-profiling"] ([ProfWay, StaticWay], [ProfWay]) + + run_cabal_test ["--disable-shared", "--enable-profiling-shared", "--enable-profiling"] ([ProfDynWay, ProfWay, StaticWay], [ProfWay]) + + run_cabal_test ["--disable-shared", "--enable-profiling", "--enable-profiling-shared", "--enable-executable-dynamic"] ([ProfWay, ProfDynWay, StaticWay], [ProfDynWay]) + + run_cabal_test ["--enable-profiling", "--enable-executable-dynamic"] ([ProfDynWay, ProfWay, DynWay, StaticWay], [ProfDynWay]) + + run_cabal_test ["prof-shared", "--disable-library-profiling", "--enable-profiling", "--enable-executable-dynamic"] ([ProfDynWay, DynWay, StaticWay], []) + diff --git a/cabal-testsuite/PackageTests/ProfSharedWarning/Lib.hs b/cabal-testsuite/PackageTests/ProfSharedWarning/Lib.hs new file mode 100644 index 00000000000..516d174a825 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProfSharedWarning/Lib.hs @@ -0,0 +1,3 @@ +module Lib where + +lib = 10 diff --git a/cabal-testsuite/PackageTests/ProfSharedWarning/cabal.project b/cabal-testsuite/PackageTests/ProfSharedWarning/cabal.project new file mode 100644 index 00000000000..e6fdbadb439 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProfSharedWarning/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/cabal-testsuite/PackageTests/ProfSharedWarning/exe/Prof.hs b/cabal-testsuite/PackageTests/ProfSharedWarning/exe/Prof.hs new file mode 100644 index 00000000000..200915ffefa --- /dev/null +++ b/cabal-testsuite/PackageTests/ProfSharedWarning/exe/Prof.hs @@ -0,0 +1,5 @@ +module Main where + +import Lib + +main = print lib diff --git a/cabal-testsuite/PackageTests/ProfSharedWarning/profShared.cabal b/cabal-testsuite/PackageTests/ProfSharedWarning/profShared.cabal new file mode 100644 index 00000000000..ef348cfecc6 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProfSharedWarning/profShared.cabal @@ -0,0 +1,13 @@ +Cabal-Version: 3.8 +Name: prof-shared +Version: 0.1 +Build-Type: Simple + +library + exposed-modules: Lib + Build-Depends: base + +executable Prof + main-is: Prof.hs + hs-source-dirs: exe + build-depends: base, prof-shared diff --git a/cabal-testsuite/PackageTests/ProfSharedWarning/setup.out b/cabal-testsuite/PackageTests/ProfSharedWarning/setup.out new file mode 100644 index 00000000000..66512712837 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProfSharedWarning/setup.out @@ -0,0 +1,3 @@ +# Setup configure +Configuring prof-shared-0.1... +Warning: Executables will use dynamic linking, but a shared library is not being built. Linking will fail if any executables depend on the library. diff --git a/cabal-testsuite/PackageTests/ProfSharedWarning/setup_prof.out b/cabal-testsuite/PackageTests/ProfSharedWarning/setup_prof.out new file mode 100644 index 00000000000..ad201b3b391 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProfSharedWarning/setup_prof.out @@ -0,0 +1,4 @@ +# Setup configure +Configuring prof-shared-0.1... +Warning: The flag --enable-executable-profiling is deprecated. Please use --enable-profiling instead. +Warning: Executables will use profiled dynamic linking, but a profiled shared library is not being built. Linking will fail if any executables depend on the library. diff --git a/cabal-testsuite/src/Test/Cabal/Prelude.hs b/cabal-testsuite/src/Test/Cabal/Prelude.hs index b72e427c91b..d110bd9f433 100644 --- a/cabal-testsuite/src/Test/Cabal/Prelude.hs +++ b/cabal-testsuite/src/Test/Cabal/Prelude.hs @@ -834,22 +834,22 @@ getScriptCacheDirectory script = do ------------------------------------------------------------------------ -- * Skipping tests -hasSharedLibraries :: TestM Bool -hasSharedLibraries = do - shared_libs_were_removed <- isGhcVersion ">= 7.8" - return (not (buildOS == Windows && shared_libs_were_removed)) - -hasProfiledLibraries :: TestM Bool -hasProfiledLibraries = do +testCompilerWithArgs :: [String] -> TestM Bool +testCompilerWithArgs args = do env <- getTestEnv ghc_path <- programPathM ghcProgram let prof_test_hs = testWorkDir env "Prof.hs" liftIO $ writeFile prof_test_hs "module Prof where" r <- liftIO $ run (testVerbosity env) (Just $ testCurrentDir env) - (testEnvironment env) ghc_path ["-prof", "-c", prof_test_hs] + (testEnvironment env) ghc_path (["-c", prof_test_hs] ++ args) Nothing return (resultExitCode r == ExitSuccess) +hasProfiledLibraries, hasProfiledSharedLibraries, hasSharedLibraries :: TestM Bool +hasProfiledLibraries = testCompilerWithArgs ["-prof"] +hasProfiledSharedLibraries = testCompilerWithArgs ["-prof", "-dynamic"] +hasSharedLibraries = testCompilerWithArgs ["-dynamic"] + -- | Check if the GHC that is used for compiling package tests has -- a shared library of the cabal library under test in its database. -- diff --git a/changelog.d/issue-4816 b/changelog.d/issue-4816 new file mode 100644 index 00000000000..e0ac7700b7e --- /dev/null +++ b/changelog.d/issue-4816 @@ -0,0 +1,23 @@ +synopsis: Add support for building profiled dynamic way +packages: Cabal Cabal-syntax cabal-install +prs: #9900 +issues: #4816 + +description: { +Add support for profiled dynamic way + +New options for cabal.project and ./Setup interface: + +* `profiling-shared`: Enable building profiling dynamic way +* Passing `--enable-profiling` and `--enable-executable-dynamic` builds + profiled dynamic executables. + +Support for using `profiling-shared` is guarded behind a constraint +which ensures you are using `Cabal >= 3.13`. + +In the cabal file: + +* `ghc-prof-shared-options`, for passing options when building in + profiling dynamic way + +} diff --git a/changelog.d/issue-4816-2 b/changelog.d/issue-4816-2 new file mode 100644 index 00000000000..96307c3f83e --- /dev/null +++ b/changelog.d/issue-4816-2 @@ -0,0 +1,26 @@ +synopsis: Fix interaction of `--*-shared` and `--*-executable-dynamic` options. +packages: cabal-install +prs: #9900 +issues: #10050 + +description: { + +If you explicitly request `--disable-shared` it should disable the building of +a shared library and override any automatic ways this option is turned on. + +Passing `--enable-executable-dynamic` turns on `--enable-shared` if the option is +not specified explicitly. + +Before this patch, writing `--disable-shared` on its own would not disable the building of shared libraries. Writing `--disable-shared` and `--disable-executable-dynamic` would disable shared library +creation (despite `--disable-executable-dynamic` being the default). + +Now: + +* If you specify `--enable-shared` then shared objects are built. +* If you specify `--disabled-shared` then shared objects are not built. +* If you don't explicitly specify whether you want to build shared libraries then + * `--enable-executable-dynamic` will automatically turn on building shared libraries + * `--enable-executable-dynamic --enable-profiling` will automatically turn on building + shared profiling libraries (if supported by your compiler). + +} diff --git a/doc/buildinfo-fields-reference.rst b/doc/buildinfo-fields-reference.rst index c1ccf418f81..cfabe5ee448 100644 --- a/doc/buildinfo-fields-reference.rst +++ b/doc/buildinfo-fields-reference.rst @@ -387,6 +387,14 @@ ghc-prof-options .. math:: {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet} +ghc-prof-shared-options + * Monoidal field + * Available since ``cabal-version: 3.14``. + * Documentation of :pkg-field:`library:ghc-prof-shared-options` + + .. math:: + {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet} + ghc-shared-options * Monoidal field * Documentation of :pkg-field:`library:ghc-shared-options` @@ -408,6 +416,14 @@ ghcjs-prof-options .. math:: {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet} +ghcjs-prof-shared-options + * Monoidal field + * Available since ``cabal-version: 3.14``. + * Documentation of :pkg-field:`library:ghcjs-prof-shared-options` + + .. math:: + {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet} + ghcjs-shared-options * Monoidal field * Documentation of :pkg-field:`library:ghcjs-shared-options` diff --git a/doc/cabal-package-description-file.rst b/doc/cabal-package-description-file.rst index 450ddc0c0d3..d560b69e05d 100644 --- a/doc/cabal-package-description-file.rst +++ b/doc/cabal-package-description-file.rst @@ -1930,6 +1930,13 @@ system-dependent values for these fields. ones specified via :pkg-field:`ghc-options`, and are passed to GHC during both the compile and link phases. +.. pkg-field:: ghc-prof-shared-options: token list + + Additional options for GHC when the package is built as shared profiling + library. The options specified via this field are combined with the + ones specified via :pkg-field:`ghc-options`, and are passed to GHC during + both the compile and link phases. + .. pkg-field:: ghcjs-options: token list Like :pkg-field:`ghc-options` but applies to GHCJS @@ -1942,6 +1949,10 @@ system-dependent values for these fields. Like :pkg-field:`ghc-shared-options` but applies to GHCJS +.. pkg-field:: ghcjs-prof-shared-options: token list + + Like :pkg-field:`ghc-prof-shared-options` but applies to GHCJS + .. pkg-field:: includes: filename list A list of header files to be included in any compilations via C. diff --git a/doc/setup-commands.rst b/doc/setup-commands.rst index 20bdafabfae..5ed8077f46b 100644 --- a/doc/setup-commands.rst +++ b/doc/setup-commands.rst @@ -795,10 +795,21 @@ Miscellaneous options Build shared library. This implies a separate compiler run to generate position independent code as required on most platforms. + ``--enable-shared`` is enabled automatically if GHC is dynamically linked or + you request to build dynamic executables. + .. option:: --disable-shared (default) Do not build shared library. +.. option:: --enable-profiling-shared + + Build a profiling shared library. + +.. option:: --disable-profiling-shared + + (default) Do not built a profiling shared library. + .. option:: --enable-static Build a static library. This passes ``-staticlib`` to GHC (available