cabal.project's optional-packages are too eager
- Dominant language
- Haskell
- Stars
- 1.7k
- Forks
- 750
- Avg merge
- 4d 3h
- Merged PRs (30d)
- 28
Description
I tried using an `optional-packages` stanza in a `cabal.project` file recently, but it did not work according to the expectations laid out in the documentation. The documentation says:
```rst
.. cfg-field:: optional-packages: package location list (space or comma-separated)
:synopsis: Optional project packages.
:default: ``./*/*.cabal``
Like :cfg-field:`packages`, specifies a list of package locations
containing local packages to be built. Unlike :cfg-field:`packages`,
if we glob for a package, it is permissible for the glob to match against
zero packages. The intended use-case for :cfg-field:`optional-packages`
is to make it so that vendored packages can be automatically picked up if
they are placed in a subdirectory, but not error if there aren't any.
```
I was excited by this description, since it would fit a use case I have perfectly. However, when I actually tried using it in [this minimal example](https://github.com/RyanGlScott/cabal-optional-project-bug), I discovered that it didn't quite behave like "automatically picked up if they are placed in a subdirectory, but not error if there aren't any" would lead me to believe.
The example I have is a repo with a submodule (`IHaskell/ipython-kernel`) that doesn't work yet with GHC 8.2 (due to upper version bounds on `base`). However, no other `.cabal` file in the project actually depends on `ipython-kernel`, so naturally, I placed it in `optional-packages`, since I didn't want `cabal new-build` to actually build `ipython-kernel` when building the main package itself. However, as you can see here:
```
$ git clone --recursive https://github.com/RyanGlScott/cabal-optional-project-bug
$ cd cabal-optional-project-bug/
$ cabal new-build . --dry-run
Resolving dependencies...
cabal: Could not resolve dependencies:
trying: base-4.10.0.0/installed-4.1... (dependency of
cabal-optional-project-bug-0.1)
next goal: zeromq4-haskell (dependency of ipython-kernel-0.8.4.0)
rejecting: zeromq4-haskell-0.6.7, zeromq4-haskell-0.6.6,
zeromq4-haskell-0.6.5, zeromq4-haskell-0.6.4, zeromq4-haskell-0.6.3,
zeromq4-haskell-0.6.2, zeromq4-haskell-0.6.1, zeromq4-haskell-0.6,
zeromq4-haskell-0.5.1, zeromq4-haskell-0.5, zeromq4-haskell-0.4.1,
zeromq4-haskell-0.4, zeromq4-haskell-0.3.2, zeromq4-haskell-0.3.1,
zeromq4-haskell-0.3 (conflict: requires pkg-config package libzmq>=4.0 &&
<5.0, not found in the pkg-config database)
trying: zeromq4-haskell-0.2
next goal: async (dependency of zeromq4-haskell-0.2)
rejecting: async-2.1.1.1, async-2.1.1, async-2.1.0 (conflict: zeromq4-haskell
=> async==2.0.*)
rejecting: async-2.0.2 (conflict: base==4.10.0.0/installed-4.1..., async =>
base>=4.3 && <4.9)
rejecting: async-2.0.1.6, async-2.0.1.5 (conflict:
base==4.10.0.0/installed-4.1..., async => base>=4.3 && <4.8)
rejecting: async-2.0.1.4, async-2.0.1.3 (conflict:
base==4.10.0.0/installed-4.1..., async => base>=4.3 && <4.7)
rejecting: async-2.0.1.2, async-2.0.1.1, async-2.0.1.0, async-2.0.0.0
(conflict: base==4.10.0.0/installed-4.1..., async => base>=4.3 && <4.6)
rejecting: async-1.4, async-1.3, async-1.2, async-1.1, async-1.0 (conflict:
zeromq4-haskell => async==2.0.*)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: base, zeromq4-haskell, async,
ipython-kernel, cabal-optional-project-bug
```
`cabal new-build` still attempts to build `ipython-kernel`, even though it's sequestered off into `optional-packages`! This effectively prevents me from doing anything with this project using `cabal new-build` unless I manually scrub `ipython-kernel` from `optional-packages` in the `cabal.project` file.
I'd request that `cabal new-build` not attempt to build `ipython-kernel` unless the main package itself depends on it (which it doesn't, in this example).
Contributor guide
Assessment
This issue has not been assessed yet.