Cabal-3.12.0.0 passes include dirs to GHC in a new order
- Dominant language
- Haskell
- Stars
- 1.7k
- Forks
- 750
- Avg merge
- 4d 3h
- Merged PRs (30d)
- 28
Description
A full reproducer with analysis is at https://github.com/andreasabel/bug-cabal-3.12-setup .
I noticed this issue when using ghc-9.10.1 for the first time to build Agda using `cabal v1-install`. The Agda parser was malfunctioning. Turned out I had a stale `Lexer.hs` next to my `Lexer.x`, and this would be used when building with ghc-9.10 but not when building with ghc-9.8. After some hours I traced the problem down to the version of the `Cabal` library shipped with these GHCs.
## In short
Cabal-3.12 passes the include directories to GHC in a different order than Cabal-3.10. Cabal-3.10 puts `dist/build` before the `hs-source-dirs` whereas Cabal-3.12 does it the other way round. This leads GHC to pick up a different `.hs` file:
- In case of `Cabal-3.10` the one generated by the build-tool.
- In case of `Cabal-3.12` the one sitting in the source tree.
The problem is reproduced in a GitHub workflow run here: https://github.com/andreasabel/bug-cabal-3.12-setup/actions/runs/9291884301 . Passes with GHC 9.8, fails with GHC 9.10, independent of the version of `cabal-install`.
## Full description
It follows a longer description copied from https://github.com/andreasabel/bug-cabal-3.12-setup/blob/61cdad9444a3b13e2b833e1dde36019c4a31f782/README.md
__Cabal-3.12 passes include dirs in wrong order to GHC__
Conditions:
- GHC 9.10
- `cabal v1-install`
- custom setup (can be default `Setup.hs`), so that `Cabal-3.12` is used
- building a `library` (not just an `executable`)
- using a build-tool: we use `happy` here to shadow a `.hs` file by a `.y` file
- `hs-source-dirs` is not `.` but e.g. `src`
Files:
- `fred.cabal` with
* `build-type: Custom`
* `library` with `hs-source-dirs: src` (in particular not `.`)
- `Setup.hs` (standard)
- `src/Fred.y`: processed by `happy`
- `src/Fred.hs`: stale code that should be shadowed by `Fred.y` always
In this setting `cabal v1-install` malfunctions if `ghc` is `ghc-9.10.1`. (Works with older GHCs.)
It picks up `src/Fred.hs` instead of `dist/build/Fred.hs` that is created by `happy` from `src/Fred.y`.
Looking at the verbose output `cabal v1-install -v3`, we notice a difference in the call to `ghc` when the GHC is 9.10.1.
- GHC 9.10 / Cabal-3.12
/usr/local/bin/ghc --make -fbuilding-cabal-package \
...
-isrc -idist/build \
... \
Fred
[1 of 2] Compiling Main ( Fred.hs, dist/build/Main.o, ...
- GHC 9.8 / Cabal-3.10
/usr/local/bin/ghc --make -fbuilding-cabal-package \
... \
-idist/build -isrc \
... \
Fred
[1 of 1] Compiling Parser ( dist/build/Parser.hs, ... )
When building with GHC 9.8, library `Cabal-3.10` is used which places the path `dist/build` with the generated files correctly before the path `.` of the source files; but with GHC 9.10, library `Cabal-3.12` is used which does it the other way.
Full calls:
- GHC 9.10 / Cabal-3.12
/usr/local/bin/ghc --make -fbuilding-cabal-package -O -static -dynamic-too -dynosuf dyn_o -dynhisuf dyn_hi \
-outputdir dist/build -odir dist/build -hidir dist/build \
-hiedir dist/build/extra-compilation-artifacts/hie \
-stubdir dist/build -i \
-i. -idist/build \
-idist/build/autogen -idist/build/global-autogen \
-Idist/build/autogen -Idist/build/global-autogen -Idist/build \
-I/usr/local/opt/icu4c/include -I/usr/local/opt/libxml2/include/libxml2 \
-optP-include -optPdist/build/autogen/cabal_macros.h \
-this-unit-id stale-0-Ly26ql3fYpuLnJ9xynYGbf \
-hide-all-packages -Wmissing-home-modules -package-db dist/package.conf.inplace \
-package-id array-0.5.7.0-2002 -package-id base-4.20.0.0-8a80 \
-XHaskell2010 \
Fred
[1 of 2] Compiling Main ( Fred.hs, dist/build/Main.o, ...
- GHC 9.8 / Cabal-3.10
/usr/local/bin/ghc --make -fbuilding-cabal-package -O -static -dynamic-too -dynosuf dyn_o -dynhisuf dyn_hi \
-outputdir dist/build -odir dist/build -hidir dist/build \
-stubdir dist/build -i \
-idist/build -i. \
-idist/build/autogen -idist/build/global-autogen \
-Idist/build/autogen -Idist/build/global-autogen -Idist/build \
-I/usr/local/opt/icu4c/include -I/usr/local/opt/libxml2/include/libxml2 \
-optP-include -optPdist/build/autogen/cabal_macros.h \
-this-unit-id stale-0-F795SeGwWezHPbPW8onWYj \
-hide-all-packages -Wmissing-home-modules -package-db dist/package.conf.inplace \
-package-id array-0.5.6.0-28ee -package-id base-4.19.1.0-654f \
-XHaskell2010 \
Fred
[1 of 1] Compiling Parser ( dist/build/Parser.hs, ... )
Contributor guide
Research direction
Start with the linked reproducer and its README, then inspect fred.cabal, Setup.hs, src/Fred.y, and the stale src/Fred.hs. Run the GitHub Actions reproduction with GHC 9.8 and 9.10 using cabal v1-install, and compare the verbose GHC include-directory ordering; done means the generated file is selected consistently in the reported library setup.
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
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100