haskell / haskell/cabal

cabalSpecLatest remains 3.16 in cabal-install 3.18.1.0, causing cabal-version: 3.18 Simple packages to fail

Open
#12,271 4 comments 1 reaction 0 assignees View on GitHub
attention: needs-backport 3.18 attention: pr-welcome regression in 3.18 type: bug
Dominant language
Haskell
Stars
1.7k
Forks
750
Avg merge
4d 3h
Merged PRs (30d)
28

Description

## Describe the bug

Cabal-syntax 3.18.1.0 defines and parses `CabalSpecV3_18`. However, `cabalSpecLatest` remains `CabalSpecV3_16`.

This mismatch changes the behaviour of cabal-install. `packageSetupScriptStyle` treats any non-`Custom`, non-`Hooks` package above `cabalSpecLatest` as a future-format package.

A normal package with `cabal-version: 3.18` therefore receives `SetupNonCustomExternalLib`, not `SetupNonCustomInternalLib`.

For example, this expression returns `SetupNonCustomExternalLib`:

```haskell
packageSetupScriptStyle
(emptyPackageDescription {specVersion = CabalSpecV3_18})
```

The expected result is `SetupNonCustomInternalLib`. cabal-install 3.18.1.0 links against a Cabal library that supports specification 3.18.

Explicit `.cabal` parsing recognises `cabal-version: 3.18`. The problem is the stale default and code that uses it as the supported-version boundary.

## To reproduce

Use cabal-install 3.18.1.0:

```console
$ cabal --version
cabal-install version 3.18.1.0
compiled using version 3.18.1.0 of the Cabal library
```

Create `repro.cabal`:

```cabal
cabal-version: 3.18
name: repro
version: 0.1.0.0
build-type: Simple

executable repro
main-is: Main.hs
build-depends: base
default-language: Haskell2010
```

Create `Main.hs`:

```haskell
main :: IO ()
main = putStrLn "ok"
```

Use an empty setup-executable cache. An existing cache entry can otherwise hide the problem.

```console
setup_cache=$(mktemp -d)

XDG_CACHE_HOME="$setup_cache" cabal build --dry-run
# Succeeds

XDG_CACHE_HOME="$setup_cache" cabal build
# Fails
```

The failure starts approximately as follows:

```text
[1 of 2] Compiling Main (.../setup/setup.hs, .../setup/Main.o)

setup/setup.hs:2:1: error:
Could not load module ‘Distribution.Simple’.
It is a member of the hidden package ‘Cabal-...’.
```

The failing `Main` module is the generated setup wrapper, not the package's `Main.hs`.

## Expected behaviour

The full build must succeed.

A `Simple` package with `cabal-version: 3.18` must use `SetupNonCustomInternalLib` in cabal-install 3.18.1.0.

## What happens internally

1. The release recognizes `CabalSpecV3_18`, but `cabalSpecLatest` remains `CabalSpecV3_16`.
2. `packageSetupScriptStyle` therefore classifies the package as `SetupNonCustomExternalLib`.
3. `mkDefaultSetupDeps` computes an implicit dependency on `Cabal >= 3.17`.
4. `setImplicitSetupInfo` materializes implicit setup information only for `Custom` and `Hooks`.
5. It therefore discards the computed dependency for the `Simple` package.
6. The solver sees no setup dependency, so `--dry-run` succeeds.
7. The elaborated plan nevertheless retains `SetupNonCustomExternalLib`.
8. During execution, cabal compiles the generated `Setup.hs` with an empty exclusive dependency set.
9. The generated setup wrapper cannot import `Distribution.Simple`, so the build fails.

Change only the declared specification version:

```diff
-cabal-version: 3.18
+cabal-version: 3.16
```

The full build then succeeds.

## Proposed fix

- Publish a Cabal-syntax 3.18 patch release with:

```haskell
cabalSpecLatest = CabalSpecV3_18
```

- Publish a cabal-install patch release with binaries built against the corrected Cabal-syntax release.

The 3.18 release branch must advance only to `CabalSpecV3_18`.

Current master also defines `CabalSpecV3_20` and contains features gated by it. The corresponding change on master must advance `cabalSpecLatest` to `CabalSpecV3_20`.

Contributor guide

Open the contributing guide

Research direction

Start by locating cabalSpecLatest, packageSetupScriptStyle, and the CabalSpecV3_18 definitions in the Cabal and cabal-install sources. Reproduce the issue with the provided cabal-version: 3.18 package and empty setup cache, then add regression coverage showing that it uses SetupNonCustomInternalLib and that the full build succeeds. Verify the release branch stops at CabalSpecV3_18 and current master uses CabalSpecV3_20.

Written by the indexing model from the issue text.

Assessment

Tech stack
haskell
Domain
build-system
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.