Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ Bug fixes:
* After March 2026, Hackage requires Stack's user agent to be set when applying
digest authentication to a request. Stack's `upload` command now does that,
re-establishing authentication by Hackage username and password.
* Stack 3.9.3 and earlier fail to construct a build plan if project package A
depends on project package B and package B's executables (only) depend on
package A and the name of A is before that of B, alphabetically. That bug is
fixed.

## v3.9.3 - 2026-02-19

Expand Down
8 changes: 7 additions & 1 deletion src/Stack/Build/ConstructPlan.hs
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,9 @@ addFinal ::
-> M ()
addFinal lp package allInOne buildHaddocks = do
let name = package.name
res <- addPackageDeps package >>= \case
logDebugPlanS "addFinal" "Clearing the call stack."
res <- local (\ctx' -> ctx' { callStack = [] }) $
addPackageDeps package >>= \case
Left e -> pure $ Left e
Right (MissingPresentDeps missing present _minLoc) -> do
let pkgConfigOpts = packageConfigureOptsFromPackage package
Expand All @@ -505,6 +507,10 @@ addFinal lp package allInOne buildHaddocks = do
, cachePkgSrc = CacheSrcLocal (toFilePath (parent lp.cabalFP))
, buildTypeConfig = packageBuildTypeConfig package
}
ctx <- ask
logDebugPlanS "addFinal" $
"Restoring the call stack: "
<> fromString (show $ map packageNameString ctx.callStack)
logDebugPlanS "addFinal" $
"Adding to construction output "
<> fromPackageName name
Expand Down
27 changes: 27 additions & 0 deletions tests/integration/tests/6905-cyclic-plan/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-- | The test's project has project packages A and B.
--
-- In terms of main libraries, the dependencies are (->- is 'depends on'):
--
-- A ->- B
--
-- In terms of executables (a test suite):
--
-- B ->- A
--
-- As, overall, A ->- B and B ->- A, packages A and B cannot be built
-- 'all-in-one'.
--
-- This integration test tests:
--
-- * when A is named myPackageA and B is named myPackageB; and
--
-- * when A is named myPackageD and B is named myPackageC.
--
-- See: https://github.com/commercialhaskell/stack/issues/6905

import StackTest

main :: IO ()
main = do
stack ["--stack-yaml", "stack1.yaml", "test"]
stack ["--stack-yaml", "stack2.yaml", "test"]
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
myPackageA.cabal
myPackageB.cabal
myPackageC.cabal
0myPackageB.cabal
myPackageD.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
spec-version: 0.36.0

name: myPackageA

dependencies:
- base

library:
source-dirs: src
dependencies:
- myPackageB
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module LibA
( funcB
) where

import LibB ( funcB )
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
spec-version: 0.36.0

# Only builds if this package name comes before myPackageA, alphabetically!
name: 0myPackageB
name: myPackageB

dependencies:
- base
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
spec-version: 0.36.0

name: myPackageC

dependencies:
- base

library:
source-dirs: src

tests:
test:
source-dirs: test
main: Main.hs
dependencies:
- myPackageD
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module LibC
( funcC
) where

funcC :: IO ()
funcC = pure ()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import LibD ( funcC )

main :: IO ()
main = funcC
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
spec-version: 0.36.0

name: myPackageD

dependencies:
- base

library:
source-dirs: src
dependencies:
- myPackageC
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module LibD
( funcC
) where

import LibC ( funcC )
5 changes: 5 additions & 0 deletions tests/integration/tests/6905-cyclic-plan/files/stack1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
snapshot: ghc-9.10.3

packages:
- myPackageA
- myPackageB
5 changes: 5 additions & 0 deletions tests/integration/tests/6905-cyclic-plan/files/stack2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
snapshot: ghc-9.10.3

packages:
- myPackageC
- myPackageD
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,18 @@
-- As, overall, A ->- B and B ->- A, packages A and B cannot be built
-- 'all-in-one'.
--
-- This integration test passes when A is named myPackageA and B is named
-- 0myPackageB, but it fails when B is renamed myPackageB. That must be a bug in
-- Stack.
-- A, B and C are named myPackageA, myPackageB and myPackageC respectively.
--
-- See: https://github.com/commercialhaskell/stack/issues/6905

import Control.Monad ( unless )
import Data.List ( isInfixOf )
import StackTest

main :: IO ()
main = do
-- FIXME: Make 'clean' unnecessary (see #1411)
stack ["clean"]
stackCheckStderr ["test", "--coverage"] $ \out -> do
unless ("The coverage report for myPackageA's test-suite test1 is available at" `isInfixOf` out) $
fail "Didn't get expected report for test1"
unless ("[S-6829]" `isInfixOf` out) $
fail "Didn't get expected empty report for test2"
-- Test then build works too.
stack ["clean"]
stack ["test"]
stack ["build"]
6 changes: 6 additions & 0 deletions tests/integration/tests/6905-multi-test/files/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
myPackageA.cabal
myPackageB.cabal
myPackageC.cabal
myPackageD.cabal
myPackageE.cabal
myPackageF.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ dependencies:
library:
source-dirs: src
dependencies:
# Only builds if this package name comes before myPackageA, alphabetically!
- 0myPackageB
- myPackageB

executables:
myExeA:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
spec-version: 0.36.0

name: myPackageB

dependencies:
- base

library:
source-dirs: src

tests:
test:
source-dirs: test
main: Main.hs
dependencies:
- myPackageA
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module LibB
( funcB
) where

funcB :: IO ()
funcB = pure ()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import LibA ( funcB )

main :: IO ()
main = funcB
Loading