Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build-type: Configure; package Cabal-syntax-3.8.1.0 conflicts with itself #6524

Closed
hasufell opened this issue Mar 16, 2024 · 20 comments
Closed

Comments

@hasufell
Copy link
Contributor

2024-03-16T10:34:46.0274820Z streamly                     > configure
2024-03-16T10:34:46.2895020Z streamly                     > [1 of 3] Compiling Main             ( /private/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/stack-885afe2bdf7374d4/streamly-0.8.3/Setup.hs, /private/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/stack-885afe2bdf7374d4/streamly-0.8.3/.stack-work/dist/x86_64-osx/ghc-9.4.8/setup/Main.o )
2024-03-16T10:34:46.4716440Z streamly                     > [2 of 3] Compiling StackSetupShim   ( /Users/runner/.stack/setup-exe-src/setup-shim-6HauvNHV.hs, /private/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/stack-885afe2bdf7374d4/streamly-0.8.3/.stack-work/dist/x86_64-osx/ghc-9.4.8/setup/StackSetupShim.o )
2024-03-16T10:34:46.4904380Z streamly                     > 
2024-03-16T10:34:46.4921290Z streamly                     > /Users/runner/.stack/setup-exe-src/setup-shim-6HauvNHV.hs:7:1: error:
2024-03-16T10:34:46.4940030Z streamly                     >     Ambiguous module name ‘Distribution.PackageDescription’:
2024-03-16T10:34:46.5010610Z streamly                     >       it was found in multiple packages:
2024-03-16T10:34:46.5072480Z streamly                     >       Cabal-syntax-3.8.1.0 Cabal-syntax-3.8.1.0
2024-03-16T10:34:46.5082300Z streamly                     >   |
2024-03-16T10:34:46.5123920Z streamly                     > 7 | import Distribution.PackageDescription (PackageDescription, emptyHookedBuildInfo)
2024-03-16T10:34:46.5212090Z streamly                     >   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

https://github.com/haskell/ghcup-hs/actions/runs/8307024100/job/22735795982

stack version 2.15.3

To reproduce:

  • git clone https://github.com/haskell/ghcup-hs.git
  • stack build

This seems to only happen on macOS (in CI).

@mpilgrem
Copy link
Member

@hasufell, the source code (src/setup-shim/StackSetupShim.hs) has:

{-# LANGUAGE CPP            #-}
{-# LANGUAGE PackageImports #-}
module StackSetupShim where
import Main
#if defined(MIN_VERSION_Cabal)
#if MIN_VERSION_Cabal(3,8,1)
import Distribution.PackageDescription (PackageDescription, emptyHookedBuildInfo)
#else
import "Cabal" Distribution.PackageDescription (PackageDescription, emptyHookedBuildInfo)
#endif
#else
import Distribution.PackageDescription (PackageDescription, emptyHookedBuildInfo)
#endif

I am wondering if I have the logic of the #if MIN_VERSION_Cabal(3,8,1) 'the wrong way around'. The history of this is at:

@hasufell
Copy link
Contributor Author

I'm not sure. It seems to be spurious. Sometimes the CI succeeds, sometimes not.

@mpilgrem
Copy link
Member

mpilgrem commented Mar 16, 2024

Some comments for my own use:

If the 'setup-exe' has not been cached, it is built with (for example, extracts, reformatted):

...\ghc-9.6.4\bin\ghc-9.6.4.exe 
-rtsopts 
-threaded 
-clear-package-db   # Clear the current package database stack
-global-package-db  # Add the global package database to the top of the current stack
-hide-all-packages  # All packages need to be explicitly exposed 
-package base 
-main-is StackSetupShim.mainOverride 
-package Cabal-3.10.1.0 
C:\sr\setup-exe-src\setup-9p6GVs8J.hs 
C:\sr\setup-exe-src\setup-shim-9p6GVs8J.hs 
-o C:\sr\setup-exe-cache\x86_64-windows\tmp-Cabal-simple_9p6GVs8J_3.10.1.0_ghc-9.6.4.exe

the -package Cabal-3.10.1.0 being the GHC boot package for the specified GHC. I think this can't be the problem, because all the packages are hidden from GHC except for base and Cabal.

However, there is also code in Stack.Build.ExecuteEnv.withSingleContext as part of withCabal (extract):

              runExe compilerPath $
                [ "--make"
                , "-odir", toFilePathNoTrailingSep setupDir
                , "-hidir", toFilePathNoTrailingSep setupDir
                , "-i", "-i."
                ] ++ packageArgs ++
                [ toFilePath setuphs
                , toFilePath ee.setupShimHs
                , "-main-is"
                , "StackSetupShim.mainOverride"
                , "-o", toFilePath outputFile
                , "-threaded"
                ] ++

                -- Apply GHC options
                -- https://github.com/commercialhaskell/stack/issues/4526
                map
                  T.unpack
                  ( Map.findWithDefault
                      []
                      AGOEverything
                      config.ghcOptionsByCat
                  ++ case config.applyGhcOptions of
                       AGOEverything -> ee.buildOptsCLI.ghcOptions
                       AGOTargets -> []
                       AGOLocals -> []
                  )

So, if I take the example given in 79e6134, one of the steps is (extracts, reformatted):

process     > configure
[debug] Run process within ...\process-1.6.15.0\: 
...\ghc-9.0.2\bin\ghc-9.0.2.exe 
--make 
-odir ...\process-1.6.15.0\.stack-work\dist\f972502b\setup
-hidir ...\process-1.6.15.0\.stack-work\dist\f972502b\setup
-i
-i.
-package=Cabal-3.4.1.0  # Expose this version of the Cabal package
-clear-package-db 
-global-package-db 
-package-db=C:\sr\snapshots\dfce5266\pkgdb 
...\process-1.6.15.0\Setup.hs
C:\sr\setup-exe-src\setup-shim-9p6GVs8J.hs 
-main-is StackSetupShim.mainOverride 
-o ...\process-1.6.15.0\.stack-work\dist\f972502b\setup\setup
-threaded 
-haddock
...
[info] process     > [2 of 2] Compiling StackSetupShim ...
[info] process     > Linking ...\process-1.6.15.0\.stack-work\dist\f972502b\setup\setup.exe ...

At the end of the build, the package database C:\sr\snapshots\dfce5266\pkgdb contains the packages specified as extra-deps: Cabal-3.8.1.0-9FYtgyN7c9W8mwkFl4FEqj.conf, Cabal-syntax-3.8.1.0-CC9Bfx5CE7X4XpP9arS2OL.conf, process-1.6.15.0-DsrkIC2fIQkBJadX1qo1Db.conf.

@mpilgrem
Copy link
Member

mpilgrem commented Mar 16, 2024

@hasufell, an odd thing about your error message:

2024-03-16T10:34:46.4940030Z streamly >     Ambiguous module name ‘Distribution.PackageDescription’:
2024-03-16T10:34:46.5010610Z streamly >       it was found in multiple packages:
2024-03-16T10:34:46.5072480Z streamly >       Cabal-syntax-3.8.1.0 Cabal-syntax-3.8.1.0

is that it is referring to the same package identifier Cabal-syntax-3.8.1.0 twice.

Back when I was experiencing ambiguity, it was between different packages:

process >     Ambiguous module name ‘Distribution.PackageDescription’:
process >       it was found in multiple packages:
process >       Cabal-3.4.1.0 Cabal-syntax-3.8.1.0

EDIT: I think that is the problem (the same two package identifiers, 'conflicting with itself') not the source code for the shim.

@mpilgrem
Copy link
Member

I think the logic of my:

#if MIN_VERSION_Cabal(3,8,1)
import Distribution.PackageDescription (PackageDescription, emptyHookedBuildInfo)
#else
import "Cabal" Distribution.PackageDescription (PackageDescription, emptyHookedBuildInfo)
#endif

was that (a) with Cabal >= 3.8.1 GHC knew how to handle the clash of module names between Cabal and Cabal-syntax but (b) Cabal < 3.8.1 did not - so "Cabal" had to be specified expressly.

The GHC-supplied Cabal-3.8.1.0.conf includes:

exposed-modules:
    ...
    Distribution.PackageDescription from Cabal-syntax-3.8.1.0:Distribution.PackageDescription,
    ...

@mpilgrem mpilgrem changed the title Ambiguous module name ‘Distribution.PackageDescription’ in setup-shim Package Cabal-syntax-3.8.1.0 somehow conflicting with itself Mar 16, 2024
@mpilgrem mpilgrem self-assigned this Mar 16, 2024
@mpilgrem
Copy link
Member

As indicated, I could not reproduce on Windows 11. The snapshot is lts-21.25 (GHC 9.4.8, which comes with Cabal-3.8.1.0 and Cabal-syntax-3.8.1.0). Cabal-3.8.1.0 and Cabal-syntax-3.8.1.0 are also specified as extra-deps (presumably because other GHC boot packages have been overridden), which explains why they are built anyway.

I wonder if package shadowing is not occurring as it should for GHC 9.4.8 on macOS?

@mpilgrem
Copy link
Member

On Windows 11, using stack --verbose build streamly, the call to GHC has the form above:

Run process within ...\streamly-0.8.3\: 
...\ghc-9.4.8\bin\ghc-9.4.8.exe
--make
-odir ...\streamly-0.8.3\.stack-work\dist\f1a1ac53\setup 
-hidir ...\streamly-0.8.3\.stack-work\dist\f1a1ac53\setup 
-i 
-i. 
-package=Cabal-3.8.1.0 
-clear-package-db 
-global-package-db 
-package-db=C:\sr\snapshots\612a4b31\pkgdb 
...\streamly-0.8.3\Setup.hs 
C:\sr\setup-exe-src\setup-shim-9p6GVs8J.hs 
-main-is StackSetupShim.mainOverride 
-o ...\streamly-0.8.3\.stack-work\dist\f1a1ac53\setup\setup 
-threaded 
-haddock

@mpilgrem
Copy link
Member

mpilgrem commented Mar 16, 2024

An observation:

Returning to my 79e6134 example:

The GHC-supplied Cabal-3.8.1.0.conf has (extract):

...
id:                   Cabal-3.8.1.0
...
abi:                  c52458c52981c7dfb414e1264fc98757
...
exposed-modules:
    ...
    Distribution.PackageDescription from Cabal-syntax-3.8.1.0:Distribution.PackageDescription,
    ...

but the extra-dep Cabal-3.8.1.0-9FYtgyN7c9W8mwkFl4FEqj.conf has (extract):

...
id:                   Cabal-3.8.1.0-9FYtgyN7c9W8mwkFl4FEqj
...
abi:                  d42177acfcf8b8f3b778fbe4e0cfa473
...
exposed-modules:
    ...
    Distribution.PackageDescription from Cabal-syntax-3.8.1.0-CC9Bfx5CE7X4XpP9arS2OL:Distribution.PackageDescription,

Could something like that, somehow, result in GHC 9.4.8 thinking two Cabal-syntax-3.8.1.0 are in play on macOS?

@mpilgrem
Copy link
Member

The GHC 9.4.8 Users Guide has:

Package shadowing: When multiple package databases are in use it is possible, though rarely, that the same installed package id is present in more than one database. In that case, packages closer to the top of the stack will override (shadow) those below them. If the conflicting packages are found to be equivalent (by ABI hash comparison) then one of them replaces all references to the other, otherwise the overridden package and all those depending on it will be removed.

Package version selection: When selecting a package, GHC will search for packages in all available databases. If multiple versions of the same package are available the latest non-broken version will be chosen.

Version conflict resolution: If multiple instances of a package version chosen by GHC are available then GHC will choose an unspecified instance.

It is not clear to me if "the same installed package id is present" refers to (a) the id field of the *.conf file or (b) the package identifier in Cabal terms (eg Cabal-3.8.1.0).

@mpilgrem
Copy link
Member

@hasufell, I have switched to macOS/AArch64, and I can't reproduce the problem locally on that platform either. I am using the master branch version of Stack, but nothing important should have changed since Stack 2.15.3.

@mpilgrem
Copy link
Member

Another observation:

The streamly library does not depend on Cabal but it has build-type: Configure.

At the point in @hasufell's CI run where the build fails at streamly > configure, the extra-dep Cabal-syntax has been built and registered (at 2024-03-16T10:34:18.3802200Z) but the extra-dep Cabal has not yet been built.

In my local build which works, the extra-dep Cabal-syntax has not yet been built when the streamly > configure begins.

This likely difference in the contents of the snapshot package database at the relevant time may explain why the problem is intermittent.

@mpilgrem
Copy link
Member

mpilgrem commented Mar 16, 2024

That (the explanation for intermittent failure) seems to be it: locally, if I delete the snapshot package database and start afresh with the example, but in two steps:

stack build Cabal-syntax
stack build streamly

the build fails (with dependency network) with:

network            > configure
network            > [1 of 3] Compiling Main             ( /private/var/folders/zp/dkvy_dtj31x04x3hcc29wp_00000gn/T/stack-a76fc1f394248344/network-3.1.4.0/Setup.hs, /private/var/folders/zp/dkvy_dtj31x04x3hcc29wp_00000gn/T/stack-a76fc1f394248344/network-3.1.4.0/.stack-work/dist/aarch64-osx/ghc-9.4.8/setup/Main.o )
network            > [2 of 3] Compiling StackSetupShim   ( /Users/mpilgrem/.stack/setup-exe-src/setup-shim-6HauvNHV.hs, /private/var/folders/zp/dkvy_dtj31x04x3hcc29wp_00000gn/T/stack-a76fc1f394248344/network-3.1.4.0/.stack-work/dist/aarch64-osx/ghc-9.4.8/setup/StackSetupShim.o )
network            >
network            > /Users/mpilgrem/.stack/setup-exe-src/setup-shim-6HauvNHV.hs:7:1: error:
network            >     Ambiguous module name ‘Distribution.PackageDescription’:
network            >       it was found in multiple packages:
network            >       Cabal-syntax-3.8.1.0 Cabal-syntax-3.8.1.0
network            >   |
network            > 7 | import Distribution.PackageDescription (PackageDescription, emptyHookedBuildInfo)
network            >   |

EDIT: This applies on OS other than macOS - it applies to Windows 11, for example.

@mpilgrem
Copy link
Member

mpilgrem commented Mar 16, 2024

I am looking at the Nothing branch of the getPackageArgs part of withCabal of withSingleContext. The code documentation states:

-- This branch is usually taken for builds, and is always taken
-- for `stack sdist`.
--
-- This approach is debatable. It adds access to the snapshot
-- package database for Cabal. There are two possible objections:
--
-- 1. This doesn't isolate the build enough; arbitrary other
-- packages available could cause the build to succeed or fail.
--
-- 2. This doesn't provide enough packages: we should also
-- include the local database when building local packages.
--
-- Currently, this branch is only taken via `stack sdist` or when
-- explicitly requested in the stack.yaml file.

What @hasufell is experiencing seems to me to be an instance of objection No. 1 in the code comment. I am wondering: for build-type: Configure should the approach to the build (in terms of package databases) of the 'setup-exe' be as for Simple? The only difference between them is the presence and running of a configure shell script.

EDIT: I am going to try that solution in a pull request.

@mpilgrem mpilgrem changed the title Package Cabal-syntax-3.8.1.0 somehow conflicting with itself build-type: Configure; package Cabal-syntax-3.8.1.0 conflicts with itself Mar 16, 2024
mpilgrem added a commit that referenced this issue Mar 17, 2024
@mpilgrem
Copy link
Member

@hasufell, in summary, you have uncovered a long-standing bug in Stack that affects the build of packages with build-type: Configure and an extra-dep Cabal-syntax, if the extra-dep happens to be registered before (a) an extra-dep Cabal is registered and (b) Stack compiles the setup executable.

I think I have a fix (#6526) and an ugly work-around in the interim. The work-around is to build the extra-dep Cabal before the rest of the build:

stack build Cabal
stack build

@hasufell
Copy link
Contributor Author

Great investigation. I'll check your branch out later and maybe run it through CI.

@mpilgrem
Copy link
Member

@hasufell, if you could run it through CI, that would be much appreciated. I am planning on releasing a Stack 2.15.5 soon (because of https://discourse.haskell.org/t/ann-stacks-default-source-for-list-of-stackage-snapshots-not-up-to-date/9023) and it would be good if I could include the resolution of this as part of that release.

@hasufell
Copy link
Contributor Author

@mpilgrem maybe we do a pre-release, that would make it easier?

@mpilgrem
Copy link
Member

I've no objection to a pre-release. I may make the exposure period shorter than the usual fortnight, given the nature of the 'new URL' fix.

mpilgrem added a commit that referenced this issue Mar 20, 2024
Fix #6524 Exclude snapshot package DB for `build-type: Configure`
mpilgrem added a commit that referenced this issue Mar 20, 2024
@hasufell
Copy link
Contributor Author

haskell/ghcup-hs#1031

I'll try to trigger it a couple times to see if it fails again

@hasufell
Copy link
Contributor Author

I have not been able to re-trigger the failure with the pre-release after 4 runs: https://github.com/haskell/ghcup-hs/actions/runs/8378001994?pr=1031

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants