Skip to content

Problem with cyclic dependencies #6905

@mpilgrem

Description

@mpilgrem

Consider two packages, A and B. Both have a library and B has a test suite. If the library of A depends on B and the test suite of B depends on A, then:

  • stack build should work; and
  • stack test should also work. This is because, although if Stack built libraries and executables 'all-in-one` (as it normally does) there would be a 'cycle' (A depends on B, B depends on A), Stack is supposed to detect that and defer the building of B's test suite until after the libraries are built.

There is an integration test that is supposed to check for that: multi-test. However, I have discovered that:

  • if A is named myPackageA and B is named myPackageB, stack test fails; but
  • if A is named myPackageD and B is named myPackageC it passes.

That is, whether stack test fails or passes depends on the alphabetical ordering of the names of A and B.

When it fails, it fails with:

Error: [S-4804]
       Stack failed to construct a build plan.

       While constructing the build plan, Stack encountered the following errors:

       In the dependencies for myPackageB-0.0.0:
         * myPackageA dependency cycle detected: myPackageA, myPackageB, myPackageA
       The above is/are needed since myPackageB is a build target.

With A and B, stack --verbose --plan-in-log ... test includes:

[debug] Constructing the build plan
[debug] (addDep) Package info for myPackageA: PIOnlySource PSFilePath ...
[debug] (installPackage) No test or bench component for myPackageA so doing an all-in-one
[debug] (addDep) Package info for myPackageB: PIOnlySource PSFilePath ... 
[debug] (addDep) Package info for base: PIOnlyInstalled Snap ...
[debug] (checkCallStackAndAddDep) Detected cycle myPackageA: ["myPackageB","myPackageA"]
[debug] (getCachedDepOrAddDep) Using cached result for base: Right (ADRFound Snap ...
[debug] (installPackage) Before trying cyclic plan, resetting lib result map to: fromList []
[debug] (addDep) Package info for base: PIOnlyInstalled Snap ...
[debug] (getCachedDepOrAddDep) Using cached result for base: Right (ADRFound Snap ...
[debug] (checkCallStackAndAddDep) Detected cycle myPackageA: ["myPackageB","myPackageA"]
[debug] (getCachedDepOrAddDep) Using cached result for base: Right (ADRFound Snap ...
[debug] (getCachedDepOrAddDep) Using cached result for base: Right (ADRFound Snap ...
[debug] (getCachedDepOrAddDep) Using cached result for myPackageB: Right (ADRToInstall ... allInOne = False

With D and C, stack --verbose --plan-in-log ... test includes:

[debug] Constructing the build plan
[debug] (addDep) Package info for myPackageC: ...
[debug] (addDep) Package info for base: ...
[debug] (addDep) Package info for myPackageD: ...
[debug] (installPackage) No test or bench component for myPackageD so doing an all-in-one build.

[debug] (checkCallStackAndAddDep) Detected cycle myPackageC: ["myPackageD","myPackageC"]
[debug] (getCachedDepOrAddDep) Using cached result for base: ...
[debug] (getCachedDepOrAddDep) Using cached result for base: ...
[debug] (installPackage) Before trying cyclic plan, resetting lib result map to: fromList []
[debug] (addDep) Package info for base: ...
[debug] (getCachedDepOrAddDep) Using cached result for base: ...
[debug] (addDep) Package info for myPackageD: ...
[debug] (installPackage) No test or bench component for myPackageD so doing an all-in-one build.

[debug] (getCachedDepOrAddDep) Using cached result for myPackageC: ...
[debug] (getCachedDepOrAddDep) Using cached result for base: ...
[debug] (getCachedDepOrAddDep) Using cached result for base: ...
[debug] (getCachedDepOrAddDep) Using cached result for myPackageD: ...

This does not appear to be a recent regression. I think it may have been present since at least Stack 2.1.1.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions