From 9523d4875b75628ca016b490561a6b2469098011 Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Thu, 8 Feb 2018 02:32:44 +0000 Subject: [PATCH 1/6] Travis: work around #5120 by moving to cabal-install-head. --- .travis.yml | 2 +- travis-install.sh | 2 +- travis/binaries/.travis.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index ba88eeb6da6..5a673ccd68b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -104,7 +104,7 @@ before_install: - export PATH=$HOME/bin:$PATH - export PATH=$HOME/.cabal/bin:$PATH - export PATH=$HOME/.local/bin:$PATH - - export PATH=/opt/cabal/2.0/bin:$PATH + - export PATH=/opt/cabal/head/bin:$PATH - export PATH=/opt/happy/1.19.5/bin:$PATH - export PATH=/opt/alex/3.1.7/bin:$PATH - if [ "$USE_GOLD" = "YES" ]; then sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.gold" 20; fi diff --git a/travis-install.sh b/travis-install.sh index fc07567bac6..76bb05c8de4 100755 --- a/travis-install.sh +++ b/travis-install.sh @@ -13,7 +13,7 @@ if [ -z ${STACK_CONFIG+x} ]; then if [ "$TRAVIS_OS_NAME" = "linux" ]; then travis_retry sudo add-apt-repository -y ppa:hvr/ghc travis_retry sudo apt-get update - travis_retry sudo apt-get install --force-yes cabal-install-head cabal-install-2.0 happy-1.19.5 alex-3.1.7 ghc-$GHCVER-prof ghc-$GHCVER-dyn + travis_retry sudo apt-get install --force-yes cabal-install-head cabal-install-head happy-1.19.5 alex-3.1.7 ghc-$GHCVER-prof ghc-$GHCVER-dyn if [ "x$TEST_OTHER_VERSIONS" = "xYES" ]; then travis_retry sudo apt-get install --force-yes ghc-7.0.4-prof ghc-7.0.4-dyn ghc-7.2.2-prof ghc-7.2.2-dyn ghc-head-prof ghc-head-dyn; fi elif [ "$TRAVIS_OS_NAME" = "osx" ]; then diff --git a/travis/binaries/.travis.yml b/travis/binaries/.travis.yml index c63206f6947..588102c4af1 100644 --- a/travis/binaries/.travis.yml +++ b/travis/binaries/.travis.yml @@ -12,7 +12,7 @@ before_install: - export PATH=$HOME/bin:$PATH - export PATH=$HOME/.cabal/bin:$PATH - export PATH=$HOME/.local/bin:$PATH - - export PATH=/opt/cabal/2.0/bin:$PATH + - export PATH=/opt/cabal/head/bin:$PATH - export PATH=/opt/happy/1.19.5/bin:$PATH - export PATH=/opt/alex/3.1.7/bin:$PATH - ./travis-install.sh From 4443f71cac7963fd36a45545b42296223aa8e7c5 Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Thu, 8 Feb 2018 02:04:13 +0000 Subject: [PATCH 2/6] Use cabal-instal 2.0.0.1 on AppVeyor and macOS Travis. --- appveyor.yml | 2 +- travis-install.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 8260ef14c85..45d98ab45b4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ install: - set PATH=%APPDATA%\cabal\bin;C:\Program Files\Git\mingw64\bin;%PATH% # TODO: remove --insecure, this is to workaround haskell.org # failing to send intermediate cert; see https://github.com/haskell/cabal/pull/4172 - - curl -o cabal.zip --insecure --progress-bar https://www.haskell.org/cabal/release/cabal-install-2.0.0.0/cabal-install-2.0.0.0-x86_64-unknown-mingw32.zip + - curl -o cabal.zip --insecure --progress-bar https://www.haskell.org/cabal/release/cabal-install-2.0.0.1/cabal-install-2.0.0.1-x86_64-unknown-mingw32.zip - 7z x -bd cabal.zip - cabal --version - cabal update diff --git a/travis-install.sh b/travis-install.sh index 76bb05c8de4..74520f77b1c 100755 --- a/travis-install.sh +++ b/travis-install.sh @@ -60,7 +60,7 @@ if [ -z ${STACK_CONFIG+x} ]; then cd ..; mkdir "${HOME}/bin" - travis_retry curl -L https://www.haskell.org/cabal/release/cabal-install-2.0.0.0/cabal-install-2.0.0.0-x86_64-apple-darwin-sierra.tar.xz | tar xJO > "${HOME}/bin/cabal" + travis_retry curl -L https://www.haskell.org/cabal/release/cabal-install-2.0.0.1/cabal-install-2.0.0.1-x86_64-apple-darwin-sierra.tar.xz | tar xJO > "${HOME}/bin/cabal" chmod a+x "${HOME}/bin/cabal" "${HOME}/bin/cabal" --version From 3e87beab06310116da6d96596a35756df98cac23 Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Thu, 8 Feb 2018 09:20:48 +0000 Subject: [PATCH 3/6] Revert "Merge pull request #5012 from grayjay/issue-4823" This reverts commit 11d8a777466de7ceee0a49a0a5b9b764bf05df98, reversing changes made to 94a7374d7b1a9b55454209e92d5057ba81be7d6a. That change was causing failures on AppVeyor, see https://github.com/haskell/cabal/pull/5012#issuecomment-364060817 --- .../Distribution/Client/Dependency.hs | 4 +- cabal-install/Distribution/Solver/Modular.hs | 125 ++---------------- .../Distribution/Solver/Modular/Log.hs | 53 +++++--- .../Distribution/Solver/Modular/Message.hs | 106 ++++++++------- .../Distribution/Solver/Modular/Preference.hs | 12 -- .../Distribution/Solver/Modular/Solver.hs | 51 +++---- .../Distribution/Solver/Modular/Tree.hs | 1 - .../Solver/Modular/WeightedPSQ.hs | 11 -- .../Distribution/Solver/Types/Variable.hs | 3 +- .../Solver/Modular/DSL/TestCaseUtils.hs | 8 +- .../Distribution/Solver/Modular/Solver.hs | 58 ++------ .../Includes2/setup-external.cabal.out | 8 +- .../use-local-version-of-package.out | 6 +- .../use-local-package-as-setup-dep.out | 10 +- .../ConfigureComponent/Exe/setup.cabal.out | 6 +- .../BuildDependsBad/setup.cabal.out | 4 +- 16 files changed, 158 insertions(+), 308 deletions(-) diff --git a/cabal-install/Distribution/Client/Dependency.hs b/cabal-install/Distribution/Client/Dependency.hs index f13777ab0b5..69f48ba88ef 100644 --- a/cabal-install/Distribution/Client/Dependency.hs +++ b/cabal-install/Distribution/Client/Dependency.hs @@ -64,7 +64,7 @@ module Distribution.Client.Dependency ( ) where import Distribution.Solver.Modular - ( modularResolver, SolverConfig(..), PruneAfterFirstSuccess(..) ) + ( modularResolver, SolverConfig(..) ) import Distribution.Simple.PackageIndex (InstalledPackageIndex) import qualified Distribution.Simple.PackageIndex as InstalledPackageIndex import Distribution.Client.SolverInstallPlan (SolverInstallPlan) @@ -719,7 +719,7 @@ resolveDependencies platform comp pkgConfigDB solver params = $ runSolver solver (SolverConfig reordGoals cntConflicts indGoals noReinstalls shadowing strFlags allowBootLibs maxBkjumps enableBj - solveExes order verbosity (PruneAfterFirstSuccess False)) + solveExes order verbosity) platform comp installedPkgIndex sourcePkgIndex pkgConfigDB preferences constraints targets where diff --git a/cabal-install/Distribution/Solver/Modular.hs b/cabal-install/Distribution/Solver/Modular.hs index b7e2d98430a..21de9cb57dc 100644 --- a/cabal-install/Distribution/Solver/Modular.hs +++ b/cabal-install/Distribution/Solver/Modular.hs @@ -1,5 +1,5 @@ module Distribution.Solver.Modular - ( modularResolver, SolverConfig(..), PruneAfterFirstSuccess(..)) where + ( modularResolver, SolverConfig(..)) where -- Here, we try to map between the external cabal-install solver -- interface and the internal interface that the solver actually @@ -9,39 +9,25 @@ module Distribution.Solver.Modular -- and finally, we have to convert back the resulting install -- plan. -import Data.Map (Map) -import qualified Data.Map as M -import Data.Set (Set) -import Data.Ord +import Data.Map as M + ( fromListWith ) import Distribution.Compat.Graph ( IsNode(..) ) -import Distribution.Compiler - ( CompilerInfo ) import Distribution.Solver.Modular.Assignment - ( Assignment, toCPs ) + ( toCPs ) import Distribution.Solver.Modular.ConfiguredConversion ( convCP ) -import qualified Distribution.Solver.Modular.ConflictSet as CS -import Distribution.Solver.Modular.Dependency -import Distribution.Solver.Modular.Flag -import Distribution.Solver.Modular.Index import Distribution.Solver.Modular.IndexConversion ( convPIs ) import Distribution.Solver.Modular.Log - ( SolverFailure(..), logToProgress ) + ( logToProgress ) import Distribution.Solver.Modular.Package ( PN ) import Distribution.Solver.Modular.Solver - ( SolverConfig(..), PruneAfterFirstSuccess(..), solve ) -import Distribution.Solver.Types.DependencyResolver + ( SolverConfig(..), solve ) import Distribution.Solver.Types.LabeledPackageConstraint import Distribution.Solver.Types.PackageConstraint -import Distribution.Solver.Types.PackagePath -import Distribution.Solver.Types.PackagePreferences -import Distribution.Solver.Types.PkgConfigDb - ( PkgConfigDb ) -import Distribution.Solver.Types.Progress -import Distribution.Solver.Types.Variable +import Distribution.Solver.Types.DependencyResolver import Distribution.System ( Platform(..) ) import Distribution.Simple.Utils @@ -52,8 +38,9 @@ import Distribution.Simple.Utils -- solver. Performs the necessary translations before and after. modularResolver :: SolverConfig -> DependencyResolver loc modularResolver sc (Platform arch os) cinfo iidx sidx pkgConfigDB pprefs pcs pns = - fmap (uncurry postprocess) $ -- convert install plan - solve' sc cinfo idx pkgConfigDB pprefs gcs pns + fmap (uncurry postprocess) $ -- convert install plan + logToProgress (solverVerbosity sc) (maxBackjumps sc) $ -- convert log format into progress format + solve sc cinfo idx pkgConfigDB pprefs gcs pns where -- Indices have to be converted into solver-specific uniform index. idx = convPIs os arch cinfo (shadowPkgs sc) (strongFlags sc) (solveExecutables sc) iidx sidx @@ -71,95 +58,3 @@ modularResolver sc (Platform arch os) cinfo iidx sidx pkgConfigDB pprefs pcs pns -- Helper function to extract the PN from a constraint. pcName :: PackageConstraint -> PN pcName (PackageConstraint scope _) = scopeToPackageName scope - --- | Run 'D.S.Modular.Solver.solve' and then produce a summarized log to display --- in the error case. --- --- When there is no solution, we produce the error message by rerunning the --- solver but making it prefer the goals from the final conflict set from the --- first run. We also set the backjump limit to 0, so that the log stops at the --- first backjump and is relatively short. Preferring goals from the final --- conflict set increases the probability that the log to the first backjump --- contains package, flag, and stanza choices that are relevant to the final --- failure. The solver shouldn't need to choose any packages that aren't in the --- final conflict set. (For every variable in the final conflict set, the final --- conflict set should also contain the variable that introduced that variable. --- The solver can then follow that chain of variables in reverse order from the --- user target to the conflict.) However, it is possible that the conflict set --- contains unnecessary variables. --- --- Producing an error message when the solver reaches the backjump limit is more --- complicated. There is no final conflict set, so we create one for the minimal --- subtree containing the path that the solver took to the first backjump. This --- conflict set helps explain why the solver reached the backjump limit, because --- the first backjump contributes to reaching the backjump limit. Additionally, --- the solver is much more likely to be able to finish traversing this subtree --- before the backjump limit, since its size is linear (not exponential) in the --- number of goal choices. We create it by pruning all children after the first --- successful child under each node in the original tree, so that there is at --- most one valid choice at each level. Then we use the final conflict set from --- that run to generate an error message, as in the case where the solver found --- that there was no solution. --- --- Using the full log from a rerun of the solver ensures that the log is --- complete, i.e., it shows the whole chain of dependencies from the user --- targets to the conflicting packages. -solve' :: SolverConfig - -> CompilerInfo - -> Index - -> PkgConfigDb - -> (PN -> PackagePreferences) - -> Map PN [LabeledPackageConstraint] - -> Set PN - -> Progress String String (Assignment, RevDepMap) -solve' sc cinfo idx pkgConfigDB pprefs gcs pns = - foldProgress Step createErrorMsg Done (runSolver sc) - where - runSolver :: SolverConfig - -> Progress String SolverFailure (Assignment, RevDepMap) - runSolver sc' = - logToProgress (solverVerbosity sc') (maxBackjumps sc') $ -- convert log format into progress format - solve sc' cinfo idx pkgConfigDB pprefs gcs pns - - createErrorMsg :: SolverFailure - -> Progress String String (Assignment, RevDepMap) - createErrorMsg (NoSolution cs msg) = - Fail $ rerunSolverForErrorMsg cs msg - createErrorMsg (BackjumpLimitReached msg) = - Step ("Backjump limit reached. Rerunning dependency solver to generate " - ++ "a final conflict set for the search tree containing the " - ++ "first backjump.") $ - foldProgress Step f Done $ - runSolver sc { pruneAfterFirstSuccess = PruneAfterFirstSuccess True } - where - f :: SolverFailure -> Progress String String (Assignment, RevDepMap) - f (NoSolution cs _) = Fail $ rerunSolverForErrorMsg cs msg - f (BackjumpLimitReached _) = - -- This case is possible when the number of goals involved in - -- conflicts is greater than the backjump limit. - Fail $ msg ++ "Failed to generate a summarized dependency solver " - ++ "log due to low backjump limit." - - rerunSolverForErrorMsg :: ConflictSet -> String -> String - rerunSolverForErrorMsg cs finalMsg = - let sc' = sc { - goalOrder = Just (preferGoalsFromConflictSet cs) - , maxBackjumps = Just 0 - } - in unlines ("Could not resolve dependencies:" : messages (runSolver sc')) - ++ finalMsg - - messages :: Progress step fail done -> [step] - messages = foldProgress (:) (const []) (const []) - --- | Goal ordering that chooses goals contained in the conflict set before --- other goals. -preferGoalsFromConflictSet :: ConflictSet - -> Variable QPN -> Variable QPN -> Ordering -preferGoalsFromConflictSet cs = - comparing $ \v -> not $ CS.member (toVar v) cs - where - toVar :: Variable QPN -> Var QPN - toVar (PackageVar qpn) = P qpn - toVar (FlagVar qpn fn) = F (FN qpn fn) - toVar (StanzaVar qpn sn) = S (SN qpn sn) diff --git a/cabal-install/Distribution/Solver/Modular/Log.hs b/cabal-install/Distribution/Solver/Modular/Log.hs index 0490b9366e1..f80352e7406 100644 --- a/cabal-install/Distribution/Solver/Modular/Log.hs +++ b/cabal-install/Distribution/Solver/Modular/Log.hs @@ -1,12 +1,13 @@ module Distribution.Solver.Modular.Log ( Log , logToProgress - , SolverFailure(..) ) where import Prelude () import Distribution.Solver.Compat.Prelude +import Data.List as L + import Distribution.Solver.Types.Progress import Distribution.Solver.Modular.Dependency @@ -22,22 +23,20 @@ import Distribution.Verbosity -- Parameterized over the type of actual messages and the final result. type Log m a = Progress m (ConflictSet, ConflictMap) a -data Exhaustiveness = Exhaustive | BackjumpLimit +messages :: Progress step fail done -> [step] +messages = foldProgress (:) (const []) (const []) --- | Information about a dependency solver failure. It includes an error message --- and a final conflict set, if available. -data SolverFailure = - NoSolution ConflictSet String - | BackjumpLimitReached String +data Exhaustiveness = Exhaustive | BackjumpLimitReached -- | Postprocesses a log file. Takes as an argument a limit on allowed backjumps. -- If the limit is 'Nothing', then infinitely many backjumps are allowed. If the -- limit is 'Just 0', backtracking is completely disabled. -logToProgress :: Verbosity -> Maybe Int -> Log Message a -> Progress String SolverFailure a +logToProgress :: Verbosity -> Maybe Int -> Log Message a -> Progress String String a logToProgress verbosity mbj l = - let ms = proc mbj l - mapFailure f = foldProgress Step (Fail . f) Done - in mapFailure finalError (showMessages ms) -- run with backjump limit applied + let es = proc (Just 0) l -- catch first error (always) + ms = proc mbj l + in go es es -- trace for first error + (showMessages (const True) True ms) -- run with backjump limit applied where -- Proc takes the allowed number of backjumps and a 'Progress' and explores the -- messages until the maximum number of backjumps has been reached. It filters out @@ -49,15 +48,30 @@ logToProgress verbosity mbj l = proc _ (Fail (cs, cm)) = Fail (Exhaustive, cs, cm) proc mbj' (Step x@(Failure cs Backjump) xs@(Step Leave (Step (Failure cs' Backjump) _))) | cs == cs' = Step x (proc mbj' xs) -- repeated backjumps count as one - proc (Just 0) (Step (Failure cs Backjump) _) = Fail (BackjumpLimit, cs, mempty) -- No final conflict map available + proc (Just 0) (Step (Failure cs Backjump) _) = Fail (BackjumpLimitReached, cs, mempty) -- No final conflict map available proc (Just n) (Step x@(Failure _ Backjump) xs) = Step x (proc (Just (n - 1)) xs) proc mbj' (Step x xs) = Step x (proc mbj' xs) - finalError :: (Exhaustiveness, ConflictSet, ConflictMap) -> SolverFailure - finalError (exh, cs, cm) = + -- The first two arguments are both supposed to be the log up to the first error. + -- That's the error that will always be printed in case we do not find a solution. + -- We pass this log twice, because we evaluate it in parallel with the full log, + -- but we also want to retain the reference to its beginning for when we print it. + -- This trick prevents a space leak! + -- + -- The third argument is the full log, ending with either the solution or the + -- exhaustiveness and final conflict set. + go :: Progress Message (Exhaustiveness, ConflictSet, ConflictMap) b + -> Progress Message (Exhaustiveness, ConflictSet, ConflictMap) b + -> Progress String (Exhaustiveness, ConflictSet, ConflictMap) b + -> Progress String String b + go ms (Step _ ns) (Step x xs) = Step x (go ms ns xs) + go ms r (Step x xs) = Step x (go ms r xs) + go ms (Step _ ns) r = go ms ns r + go ms (Fail (_, cs', _)) (Fail (exh, cs, cm)) = Fail $ + "Could not resolve dependencies:\n" ++ + unlines (messages $ showMessages (L.foldr (\ v _ -> v `CS.member` cs') True) False ms) ++ case exh of Exhaustive -> - NoSolution cs $ "After searching the rest of the dependency tree exhaustively, " ++ "these were the goals I've had most trouble fulfilling: " ++ showCS cm cs @@ -65,9 +79,14 @@ logToProgress verbosity mbj l = showCS = if verbosity > normal then CS.showCSWithFrequency else CS.showCSSortedByFrequency - BackjumpLimit -> - BackjumpLimitReached $ + BackjumpLimitReached -> "Backjump limit reached (" ++ currlimit mbj ++ "change with --max-backjumps or try to run with --reorder-goals).\n" where currlimit (Just n) = "currently " ++ show n ++ ", " currlimit Nothing = "" + go _ _ (Done s) = Done s + go _ (Done _) (Fail _) = Fail $ + -- Should not happen: Second argument is the log up to first error, + -- third one is the entire log. Therefore it should never happen that + -- the second log finishes with 'Done' and the third log with 'Fail'. + "Could not resolve dependencies; something strange happened." diff --git a/cabal-install/Distribution/Solver/Modular/Message.hs b/cabal-install/Distribution/Solver/Modular/Message.hs index 5ead5dab254..99eecc843ee 100644 --- a/cabal-install/Distribution/Solver/Modular/Message.hs +++ b/cabal-install/Distribution/Solver/Modular/Message.hs @@ -33,46 +33,59 @@ data Message = -- | Transforms the structured message type to actual messages (strings). -- --- The log contains level numbers, which are useful for any trace that involves --- backtracking, because only the level numbers will allow to keep track of --- backjumps. -showMessages :: Progress Message a b -> Progress String a b -showMessages = go 0 +-- Takes an additional relevance predicate. The predicate gets a stack of goal +-- variables and can decide whether messages regarding these goals are relevant. +-- You can plug in 'const True' if you're interested in a full trace. If you +-- want a slice of the trace concerning a particular conflict set, then plug in +-- a predicate returning 'True' on the empty stack and if the head is in the +-- conflict set. +-- +-- The second argument indicates if the level numbers should be shown. This is +-- recommended for any trace that involves backtracking, because only the level +-- numbers will allow to keep track of backjumps. +showMessages :: ([Var QPN] -> Bool) -> Bool -> Progress Message a b -> Progress String a b +showMessages p sl = go [] 0 where - -- 'go' increments the level for a recursive call when it encounters - -- 'TryP', 'TryF', or 'TryS' and decrements the level when it encounters 'Leave'. - go :: Int -> Progress Message a b -> Progress String a b - go !_ (Done x) = Done x - go !_ (Fail x) = Fail x + -- The stack 'v' represents variables that are currently assigned by the + -- solver. 'go' pushes a variable for a recursive call when it encounters + -- 'TryP', 'TryF', or 'TryS' and pops a variable when it encounters 'Leave'. + -- When 'go' processes a package goal, or a package goal followed by a + -- 'Failure', it calls 'atLevel' with the goal variable at the head of the + -- stack so that the predicate can also select messages relating to package + -- goal choices. + go :: [Var QPN] -> Int -> Progress Message a b -> Progress String a b + go !_ !_ (Done x) = Done x + go !_ !_ (Fail x) = Fail x -- complex patterns - go !l (Step (TryP qpn i) (Step Enter (Step (Failure c fr) (Step Leave ms)))) = - goPReject l qpn [i] c fr ms - go !l (Step (TryF qfn b) (Step Enter (Step (Failure c fr) (Step Leave ms)))) = - (atLevel l $ "rejecting: " ++ showQFNBool qfn b ++ showFR c fr) (go l ms) - go !l (Step (TryS qsn b) (Step Enter (Step (Failure c fr) (Step Leave ms)))) = - (atLevel l $ "rejecting: " ++ showQSNBool qsn b ++ showFR c fr) (go l ms) - go !l (Step (Next (Goal (P _ ) gr)) (Step (TryP qpn' i) ms@(Step Enter (Step (Next _) _)))) = - (atLevel l $ "trying: " ++ showQPNPOpt qpn' i ++ showGR gr) (go l ms) - go !l (Step (Next (Goal (P qpn) gr)) ms@(Fail _)) = - (atLevel l $ "unknown package: " ++ showQPN qpn ++ showGR gr) $ go l ms + go !v !l (Step (TryP qpn i) (Step Enter (Step (Failure c fr) (Step Leave ms)))) = + goPReject v l qpn [i] c fr ms + go !v !l (Step (TryF qfn b) (Step Enter (Step (Failure c fr) (Step Leave ms)))) = + (atLevel (F qfn : v) l $ "rejecting: " ++ showQFNBool qfn b ++ showFR c fr) (go v l ms) + go !v !l (Step (TryS qsn b) (Step Enter (Step (Failure c fr) (Step Leave ms)))) = + (atLevel (S qsn : v) l $ "rejecting: " ++ showQSNBool qsn b ++ showFR c fr) (go v l ms) + go !v !l (Step (Next (Goal (P qpn) gr)) (Step (TryP qpn' i) ms@(Step Enter (Step (Next _) _)))) = + (atLevel (P qpn : v) l $ "trying: " ++ showQPNPOpt qpn' i ++ showGR gr) (go (P qpn : v) l ms) + go !v !l (Step (Next (Goal (P qpn) gr)) ms@(Fail _)) = + (atLevel (P qpn : v) l $ "unknown package: " ++ showQPN qpn ++ showGR gr) $ go v l ms -- the previous case potentially arises in the error output, because we remove the backjump itself -- if we cut the log after the first error - go !l (Step (Next (Goal (P qpn) gr)) ms@(Step (Failure _c Backjump) _)) = - (atLevel l $ "unknown package: " ++ showQPN qpn ++ showGR gr) $ go l ms - go !l (Step (Next (Goal (P qpn) gr)) (Step (Failure c fr) ms)) = - (atLevel l $ showPackageGoal qpn gr) $ (atLevel l $ showFailure c fr) (go l ms) - go !l (Step (Failure c Backjump) ms@(Step Leave (Step (Failure c' Backjump) _))) - | c == c' = go l ms + go !v !l (Step (Next (Goal (P qpn) gr)) ms@(Step (Failure _c Backjump) _)) = + (atLevel (P qpn : v) l $ "unknown package: " ++ showQPN qpn ++ showGR gr) $ go v l ms + go !v !l (Step (Next (Goal (P qpn) gr)) (Step (Failure c fr) ms)) = + let v' = P qpn : v + in (atLevel v' l $ showPackageGoal qpn gr) $ (atLevel v' l $ showFailure c fr) (go v l ms) + go !v !l (Step (Failure c Backjump) ms@(Step Leave (Step (Failure c' Backjump) _))) + | c == c' = go v l ms -- standard display - go !l (Step Enter ms) = go (l+1) ms - go !l (Step Leave ms) = go (l-1) ms - go !l (Step (TryP qpn i) ms) = (atLevel l $ "trying: " ++ showQPNPOpt qpn i) (go l ms) - go !l (Step (TryF qfn b) ms) = (atLevel l $ "trying: " ++ showQFNBool qfn b) (go l ms) - go !l (Step (TryS qsn b) ms) = (atLevel l $ "trying: " ++ showQSNBool qsn b) (go l ms) - go !l (Step (Next (Goal (P qpn) gr)) ms) = (atLevel l $ showPackageGoal qpn gr) (go l ms) - go !l (Step (Next _) ms) = go l ms -- ignore flag goals in the log - go !l (Step (Success) ms) = (atLevel l $ "done") (go l ms) - go !l (Step (Failure c fr) ms) = (atLevel l $ showFailure c fr) (go l ms) + go !v !l (Step Enter ms) = go v (l+1) ms + go !v !l (Step Leave ms) = go (drop 1 v) (l-1) ms + go !v !l (Step (TryP qpn i) ms) = (atLevel (P qpn : v) l $ "trying: " ++ showQPNPOpt qpn i) (go (P qpn : v) l ms) + go !v !l (Step (TryF qfn b) ms) = (atLevel (F qfn : v) l $ "trying: " ++ showQFNBool qfn b) (go (F qfn : v) l ms) + go !v !l (Step (TryS qsn b) ms) = (atLevel (S qsn : v) l $ "trying: " ++ showQSNBool qsn b) (go (S qsn : v) l ms) + go !v !l (Step (Next (Goal (P qpn) gr)) ms) = (atLevel (P qpn : v) l $ showPackageGoal qpn gr) (go v l ms) + go !v !l (Step (Next _) ms) = go v l ms -- ignore flag goals in the log + go !v !l (Step (Success) ms) = (atLevel v l $ "done") (go v l ms) + go !v !l (Step (Failure c fr) ms) = (atLevel v l $ showFailure c fr) (go v l ms) showPackageGoal :: QPN -> QGoalReason -> String showPackageGoal qpn gr = "next goal: " ++ showQPN qpn ++ showGR gr @@ -81,23 +94,26 @@ showMessages = go 0 showFailure c fr = "fail" ++ showFR c fr -- special handler for many subsequent package rejections - goPReject :: Int + goPReject :: [Var QPN] + -> Int -> QPN -> [POption] -> ConflictSet -> FailReason -> Progress Message a b -> Progress String a b - goPReject l qpn is c fr (Step (TryP qpn' i) (Step Enter (Step (Failure _ fr') (Step Leave ms)))) - | qpn == qpn' && fr == fr' = goPReject l qpn (i : is) c fr ms - goPReject l qpn is c fr ms = - (atLevel l $ "rejecting: " ++ L.intercalate ", " (map (showQPNPOpt qpn) (reverse is)) ++ showFR c fr) (go l ms) + goPReject v l qpn is c fr (Step (TryP qpn' i) (Step Enter (Step (Failure _ fr') (Step Leave ms)))) + | qpn == qpn' && fr == fr' = goPReject v l qpn (i : is) c fr ms + goPReject v l qpn is c fr ms = + (atLevel (P qpn : v) l $ "rejecting: " ++ L.intercalate ", " (map (showQPNPOpt qpn) (reverse is)) ++ showFR c fr) (go v l ms) - -- write a message with the current level number - atLevel :: Int -> String -> Progress String a b -> Progress String a b - atLevel l x xs = - let s = show l - in Step ("[" ++ replicate (3 - length s) '_' ++ s ++ "] " ++ x) xs + -- write a message, but only if it's relevant; we can also enable or disable the display of the current level + atLevel :: [Var QPN] -> Int -> String -> Progress String a b -> Progress String a b + atLevel v l x xs + | sl && p v = let s = show l + in Step ("[" ++ replicate (3 - length s) '_' ++ s ++ "] " ++ x) xs + | p v = Step x xs + | otherwise = xs showQPNPOpt :: QPN -> POption -> String showQPNPOpt qpn@(Q _pp pn) (POption i linkedTo) = diff --git a/cabal-install/Distribution/Solver/Modular/Preference.hs b/cabal-install/Distribution/Solver/Modular/Preference.hs index e7665ba528a..74816f51f09 100644 --- a/cabal-install/Distribution/Solver/Modular/Preference.hs +++ b/cabal-install/Distribution/Solver/Modular/Preference.hs @@ -14,7 +14,6 @@ module Distribution.Solver.Modular.Preference , preferReallyEasyGoalChoices , requireInstalled , sortGoals - , pruneAfterFirstSuccess ) where import Prelude () @@ -352,17 +351,6 @@ sortGoals variableOrder = trav go varToVariable (F (FN qpn fn)) = FlagVar qpn fn varToVariable (S (SN qpn stanza)) = StanzaVar qpn stanza --- | Reduce the branching degree of the search tree by removing all choices --- after the first successful choice at each level. The returned tree is the --- minimal subtree containing the path to the first backjump. -pruneAfterFirstSuccess :: Tree d c -> Tree d c -pruneAfterFirstSuccess = trav go - where - go (PChoiceF qpn rdm gr ts) = PChoiceF qpn rdm gr (W.takeUntil active ts) - go (FChoiceF qfn rdm gr w m d ts) = FChoiceF qfn rdm gr w m d (W.takeUntil active ts) - go (SChoiceF qsn rdm gr w ts) = SChoiceF qsn rdm gr w (W.takeUntil active ts) - go x = x - -- | Always choose the first goal in the list next, abandoning all -- other choices. -- diff --git a/cabal-install/Distribution/Solver/Modular/Solver.hs b/cabal-install/Distribution/Solver/Modular/Solver.hs index b2b717ca4f6..acfe4def487 100644 --- a/cabal-install/Distribution/Solver/Modular/Solver.hs +++ b/cabal-install/Distribution/Solver/Modular/Solver.hs @@ -6,7 +6,6 @@ module Distribution.Solver.Modular.Solver ( SolverConfig(..) , solve - , PruneAfterFirstSuccess(..) ) where import Data.Map as M @@ -54,25 +53,20 @@ import Debug.Trace.Tree.Assoc (Assoc(..)) -- | Various options for the modular solver. data SolverConfig = SolverConfig { - reorderGoals :: ReorderGoals, - countConflicts :: CountConflicts, - independentGoals :: IndependentGoals, - avoidReinstalls :: AvoidReinstalls, - shadowPkgs :: ShadowPkgs, - strongFlags :: StrongFlags, - allowBootLibInstalls :: AllowBootLibInstalls, - maxBackjumps :: Maybe Int, - enableBackjumping :: EnableBackjumping, - solveExecutables :: SolveExecutables, - goalOrder :: Maybe (Variable QPN -> Variable QPN -> Ordering), - solverVerbosity :: Verbosity, - pruneAfterFirstSuccess :: PruneAfterFirstSuccess + reorderGoals :: ReorderGoals, + countConflicts :: CountConflicts, + independentGoals :: IndependentGoals, + avoidReinstalls :: AvoidReinstalls, + shadowPkgs :: ShadowPkgs, + strongFlags :: StrongFlags, + allowBootLibInstalls :: AllowBootLibInstalls, + maxBackjumps :: Maybe Int, + enableBackjumping :: EnableBackjumping, + solveExecutables :: SolveExecutables, + goalOrder :: Maybe (Variable QPN -> Variable QPN -> Ordering), + solverVerbosity :: Verbosity } --- | Whether to remove all choices after the first successful choice at each --- level in the search tree. -newtype PruneAfterFirstSuccess = PruneAfterFirstSuccess Bool - -- | Run all solver phases. -- -- In principle, we have a valid tree after 'validationPhase', which @@ -103,18 +97,15 @@ solve sc cinfo idx pkgConfigDB userPrefs userConstraints userGoals = detectCycles = traceTree "cycles.json" id . detectCyclesPhase heuristicsPhase = let heuristicsTree = traceTree "heuristics.json" id - sortGoals = case goalOrder sc of - Nothing -> goalChoiceHeuristics . - heuristicsTree . - P.deferSetupChoices . - P.deferWeakFlagChoices . - P.preferBaseGoalChoice - Just order -> P.firstGoal . - heuristicsTree . - P.sortGoals order - PruneAfterFirstSuccess prune = pruneAfterFirstSuccess sc - in sortGoals . - (if prune then P.pruneAfterFirstSuccess else id) + in case goalOrder sc of + Nothing -> goalChoiceHeuristics . + heuristicsTree . + P.deferSetupChoices . + P.deferWeakFlagChoices . + P.preferBaseGoalChoice + Just order -> P.firstGoal . + heuristicsTree . + P.sortGoals order preferencesPhase = P.preferLinked . P.preferPackagePreferences userPrefs validationPhase = traceTree "validated.json" id . diff --git a/cabal-install/Distribution/Solver/Modular/Tree.hs b/cabal-install/Distribution/Solver/Modular/Tree.hs index a7ee060e043..91c2f9becc4 100644 --- a/cabal-install/Distribution/Solver/Modular/Tree.hs +++ b/cabal-install/Distribution/Solver/Modular/Tree.hs @@ -13,7 +13,6 @@ module Distribution.Solver.Modular.Tree , para , trav , zeroOrOneChoices - , active ) where import Control.Monad hiding (mapM, sequence) diff --git a/cabal-install/Distribution/Solver/Modular/WeightedPSQ.hs b/cabal-install/Distribution/Solver/Modular/WeightedPSQ.hs index 21216358ac5..91c37a4e6ae 100644 --- a/cabal-install/Distribution/Solver/Modular/WeightedPSQ.hs +++ b/cabal-install/Distribution/Solver/Modular/WeightedPSQ.hs @@ -1,5 +1,4 @@ {-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-} -{-# LANGUAGE ScopedTypeVariables #-} module Distribution.Solver.Modular.WeightedPSQ ( WeightedPSQ , fromList @@ -12,7 +11,6 @@ module Distribution.Solver.Modular.WeightedPSQ ( , mapWithKey , mapWeightsWithKey , union - , takeUntil ) where import qualified Data.Foldable as F @@ -78,15 +76,6 @@ mapWithKey f (WeightedPSQ xs) = WeightedPSQ $ union :: Ord w => WeightedPSQ w k v -> WeightedPSQ w k v -> WeightedPSQ w k v union (WeightedPSQ xs) (WeightedPSQ ys) = fromList (xs ++ ys) --- | /O(N)/. Return the prefix of values ending with the first element that --- satisfies p, or all elements if none satisfy p. -takeUntil :: forall w k v. (v -> Bool) -> WeightedPSQ w k v -> WeightedPSQ w k v -takeUntil p (WeightedPSQ xs) = WeightedPSQ (go xs) - where - go :: [(w, k, v)] -> [(w, k, v)] - go [] = [] - go (y : ys) = y : if p (triple_3 y) then [] else go ys - triple_1 :: (x, y, z) -> x triple_1 (x, _, _) = x diff --git a/cabal-install/Distribution/Solver/Types/Variable.hs b/cabal-install/Distribution/Solver/Types/Variable.hs index b4e4b1d7549..c33dcb12e4b 100644 --- a/cabal-install/Distribution/Solver/Types/Variable.hs +++ b/cabal-install/Distribution/Solver/Types/Variable.hs @@ -5,7 +5,8 @@ import Distribution.Solver.Types.OptionalStanza import Distribution.PackageDescription (FlagName) -- | Variables used by the dependency solver. This type is similar to the --- internal 'Var' type. +-- internal 'Var' type, except that flags and stanzas are associated with +-- package names instead of package instances. data Variable qpn = PackageVar qpn | FlagVar qpn FlagName diff --git a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs index 379324ab6e3..b242f2f8153 100644 --- a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs +++ b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs @@ -3,7 +3,6 @@ module UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils ( SolverTest , SolverResult(..) - , maxBackjumps , independentGoals , allowBootLibInstalls , disableBackjumping @@ -47,9 +46,6 @@ import Distribution.Client.Dependency (foldProgress) import UnitTests.Distribution.Solver.Modular.DSL import UnitTests.Options -maxBackjumps :: Maybe Int -> SolverTest -> SolverTest -maxBackjumps mbj test = test { testMaxBackjumps = mbj } - -- | Combinator to turn on --independent-goals behavior, i.e. solve -- for the goals as if we were solving for each goal independently. independentGoals :: SolverTest -> SolverTest @@ -87,7 +83,6 @@ data SolverTest = SolverTest { testLabel :: String , testTargets :: [String] , testResult :: SolverResult - , testMaxBackjumps :: Maybe Int , testIndepGoals :: IndependentGoals , testAllowBootLibInstalls :: AllowBootLibInstalls , testEnableBackjumping :: EnableBackjumping @@ -180,7 +175,6 @@ mkTestExtLangPC exts langs pkgConfigDb db label targets result = SolverTest { testLabel = label , testTargets = targets , testResult = result - , testMaxBackjumps = Nothing , testIndepGoals = IndependentGoals False , testAllowBootLibInstalls = AllowBootLibInstalls False , testEnableBackjumping = EnableBackjumping True @@ -200,7 +194,7 @@ runTest SolverTest{..} = askOption $ \(OptionShowSolverLog showSolverLog) -> testCase testLabel $ do let progress = exResolve testDb testSupportedExts testSupportedLangs testPkgConfigDb testTargets - testMaxBackjumps (CountConflicts True) testIndepGoals + Nothing (CountConflicts True) testIndepGoals (ReorderGoals False) testAllowBootLibInstalls testEnableBackjumping testSolveExecutables (sortGoals <$> testGoalOrder) testConstraints diff --git a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs index f5fa336bad3..720884ec68e 100644 --- a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs +++ b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs @@ -292,9 +292,9 @@ tests = [ solverFailure $ isInfixOf $ -- The solver reports the version conflict when a version conflict -- and an executable conflict apply to the same package version. - "[__1] rejecting: H:bt-pkg:exe.bt-pkg-4.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)\n" - ++ "[__1] rejecting: H:bt-pkg:exe.bt-pkg-3.0.0 (does not contain executable exe1, which is required by H)\n" - ++ "[__1] rejecting: H:bt-pkg:exe.bt-pkg-2.0.0, H:bt-pkg:exe.bt-pkg-1.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)" + "rejecting: H:bt-pkg:exe.bt-pkg-4.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)\n" + ++ "rejecting: H:bt-pkg:exe.bt-pkg-3.0.0 (does not contain executable exe1, which is required by H)\n" + ++ "rejecting: H:bt-pkg:exe.bt-pkg-2.0.0, H:bt-pkg:exe.bt-pkg-1.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)" , runTest $ chooseExeAfterBuildToolsPackage True "choose exe after choosing its package - success" @@ -346,25 +346,6 @@ tests = [ ++ "these were the goals I've had most trouble fulfilling: A, B" in mkTest db "exhaustive search failure message" ["A"] $ solverFailure (isInfixOf msg) - , testSummarizedLog "show conflicts from final conflict set after exhaustive search" Nothing $ - "Could not resolve dependencies:\n" - ++ "[__0] trying: A-1.0.0 (user goal)\n" - ++ "[__1] unknown package: D (dependency of A)\n" - ++ "[__1] fail (backjumping, conflict set: A, D)\n" - ++ "After searching the rest of the dependency tree exhaustively, " - ++ "these were the goals I've had most trouble fulfilling: A, D" - , testSummarizedLog "show first conflicts after inexhaustive search" (Just 2) $ - "Could not resolve dependencies:\n" - ++ "[__0] trying: A-1.0.0 (user goal)\n" - ++ "[__1] trying: B-3.0.0 (dependency of A)\n" - ++ "[__2] next goal: C (dependency of B)\n" - ++ "[__2] rejecting: C-1.0.0 (conflict: B => C==3.0.0)\n" - ++ "Backjump limit reached (currently 2, change with --max-backjumps " - ++ "or try to run with --reorder-goals).\n" - , testSummarizedLog "don't show summarized log when backjump limit is too low" (Just 1) $ - "Backjump limit reached (currently 1, change with --max-backjumps " - ++ "or try to run with --reorder-goals).\n" - ++ "Failed to generate a summarized dependency solver log due to low backjump limit." ] ] where @@ -967,9 +948,9 @@ db18 = [ commonDependencyLogMessage :: String -> SolverTest commonDependencyLogMessage name = mkTest db name ["A"] $ solverFailure $ isInfixOf $ - "[__0] trying: A-1.0.0 (user goal)\n" - ++ "[__1] next goal: B (dependency of A +/-flagA)\n" - ++ "[__1] rejecting: B-2.0.0 (conflict: A +/-flagA => B==1.0.0 || ==3.0.0)" + "trying: A-1.0.0 (user goal)\n" + ++ "next goal: B (dependency of A +/-flagA)\n" + ++ "rejecting: B-2.0.0 (conflict: A +/-flagA => B==1.0.0 || ==3.0.0)" where db :: ExampleDb db = [ @@ -1301,29 +1282,6 @@ dbPC1 = [ , Right $ exAv "C" 1 [ExAny "B"] ] --- | Test for the solver's summarized log. The final conflict set is {A, D}, --- though the goal order forces the solver to find the (avoidable) conflict --- between B >= 2 and C first. When the solver reaches the backjump limit, it --- should only show the log to the first conflict. When the backjump limit is --- high enough to allow an exhaustive search, the solver should make use of the --- final conflict set to only show the conflict between A and D in the --- summarized log. -testSummarizedLog :: String -> Maybe Int -> String -> TestTree -testSummarizedLog testName mbj expectedMsg = - runTest $ maxBackjumps mbj $ goalOrder goals $ mkTest db testName ["A"] $ - solverFailure (== expectedMsg) - where - db = [ - Right $ exAv "A" 1 [ExAny "B", ExAny "D"] - , Right $ exAv "B" 3 [ExFix "C" 3] - , Right $ exAv "B" 2 [ExFix "C" 2] - , Right $ exAv "B" 1 [ExAny "C"] - , Right $ exAv "C" 1 [] - ] - - goals :: [ExampleVar] - goals = [P QualNone pkg | pkg <- ["A", "B", "C", "D"]] - {------------------------------------------------------------------------------- Simple databases for the illustrations for the backjumping blog post -------------------------------------------------------------------------------} @@ -1501,8 +1459,8 @@ chooseExeAfterBuildToolsPackage shouldSucceed name = requireConsistentBuildToolVersions :: String -> SolverTest requireConsistentBuildToolVersions name = mkTest db name ["A"] $ solverFailure $ isInfixOf $ - "[__1] rejecting: A:B:exe.B-2.0.0 (conflict: A => A:B:exe.B (exe exe1)==1.0.0)\n" - ++ "[__1] rejecting: A:B:exe.B-1.0.0 (conflict: A => A:B:exe.B (exe exe2)==2.0.0)" + "rejecting: A:B:exe.B-2.0.0 (conflict: A => A:B:exe.B (exe exe1)==1.0.0)\n" + ++ "rejecting: A:B:exe.B-1.0.0 (conflict: A => A:B:exe.B (exe exe2)==2.0.0)" where db :: ExampleDb db = [ diff --git a/cabal-testsuite/PackageTests/Backpack/Includes2/setup-external.cabal.out b/cabal-testsuite/PackageTests/Backpack/Includes2/setup-external.cabal.out index e91346a7b78..38102e2778f 100644 --- a/cabal-testsuite/PackageTests/Backpack/Includes2/setup-external.cabal.out +++ b/cabal-testsuite/PackageTests/Backpack/Includes2/setup-external.cabal.out @@ -99,10 +99,10 @@ Registering library for src-0.1.0.0.. Resolving dependencies... Warning: solver failed to find a solution: Could not resolve dependencies: -[__0] trying: exe-0.1.0.0 (user goal) -[__1] next goal: src (dependency of exe) -[__1] rejecting: src-/installed-... (conflict: src => mylib==0.1.0.0/installed-0.1..., src => mylib==0.1.0.0/installed-0.1...) -[__1] fail (backjumping, conflict set: exe, src) +trying: exe-0.1.0.0 (user goal) +next goal: src (dependency of exe) +rejecting: src-/installed-... (conflict: src => mylib==0.1.0.0/installed-0.1..., src => mylib==0.1.0.0/installed-0.1...) +fail (backjumping, conflict set: exe, src) After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: exe (2), src (2) Trying configure anyway. Configuring exe-0.1.0.0... diff --git a/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackage/use-local-version-of-package.out b/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackage/use-local-version-of-package.out index f975325ec42..3515de864da 100644 --- a/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackage/use-local-version-of-package.out +++ b/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackage/use-local-version-of-package.out @@ -13,7 +13,7 @@ local pkg-1.0 # cabal new-build Resolving dependencies... cabal: Could not resolve dependencies: -[__0] next goal: pkg (user goal) -[__0] rejecting: pkg-2.0 (constraint from user target requires ==1.0) -[__0] rejecting: pkg-1.0 (constraint from command line flag requires ==2.0) +next goal: pkg (user goal) +rejecting: pkg-2.0 (constraint from user target requires ==1.0) +rejecting: pkg-1.0 (constraint from command line flag requires ==2.0) After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: pkg (3) diff --git a/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.out b/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.out index db1c3e94a60..c9c06ce0dbf 100644 --- a/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.out +++ b/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.out @@ -3,11 +3,11 @@ Downloading the latest package list from test-local-repo # cabal new-build Resolving dependencies... cabal: Could not resolve dependencies: -[__0] trying: pkg-1.0 (user goal) -[__1] next goal: setup-dep (user goal) -[__1] rejecting: setup-dep-2.0 (conflict: pkg => setup-dep==1.*) -[__1] rejecting: setup-dep-1.0 (constraint from user target requires ==2.0) -[__1] fail (backjumping, conflict set: pkg, setup-dep) +trying: pkg-1.0 (user goal) +next goal: setup-dep (user goal) +rejecting: setup-dep-2.0 (conflict: pkg => setup-dep==1.*) +rejecting: setup-dep-1.0 (constraint from user target requires ==2.0) +fail (backjumping, conflict set: pkg, setup-dep) After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: setup-dep (3), pkg (2) # pkg my-exe Main.hs: setup-dep from repo diff --git a/cabal-testsuite/PackageTests/ConfigureComponent/Exe/setup.cabal.out b/cabal-testsuite/PackageTests/ConfigureComponent/Exe/setup.cabal.out index 90439a1fdc6..9284a1ad2c5 100644 --- a/cabal-testsuite/PackageTests/ConfigureComponent/Exe/setup.cabal.out +++ b/cabal-testsuite/PackageTests/ConfigureComponent/Exe/setup.cabal.out @@ -2,9 +2,9 @@ Resolving dependencies... Warning: solver failed to find a solution: Could not resolve dependencies: -[__0] trying: Exe-0.1.0.0 (user goal) -[__1] unknown package: totally-impossible-dependency-to-fill (dependency of Exe) -[__1] fail (backjumping, conflict set: Exe, totally-impossible-dependency-to-fill) +trying: Exe-0.1.0.0 (user goal) +unknown package: totally-impossible-dependency-to-fill (dependency of Exe) +fail (backjumping, conflict set: Exe, totally-impossible-dependency-to-fill) After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: Exe (2), totally-impossible-dependency-to-fill (1) Trying configure anyway. Configuring executable 'goodexe' for Exe-0.1.0.0.. diff --git a/cabal-testsuite/PackageTests/InternalVersions/BuildDependsBad/setup.cabal.out b/cabal-testsuite/PackageTests/InternalVersions/BuildDependsBad/setup.cabal.out index 815f6399b4a..32067ddeab2 100644 --- a/cabal-testsuite/PackageTests/InternalVersions/BuildDependsBad/setup.cabal.out +++ b/cabal-testsuite/PackageTests/InternalVersions/BuildDependsBad/setup.cabal.out @@ -2,8 +2,8 @@ Resolving dependencies... Warning: solver failed to find a solution: Could not resolve dependencies: -[__0] next goal: build-depends-bad-version (user goal) -[__0] rejecting: build-depends-bad-version-0.1.0.0 (conflict: build-depends-bad-version==0.1.0.0, build-depends-bad-version => build-depends-bad-version>=2) +next goal: build-depends-bad-version (user goal) +rejecting: build-depends-bad-version-0.1.0.0 (conflict: build-depends-bad-version==0.1.0.0, build-depends-bad-version => build-depends-bad-version>=2) After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: build-depends-bad-version (2) Trying configure anyway. Configuring build-depends-bad-version-0.1.0.0... From adc7406ffe644e5ce866094465d338b5ff656095 Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Thu, 8 Feb 2018 11:15:03 +0000 Subject: [PATCH 4/6] Fix paths. --- Cabal/doc/nix-local-build.rst | 8 +++++--- travis-common.sh | 2 +- travis-script.sh | 2 +- travis/upload.sh | 8 ++++---- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Cabal/doc/nix-local-build.rst b/Cabal/doc/nix-local-build.rst index 8bc2e4f7cc8..ed1b1d1bbc1 100644 --- a/Cabal/doc/nix-local-build.rst +++ b/Cabal/doc/nix-local-build.rst @@ -188,11 +188,13 @@ version of cabal-install: defining a library built with GHC 8.0.1 on 64-bit Linux is ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1``. When per-component builds are enabled (any non-Custom package), a - subcomponent like an executable or test suite named ``pexe`` will be + subcomponent like an executable or named ``pexe`` will be stored at - ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/c/pexe``; thus, + ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/x/pexe``; thus, the full path of the executable is - ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/c/pexe/build/pexe/pexe`` + ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/x/pexe/build/pexe/pexe``. + If a component is a test suite, `x` is replaced with `t`, and for benchmarks + with `b` - so you get paths like `.../t/ptest/...` and `.../b/pbench/...` (you can see why we want this to be an implementation detail!) The paths are a bit longer in HEAD but the benefit is that you can diff --git a/travis-common.sh b/travis-common.sh index 264c21f308b..bcbab482852 100644 --- a/travis-common.sh +++ b/travis-common.sh @@ -16,7 +16,7 @@ CABAL_TESTSUITE_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/ CABAL_INSTALL_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/cabal-install-${CABAL_VERSION}" CABAL_INSTALL_SETUP="${CABAL_INSTALL_BDIR}/setup/setup" SOLVER_BENCHMARKS_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/solver-benchmarks-${CABAL_VERSION}" -HACKAGE_REPO_TOOL_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/hackage-repo-tool-${HACKAGE_REPO_TOOL_VERSION}/c/hackage-repo-tool" +HACKAGE_REPO_TOOL_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/hackage-repo-tool-${HACKAGE_REPO_TOOL_VERSION}/x/hackage-repo-tool" # --------------------------------------------------------------------- # Timing / diagnostic output diff --git a/travis-script.sh b/travis-script.sh index a599a66aebb..6de5cbf15d5 100755 --- a/travis-script.sh +++ b/travis-script.sh @@ -179,7 +179,7 @@ timed ${CABAL_INSTALL_BDIR}/build/cabal/cabal update if [ "x$TEST_SOLVER_BENCHMARKS" = "xYES" ]; then timed cabal new-build $jobs solver-benchmarks:hackage-benchmark solver-benchmarks:unit-tests - timed ${SOLVER_BENCHMARKS_BDIR}/c/unit-tests/build/unit-tests/unit-tests $TEST_OPTIONS + timed ${SOLVER_BENCHMARKS_BDIR}/t/unit-tests/build/unit-tests/unit-tests $TEST_OPTIONS fi unset CABAL_BUILDDIR diff --git a/travis/upload.sh b/travis/upload.sh index 0aef219a0e7..a1956543231 100755 --- a/travis/upload.sh +++ b/travis/upload.sh @@ -70,10 +70,10 @@ cp $TRAVIS_BUILD_DIR/travis/id_rsa . cp $TRAVIS_BUILD_DIR/travis-install.sh . cp $TRAVIS_BUILD_DIR/travis-common.sh . # The binaries to test (statically linked, of course!) -cp ${CABAL_BDIR}/c/unit-tests/build/unit-tests/unit-tests Cabal -cp ${CABAL_BDIR}/c/check-tests/build/check-tests/check-tests Cabal -cp ${CABAL_BDIR}/c/parser-tests/build/parser-tests/parser-tests Cabal -cp ${CABAL_BDIR}/c/hackage-tests/build/hackage-tests/hackage-tests Cabal +cp ${CABAL_BDIR}/t/unit-tests/build/unit-tests/unit-tests Cabal +cp ${CABAL_BDIR}/t/check-tests/build/check-tests/check-tests Cabal +cp ${CABAL_BDIR}/t/parser-tests/build/parser-tests/parser-tests Cabal +cp ${CABAL_BDIR}/t/hackage-tests/build/hackage-tests/hackage-tests Cabal if [ "x$CABAL_LIB_ONLY" != "xYES" ]; then cp ${CABAL_INSTALL_BDIR}/build/cabal/cabal cabal-install fi From e7a557cf8c3f2b7e1f78f623c29ff631745e1ada Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Thu, 8 Feb 2018 18:22:17 +0000 Subject: [PATCH 5/6] Disable 'cabal check' temporarily. --- travis-script.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/travis-script.sh b/travis-script.sh index 6de5cbf15d5..da32ad9263a 100755 --- a/travis-script.sh +++ b/travis-script.sh @@ -110,7 +110,7 @@ if [ "x$CABAL_INSTALL_ONLY" != "xYES" ] ; then fi # Check for package warnings - (cd Cabal && timed cabal check) || exit $? + # (cd Cabal && timed cabal check) || exit $? fi unset CABAL_BUILDDIR @@ -175,7 +175,7 @@ timed ${CABAL_INSTALL_BDIR}/build/cabal/cabal update # Big tests (cd cabal-testsuite && timed ${CABAL_TESTSUITE_BDIR}/build/cabal-tests/cabal-tests --builddir=${CABAL_TESTSUITE_BDIR} -j3 --skip-setup-tests --with-cabal ${CABAL_INSTALL_BDIR}/build/cabal/cabal --with-hackage-repo-tool ${HACKAGE_REPO_TOOL_BDIR}/build/hackage-repo-tool/hackage-repo-tool $TEST_OPTIONS) || exit $? -(cd cabal-install && timed cabal check) || exit $? +# (cd cabal-install && timed cabal check) || exit $? if [ "x$TEST_SOLVER_BENCHMARKS" = "xYES" ]; then timed cabal new-build $jobs solver-benchmarks:hackage-benchmark solver-benchmarks:unit-tests From 686173c5519dafd04cdc0d538703ca9014771e07 Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Thu, 8 Feb 2018 18:23:42 +0000 Subject: [PATCH 6/6] Downgrade the severity of the '-main-is' ghc-options check. --- Cabal/Distribution/PackageDescription/Check.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cabal/Distribution/PackageDescription/Check.hs b/Cabal/Distribution/PackageDescription/Check.hs index 7d62188072b..bae239d9a82 100644 --- a/Cabal/Distribution/PackageDescription/Check.hs +++ b/Cabal/Distribution/PackageDescription/Check.hs @@ -801,7 +801,7 @@ checkGhcOptions pkg = "'ghc-options: --make' is never needed. Cabal uses this automatically." , checkFlags ["-main-is"] $ - PackageDistSuspicious $ + PackageDistSuspiciousWarn $ "'ghc-options: -main-is' is not portable." , checkNonTestAndBenchmarkFlags ["-O0", "-Onot"] $