This project is mirrored from Pull mirroring updated .
  1. 09 May, 2018 1 commit
    • kristenk's avatar
      Solver: Enforce dependencies on libraries (fixes #779). · 6efb5e23
      kristenk authored
      This commit generalizes the fix for issue #4781
      (e86f8389) by tracking dependencies on
      components instead of dependencies on executables.  That means that the solver
      always checks whether a package contains a library before using it to satisfy a
      build-depends dependency.  If a version of a package doesn't contain a library,
      the solver can try other versions.  Associating each dependency with a component
      also moves towards the design for component-based dependency solving described
      in issue #4087.
  2. 21 Jan, 2018 1 commit
    • kristenk's avatar
      Also merge dependencies with different DependencyReasons. · a5fefbd2
      kristenk authored
      This commit adds to the previous one by merging dependencies even when they have
      different DependencyReasons.  This change should completely prevent the
      dependency-lifting feature from causing exponential growth of dependencies.  It
      also improves the memory usage test by putting each dependency under a different
      flag, meaning that every dependency has a different DependencyReason.
  3. 20 Jan, 2018 1 commit
    • kristenk's avatar
      Merge dependencies more effectively in D.Solver.Modular.IndexConversion. · 59febb17
      kristenk authored
      This commit is a more thorough fix for the problem that
      4f7ac10d attempted to fix.  4f7ac10d combined
      all dependencies on the same package within the same build-depends or
      build-tool-depends field, in order to avoid performance problems in the solver
      QuickCheck tests.  That wasn't enough to prevent the solver from creating many
      duplicate dependencies when converting the PackageDescription to the
      solver-specific format, though.  When a package contained many conditionals that
      each contained the same dependency in both branches, the solver lifted those
      dependencies out of the conditionals without deduplicating them.
      This commit moves the step that merges dependencies after the step that lifts
      common dependencies out of conditionals.
  4. 17 Dec, 2017 3 commits
    • kristenk's avatar
      Solver: Combine dependencies on the same package in the same 'build-depends'. · 4f7ac10d
      kristenk authored
      This commit is unlikely to have an effect on real packages, but it reduces the
      chance of performance problems caused by duplicate dependencies in the solver
      quickcheck tests.  It also adds a regression test to memory-usage-tests.
    • kristenk's avatar
      Solver: Remove redundant flag choices from FlaggedDeps. · d239a60f
      kristenk authored
      This commit simplifies the solver's internal representation of package
      conditionals by removing branches that are unreachable.  For example, the solver
      now simplifies
      if flag(A)
        if flag(A)
          build-depends: package-a
          build-depends: package-b
      if flag(A)
        build-depends: package-a
      because A must be true for the second conditional to be relevant to the
      finalized PackageDescription.
      This change probably won't improve performance by simplifying real packages.
      However, it fixes a bug in the solver's handling of a certain edge case.  Before
      this change, it was possible for the solver to create DependencyReasons with
      conflicting flag values.  The conflicting values could cause a problem when
      one was FlagBoth, the value used when the same dependency appears on both sides
      of a conditional.  Here is an example:
      if flag(A)
        if flag(A)
          build-depends: unknown-package
          build-depends: unknown-package
      Previously, the solver inserted both A=FlagTrue and A=FlagBoth into the
      DependencyReason for the dependency on unknown-package. When the previous
      commit changed the association list of flag values into a map, FlagBoth replaced
      FlagTrue and prevented the solver from trying -A.
      This commit simplifies the conditionals to:
      if flag(A)
        build-depends: unknown-package
      It also adds some unit tests for dependencies occurring on both sides of
      conditionals. "testBackjumpingWithCommonDependency" tests the example above.
    • kristenk's avatar
      Solver: Deduplicate flags and stanzas in DependencyReason. · 6fe3c5f7
      kristenk authored
      This commit changes DependencyReason's list fields to maps and sets. Duplicate
      flags were possible when a flag appeared multiple times in nested conditionals
      or a flag controlled a "Buildable: False" field. The duplicate flag could show
      up in log messages:
      [__5] trying: json-rpc-client:+demo
      [__6] trying: process- (dependency of json-rpc-client +demo +demo)
      [__5] trying: json-rpc-client:+demo
      [__6] trying: process- (dependency of json-rpc-client +demo)
  5. 25 Nov, 2017 1 commit
    • Herbert Valerio Riedel's avatar
      Have the solver reject packages with a too-new/unsupported spec-version · 97155ecd
      Herbert Valerio Riedel authored
      This compares the request spec-version to the lib:Cabal's version in order to
      determine whether cabal is able to properly understand the package. If it's
      newer than the currently linked lib:Cabal version it's turned into a global
      `FailResult` which the solver treats as desired in terms of backtracking and
      error reporting.
      This is related to the new spec-version forward-compat scheme (see #4899).
      This is a forward-port of #4907 to the `master` branch
  6. 12 Nov, 2017 1 commit
  7. 25 Sep, 2017 1 commit
    • kristenk's avatar
      Remove the package instance from D.Solver.Modular.Var (closes #4142). · e1ca9dcf
      kristenk authored
      This change has several effects:
      - The solver no longer includes the package version in messages that relate to
        a package's flags, stanzas, or dependencies.  However, the solver always
        chooses the package version before choosing any flags, stanzas, or
        dependencies for the package, so it should be easy to find the version
        by looking earlier in the log.
      - In conflict counting, the solver treats flags with the same name in different
        versions of a package as the same flag.  This change in the conflict counting
        heuristic can improve the solver's efficiency when the same flag causes the
        same conflicts in different versions of a package.  The same applies to
        enabling tests or benchmarks.
      - Each flag or stanza can only appear once in a conflict set.  This has no
        effect on behavior, but it simplifies the message containing the final
        conflict set.
      Here is an example of the change in a log message.  It only prints
      hackage-server's version once, when it first chooses the package.  The conflict
      set also has one fewer variable, but that is probably due to the change in
      conflict counting.
       Resolving dependencies...
       cabal: Could not resolve dependencies:
       trying: hackage-server-0.5.0 (user goal)
      -trying: hackage-server-0.5.0:+build-hackage-build
      -trying: unix- (dependency of hackage-server-0.5.0
      +trying: hackage-server:+build-hackage-build
      +trying: unix- (dependency of hackage-server
      -next goal: aeson (dependency of hackage-server-0.5.0 +build-hackage-build)
      +next goal: aeson (dependency of hackage-server +build-hackage-build)
       rejecting: aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-, aeson-
       (conflict: hackage-server +build-hackage-build => aeson==0.6.1.*)
       rejecting: aeson- (conflict: unix => time==,
       aeson => time<1.5)
       rejecting: aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-, aeson-,
       aeson-, aeson-, aeson-, aeson-, aeson-
       (conflict: hackage-server +build-hackage-build => aeson==0.6.1.*)
       After searching the rest of the dependency tree exhaustively, these were the
      -goals I've had most trouble fulfilling: aeson, hackage-server,
      -hackage-server-0.4:build-hackage-mirror, template-haskell
      +goals I've had most trouble fulfilling: aeson,
      +hackage-server:build-hackage-build, hackage-server, template-haskell
      I ran hackage-benchmark to compare this commit with master (two commits
      earlier).  I used --min-run-time-percentage-difference-to-rerun=10 to only rerun
      packages if the run times differed by more than 10% in the first trial, and
      defaults for the rest of the options (10 trials, p-value of 0.05, 90 second
      timeout). The index state was "2017-09-24T03:35:06Z".
      1 is master, and 2 is this commit:
      package            result1       result2             mean1       mean2     stddev1     stddev2     speedup
      CC-delcont-ref     Solution      Solution           1.467s      1.505s      0.019s      0.100s      0.975
      ascii-cows         Solution      Solution           1.827s      1.758s      0.159s      0.012s      1.040
      opaleye-classy     NoInstallPlan NoInstallPlan      4.588s      4.070s      0.043s      0.032s      1.127
      range-space        NoInstallPlan NoInstallPlan      2.642s      2.299s      0.016s      0.016s      1.149
      rts                PkgNotFound   PkgNotFound        1.323s      1.327s      0.032s      0.033s      0.997
      servant-auth-docs  Solution      Solution           1.968s      1.998s      0.017s      0.074s      0.985
      thorn              BackjumpLimit NoInstallPlan      4.793s      3.141s      0.050s      0.034s      1.526
      unordered-intmap   Solution      Solution           1.502s      1.511s      0.081s      0.047s      0.994
      I looked at the solver logs for the three packages with the largest changes in
      run time, opaleye-classy, range-space, and thorn.  Each one showed that the
      solver started preferring a flag in an older version of a package after it had
      caused conflicts in a newer version of the package.
  8. 17 Jun, 2017 1 commit
    • kristenk's avatar
      Solver: Add individual flags to conflict sets. · 1d016574
      kristenk authored
      This commit changes the way that the solver tracks the variables that introduce
      dependencies, in order to fix some bugs that prevented the solver from tracking
      individual flags.  I refactored Dep, the type that represents a build-depends or
      build-tool-depends dependency, so that it stores the package, flag, and stanza
      choices that introduced the dependency.  That information is stored in a field
      of type DependencyReason.  The DependencyReason is available to any solver phase
      that needs to create conflict sets, such as "build" or "validation".  Whenever
      there is a conflict involving a dependency, the solver creates a conflict set
      and a log message using the dependency's DependencyReason.  This means that the
      solver only needs to calculate the dependency reasons once, in
      IndexConversion.hs, rather than every time they are used, i.e., in Builder.hs
      (for goal reasons), Validate.hs, and Linking.hs.
      Another difference between this commit and master is the dependencies between
      solver variables.  On master, each dependency or variable is introduced by
      exactly one other variable.  For example, if package x has a flag y, which
      controls a dependency on package z, then the three variables depend on each
      other in a chain, x -> y -> z.  If z can't be satisfied, the solver backjumps
      to its cause, y, and if flipping y doesn't help, it continues backjumping to y's
      cause, which is x.  In contrast, this commit allows each dependency to be
      introduced by a package and any number of flags and stanzas.  So z's
      DependencyReason would contain both x and y.
      Storing all flags that introduced a dependency allows the solver to correctly
      calculate conflict sets when there are nested conditionals.  We no longer need
      to combine each package's flags into a single conflict set variable.  This
      commit removes the 'simplifyVar' function and adds flag variables directly to
      conflict sets.  See issue #4391.
      This commit makes another minor change.  In this commit and master, if a
      dependency appears in the if and else blocks of a conditional, the solver lifts
      it out of the conditional.  Previously, the solver behaved as if the flag did
      not introduce the dependency.  This commit adds the flag variable to the
      conflict set or error message if the dependency is involved in a conflict.  This
      change doesn't affect correctness, but I think it improves the error messages,
      since it gives the whole reason that each dependency was introduced.
  9. 28 Apr, 2017 1 commit
  10. 01 Apr, 2017 1 commit
    • kristenk's avatar
      Refactor solver goal types. · 2245c9d9
      kristenk authored
      This commit should have no effect on behavior.  It splits the OpenGoal type into
      OpenGoal and PotentialGoal.  Both types are only used when building the search
      tree.  While PotentialGoal can represent any dependency or constraint, OpenGoal
      only represents dependencies that introduce goals (solver variables).  Limiting
      OpenGoal to only represent goals simplifies the code.
      This commit also removes OpenGoal and FlaggedDep's 'comp' type variables.  The
      two types had only been used with 'comp' equal to () or Component.  Now
      FlaggedDep always uses Component, and OpenGoal does not need a Component.
  11. 17 Mar, 2017 4 commits
    • Edward Z. Yang's avatar
      Fix comment typo. · 3ef451c0
      Edward Z. Yang authored
      Signed-off-by: default avatarEdward Z. Yang <>
    • Edward Z. Yang's avatar
      Refactor MungedPackageId and PackageIndex. · f4ded04f
      Edward Z. Yang authored
      This makes the necessary changes to 4dc0f30fc36914ee2f01bde016bee98b8e0bb0bb
      to handle component configuring correctly.  It probably is a good step
      towards pkg:lib style dependencies.
      The big ideas:
      * There's a new AnnotatedId type, which is any identifier (like
        ComponentId), but also with a PackageId and ComponentName.
        It's a bit like ConfiguredId, but ConfiguredId is specialized
        for ComponentId.  There's a conversion function
      * We adopt a totally new strategy for handling MungedPackageId in
        InstalledPackageInfo.  Rather than store the munged package
        identifier in IPI, we NEVER store it, instead computing it
        from the package name and library name (which are stored.)
        There is now code to PARSE a munged package name into these
        two components, so that when we read 'name' we get the
        correct info.  The resulting code is splendidly clear.
      * Some places where we took a ComponentName (notably
        computeCompatPackageName) we now take 'Maybe UnqualComponentName'.
        This is more accurate, because compatibility package names are
        only computed for libraries, not other components.  Some code
        in Distribution.Backpack.ReadyComponent is partial now,
        but the invariants should hold up.
      * A number of places where MungedId was applied, I undid them.
        Most notable are macro generation (that should be PACKAGES,
        not components) and mkLegacyUnitId (since REALLY old style
        unit identifiers, we won't support internal libraries anyway.)
      * Many functions in PackageIndex are monomorphized to
        InstalledPackageInfo.  Fortunately cabal-install's usage
        still works.
      * Distribution/Client/SolverPlanIndex.hs, not used by anyone,
        got the axe.
      * Dependency solving has a hack to solve the problem of how to
        interpret installed internal libraries in the package database.
        The basic idea is that, although in most cases where we used
        a MungedId, we say it explicitly, in the SOLVER, we munge
        *installed package names* only, and keep the type PackageName.
        It's a hack, but the alternative is to write a lot more code.
        Note that is MORALLY PN is indeed a PackageName, since we really
        are solving for honest to goodness packages, not components!
        See Note [Index conversion with internal libraries] for more
      * ConfiguredId now records the ComponentName.  This is quite important,
        because we need to use it to figure out how we are going to phrase
        --dependency.  In fact, it is a miracle that this worked at all
        (and it only worked because of a very skeevy update to the PackageId
        in the creation of ConfiguredComponent).  Irritatingly, this must
        be a Maybe ComponentName, because a ConfiguredId MIGHT refer to
        a setup component. Very distressing.
      Signed-off-by: default avatarEdward Z. Yang <>
    • Edward Z. Yang's avatar
      Revert "Revert "Merge pull request #4382 from Ericson2314/munge"" · b0e6c311
      Edward Z. Yang authored
      This reverts commit 4774fb6558974a721176f1fb48d8ce7d43119251.
    • Edward Z. Yang's avatar
      Revert "Merge pull request #4382 from Ericson2314/munge" · b1b9d3b1
      Edward Z. Yang authored
      This reverts commit 332d809c, reversing
      changes made to 0c72bc88.
  12. 09 Mar, 2017 1 commit
  13. 20 Feb, 2017 1 commit
    • kristenk's avatar
      Allow the solver to toggle manual flags to match constraints that have any qualifier. · f7f63ab4
      kristenk authored
      This fixes #4299. The change gives the dependency solver the flexibility to link
      dependencies when the user has only set a manual flag on one of them.
      Previously, the solver would force the constrained dependency to have the
      flag value from the constraint and force the unconstrained dependency to have
      the default flag value. In cases where the single instance restriction required
      the dependencies to be linked, the solver couldn't find a solution.
      Qualified constraints can still be used to force different dependencies on a
      package to use different flag values. For example,
      "--constraint 'pkg +flag' --constraint 'pkg2:setup.pkg -flag'" turns the flag on
      for the top-level dependency and off for the setup dependency.
      I also stored flag default values in the search tree to simplify the code.
  14. 06 Jan, 2017 2 commits
  15. 14 Nov, 2016 1 commit
  16. 01 Nov, 2016 1 commit
  17. 31 Oct, 2016 1 commit
  18. 28 Oct, 2016 1 commit
    • Edsko de Vries's avatar
      Add support for foreign libraries. · 382143aa
      Edsko de Vries authored
      A stanza for a platform library looks something like
          platform-library test-package
            type:                native-shared
            if os(Windows)
              options: standalone
              mod-def-file: TestPackage.def
            other-modules:       MyPlatformLib.Hello
            build-depends:       base >=4.7 && <4.9
            hs-source-dirs:      src
            c-sources:           csrc/MyPlatformLibWrapper.c
            default-language:    Haskell2010
      where native-shared means that we want to build a native shared library
      (.so on Linux, .dylib on OSX, .dll on Windows). The parser also
      recognizes native-static but this is not currently supported anywhere.
      The standalone option means that the we merge all library dependencies
      into the dynamic library (i.e., ghc options -shared -static), rather
      than make the created dynamic library just record its dependencies (ghc
      options -shared -dynamic); it is currently compulsory on Windows and
      unsupported anywhere else. The mod-def-file can be used to specify a
      module definition file, and is also Windows specific.
      There is a bit of refactoring in Build: gbuild is the old buildOrReplExe
      and now deals with both executables and platform libraries.
  19. 27 Sep, 2016 1 commit
    • Herbert Valerio Riedel's avatar
      Make `PackageName` type opaque (#3896) · dabd9d98
      Herbert Valerio Riedel authored
      When looking at heap-profiles of `cabal-install`, the `(:)` constructor
      stands out as the most-allocated constructor on the heap.
      Having to handle 10k+ package names contributes to the allocation
      numbers, especially on 64bit archs where ASCII `String`s have a 24 byte
      per character footprint.
      This commit is a preparatory commit to pave the way for changing
      `PackageName`'s internal representation to something like
      `ShortByteString` (which is essentially a thin wrapper around primitive
      `ByteArray#`s which themselves have have an overhead of 2 words + one
      byte per ASCII character rounded up to nearest word) which would allow
      to reduce the memory footprint by a full order of magnitude, as well as
      reduce pointer chasing and GC overhead.
  20. 21 Sep, 2016 1 commit
    • Edward Z. Yang's avatar
      Don't solve for executables in legacy code path. · 9e99b3f4
      Edward Z. Yang authored
      There is a bug in `cabal configure`'s invocation of the solver in
              (SourcePackageDb mempty packagePrefs)
              [SpecificSourcePackage localPkg]
      We can see that the solver is given an EMPTY source package database.
      This is because we assume that everything you need from cabal configure
      is taken from the installed package index.
      But this is NOT true for executables, which never have an entry in the
      installed package index. So we SHOULD NOT solve for
      executables in the legacy codepath, since there isn't anything useful we
      can do with the info anyway.  This gets toggled using a new solver
      parameter SolveExecutables.
      I didn't bother with a test because this will be obsoleted by
      Fixes #3875
      Signed-off-by: default avatarEdward Z. Yang <>
  21. 07 Sep, 2016 1 commit
    • kristenk's avatar
      Fix #3775. · c7fdf9d0
      kristenk authored
      This commit undoes a change from c0a48602 that filtered out build-depends
      entries that matched the names of executable components.
  22. 21 Aug, 2016 1 commit
    • Edward Z. Yang's avatar
      Solve for, build, and add to path build-tools dependencies. · c0a48602
      Edward Z. Yang authored
      This fixes #220: new-build now builds, installs and adds executables to
      PATH automatically if they show up in 'build-tools'.  However, there is
      still more that could be done: the new behavior only applies to a
      specific list of 'build-tools' (alex, happy, etc) which Cabal recognizes
      out of the box.  The plan is to introduce a new 'tool-depends' field to
      allow dependencies on other executables as well.
      Signed-off-by: default avatarEdward Z. Yang <>
  23. 22 Jul, 2016 1 commit
  24. 21 Jul, 2016 1 commit
  25. 05 Jun, 2016 1 commit
  26. 26 Apr, 2016 1 commit
  27. 24 Apr, 2016 1 commit
  28. 22 Apr, 2016 1 commit
    • Andres Löh's avatar
      Replace Goal with Var where possible; remove Unknown goal reason. · 16cae8a0
      Andres Löh authored
      In several places where we used to work with Goals mainly to maintain
      the goal reasons for constructing conflict sets, we can now do so
      without, and just use Vars instead.
      This also has the advantage that when creating dependencies during
      index conversion, we now do not have to invent goal reasons. We used
      to do that by having an "Unknown" goal reason. This is now no longer
  29. 21 Apr, 2016 1 commit
  30. 01 Apr, 2016 4 commits
  31. 31 Mar, 2016 1 commit