Skip to content

Commit 7581b4c

Browse files
committed
Makes flags overridable on the command line.
This is to fix issue #4452.
1 parent 76183b4 commit 7581b4c

File tree

4 files changed

+56
-24
lines changed

4 files changed

+56
-24
lines changed

Cabal/Distribution/PackageDescription.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ module Distribution.PackageDescription (
9999
nullFlagAssignment, showFlagValue,
100100
diffFlagAssignment, lookupFlagAssignment, insertFlagAssignment,
101101
dispFlagAssignment, parseFlagAssignment, parsecFlagAssignment,
102+
findDuplicateFlagAssignments,
102103
CondTree(..), ConfVar(..), Condition(..),
103104
cNot, cAnd, cOr,
104105

Cabal/Distribution/Types/GenericPackageDescription.hs

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module Distribution.Types.GenericPackageDescription (
1616
lookupFlagAssignment,
1717
insertFlagAssignment,
1818
diffFlagAssignment,
19+
findDuplicateFlagAssignments,
1920
nullFlagAssignment,
2021
showFlagValue,
2122
dispFlagAssignment,
@@ -25,11 +26,11 @@ module Distribution.Types.GenericPackageDescription (
2526
) where
2627

2728
import Prelude ()
28-
import Data.List ((\\))
2929
import Distribution.Compat.Prelude
3030
import Distribution.Utils.ShortText
3131
import Distribution.Utils.Generic (lowercase)
3232
import qualified Text.PrettyPrint as Disp
33+
import qualified Data.Map as Map
3334
import qualified Distribution.Compat.ReadP as Parse
3435
import qualified Distribution.Compat.Parsec as P
3536
import Distribution.Compat.ReadP ((+++))
@@ -154,55 +155,80 @@ instance Text FlagName where
154155
-- discovered during configuration. For example @--flags=foo --flags=-bar@
155156
-- becomes @[("foo", True), ("bar", False)]@
156157
--
157-
newtype FlagAssignment = FlagAssignment [(FlagName, Bool)]
158-
deriving (Binary,Eq,Ord,Semigroup,Monoid)
158+
newtype FlagAssignment = FlagAssignment { getFlagAssignment :: Map.Map FlagName (Int, Bool) }
159+
deriving (Binary)
159160

160-
-- TODO: the Semigroup/Monoid/Ord/Eq instances would benefit from
161-
-- [(FlagName,Bool)] being in a normal form, i.e. sorted. We could
162-
-- e.g. switch to a `Data.Map.Map` representation, but see duplicates
163-
-- check in `configuredPackageProblems`.
161+
instance Eq FlagAssignment where
162+
(==) (FlagAssignment m1) (FlagAssignment m2) = fmap snd m1 == fmap snd m2
163+
164+
instance Ord FlagAssignment where
165+
compare (FlagAssignment m1) (FlagAssignment m2) = fmap snd m1 `compare` fmap snd m2
166+
167+
-- | Combines pairs of values contained in the 'FlagAssignment' Map.
168+
--
169+
-- The last flag specified takes precedence, and we record the number
170+
-- of times we have seen the flag.
164171
--
165-
-- Also, the 'Semigroup' instance currently is left-biased as entries
166-
-- in the left-hand 'FlagAssignment' shadow those occuring in the
167-
-- right-hand side 'FlagAssignment' for the same flagnames.
172+
combineFlagValues :: (Int, Bool) -> (Int, Bool) -> (Int, Bool)
173+
combineFlagValues (c1, _) (c2, b2) = (c1 + c2, b2)
174+
175+
-- The 'Semigroup' instance currently is right-biased.
176+
--
177+
-- If duplicate flags are specified, we want the last flag specified to
178+
-- take precedence and we want to know how many times the flag has been
179+
-- specified so that we have the option of warning the user about
180+
-- supplying duplicate flags.
181+
instance Semigroup FlagAssignment where
182+
(<>) (FlagAssignment m1) (FlagAssignment m2) = FlagAssignment (Map.unionWith combineFlagValues m1 m2)
183+
184+
instance Monoid FlagAssignment where
185+
mempty = FlagAssignment Map.empty
186+
mappend = (<>)
168187

169188
-- | Construct a 'FlagAssignment' from a list of flag/value pairs.
170189
--
190+
-- If duplicate flags occur in the input list, the later entries
191+
-- in the list will take precedence.
192+
--
171193
-- @since 2.2.0
172194
mkFlagAssignment :: [(FlagName, Bool)] -> FlagAssignment
173-
mkFlagAssignment = FlagAssignment
195+
mkFlagAssignment = FlagAssignment . Map.fromListWith (flip combineFlagValues) . fmap (fmap (\b -> (1, b)))
174196

175197
-- | Deconstruct a 'FlagAssignment' into a list of flag/value pairs.
176198
--
177-
-- @ ('mkFlagAssignment' . 'unFlagAssignment') fa == fa @
199+
-- @ 'null' ('findDuplicateFlagAssignments' fa) ==> ('mkFlagAssignment' . 'unFlagAssignment') fa == fa @
178200
--
179201
-- @since 2.2.0
180202
unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
181-
unFlagAssignment (FlagAssignment xs) = xs
203+
unFlagAssignment = fmap (fmap snd) . Map.toList . getFlagAssignment
182204

183205
-- | Test whether 'FlagAssignment' is empty.
184206
--
185207
-- @since 2.2.0
186208
nullFlagAssignment :: FlagAssignment -> Bool
187-
nullFlagAssignment (FlagAssignment []) = True
188-
nullFlagAssignment _ = False
209+
nullFlagAssignment = Map.null . getFlagAssignment
189210

190211
-- | Lookup the value for a flag
191212
--
192213
-- Returns 'Nothing' if the flag isn't contained in the 'FlagAssignment'.
193214
--
194215
-- @since 2.2.0
195216
lookupFlagAssignment :: FlagName -> FlagAssignment -> Maybe Bool
196-
lookupFlagAssignment fn = lookup fn . unFlagAssignment
217+
lookupFlagAssignment fn = fmap snd . Map.lookup fn . getFlagAssignment
197218

198219
-- | Insert or update the boolean value of a flag.
199220
--
221+
-- If the flag is already present in the 'FlagAssigment', the
222+
-- value will be updated and the fact that multiple values have
223+
-- been provided for that flag will be recorded so that a
224+
-- warning can be generated later on.
225+
--
200226
-- @since 2.2.0
201227
insertFlagAssignment :: FlagName -> Bool -> FlagAssignment -> FlagAssignment
202228
-- TODO: this currently just shadows prior values for an existing flag;
203229
-- rather than enforcing uniqueness at construction, it's verified lateron via
204230
-- `D.C.Dependency.configuredPackageProblems`
205-
insertFlagAssignment flag val = mkFlagAssignment . ((flag,val):) . unFlagAssignment
231+
insertFlagAssignment flag val = FlagAssignment . Map.insertWith (flip combineFlagValues) flag (1, val) . getFlagAssignment
206232

207233
-- | Remove all flag-assignments from the first 'FlagAssignment' that
208234
-- are contained in the second 'FlagAssignment'
@@ -214,7 +240,13 @@ insertFlagAssignment flag val = mkFlagAssignment . ((flag,val):) . unFlagAssignm
214240
--
215241
-- @since 2.2.0
216242
diffFlagAssignment :: FlagAssignment -> FlagAssignment -> FlagAssignment
217-
diffFlagAssignment fa1 fa2 = mkFlagAssignment (unFlagAssignment fa1 \\ unFlagAssignment fa2)
243+
diffFlagAssignment fa1 fa2 = FlagAssignment (Map.difference (getFlagAssignment fa1) (getFlagAssignment fa2))
244+
245+
-- | Find the 'FlagName's that have been listed more than once.
246+
--
247+
-- @since 2.2.0
248+
findDuplicateFlagAssignments :: FlagAssignment -> [FlagName]
249+
findDuplicateFlagAssignments = Map.keys . Map.filter ((> 1) . fst) . getFlagAssignment
218250

219251
-- | @since 2.2.0
220252
instance Read FlagAssignment where
@@ -235,7 +267,7 @@ dispFlagAssignment = Disp.hsep . map (Disp.text . showFlagValue) . unFlagAssignm
235267

236268
-- | Parses a flag assignment.
237269
parsecFlagAssignment :: ParsecParser FlagAssignment
238-
parsecFlagAssignment = FlagAssignment <$> P.sepBy (onFlag <|> offFlag) P.skipSpaces1
270+
parsecFlagAssignment = mkFlagAssignment <$> P.sepBy (onFlag <|> offFlag) P.skipSpaces1
239271
where
240272
onFlag = do
241273
P.optional (P.char '+')
@@ -248,7 +280,7 @@ parsecFlagAssignment = FlagAssignment <$> P.sepBy (onFlag <|> offFlag) P.skipSpa
248280

249281
-- | Parses a flag assignment.
250282
parseFlagAssignment :: Parse.ReadP r FlagAssignment
251-
parseFlagAssignment = FlagAssignment <$> Parse.sepBy parseFlagValue Parse.skipSpaces1
283+
parseFlagAssignment = mkFlagAssignment <$> Parse.sepBy parseFlagValue Parse.skipSpaces1
252284
where
253285
parseFlagValue =
254286
(do Parse.optional (Parse.char '+')

cabal-install/Distribution/Client/Dependency.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ import Distribution.Compiler
9696
import Distribution.System
9797
( Platform )
9898
import Distribution.Client.Utils
99-
( duplicates, duplicatesBy, mergeBy, MergeResult(..) )
99+
( duplicatesBy, mergeBy, MergeResult(..) )
100100
import Distribution.Simple.Utils
101101
( comparing )
102102
import Distribution.Simple.Setup
@@ -891,8 +891,7 @@ configuredPackageProblems :: Platform -> CompilerInfo
891891
-> SolverPackage UnresolvedPkgLoc -> [PackageProblem]
892892
configuredPackageProblems platform cinfo
893893
(SolverPackage pkg specifiedFlags stanzas specifiedDeps' _specifiedExeDeps') =
894-
-- FIXME/TODO: FlagAssignment ought to be duplicate-free as internal invariant
895-
[ DuplicateFlag flag | ((flag,_):_) <- duplicates (PD.unFlagAssignment specifiedFlags) ]
894+
[ DuplicateFlag flag | flag <- PD.findDuplicateFlagAssignments specifiedFlags ]
896895
++ [ MissingFlag flag | OnlyInLeft flag <- mergedFlags ]
897896
++ [ ExtraFlag flag | OnlyInRight flag <- mergedFlags ]
898897
++ [ DuplicateDeps pkgs

cabal-testsuite/PackageTests/Regression/T3436/sandbox.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ Installing library in <PATH>
1818
Installed Cabal-2.0
1919
Failed to install custom-setup-1.0
2020
cabal: Error: some packages failed to install:
21-
custom-setup-1.0-92JpsxIMpiQHysxYdDtEVq failed during the configure step. The exception was:
21+
custom-setup-1.0-KL06TzJxSBkDtcPp9Xd2v1 failed during the configure step. The exception was:
2222
ExitFailure 1

0 commit comments

Comments
 (0)