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

document multiple-components workaround #322

Merged
merged 3 commits into from
Sep 13, 2024
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
1 change: 1 addition & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
# Integration and tips

- [Tasty](./integration/tasty.md)
- [Multiple Cabal components](./integration/multiple-components.md)
96 changes: 96 additions & 0 deletions docs/integration/multiple-components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Multiple Cabal components

Currently, multiple Cabal components don't work. You can work around this with
[the Cabal `test-dev` trick][test-dev] as described by the venerable Jade
Lovelace. This works by defining a new component in our `.cabal` file which
includes the sources from the library and the tests, which has the added
benefit of speeding up compile times by allowing the compilation of different
components to be interleaved.

[test-dev]: https://jade.fyi/blog/cabal-test-dev-trick/

You can [see this demonstrated in the ghciwatch test sources
here][test-dev-in-ghciwatch]. We define four components:

- `library`
- `tests`
- An internal `test-lib` library
- An internal `test-dev` library

[test-dev-in-ghciwatch]: https://github.com/MercuryTechnologies/ghciwatch/blob/93fbb67fba6abd3903596876394acf234cb9bdb2/tests/data/simple/package.yaml

Then, we can use a command like `cabal v2-repl test-dev` to run a GHCi session
containing both the library and test sources.

The `package.yaml` should look something like this:

```yaml
---
spec-version: 0.36.0
name: my-simple-package
version: 0.1.0.0

flags:
local-dev:
description: Turn on development settings, like auto-reload templates.
manual: true
default: false

library:
source-dirs: src

tests:
test:
main: Main.hs
source-dirs:
- test-main
ghc-options: -threaded -rtsopts -with-rtsopts=-N
when:
- condition: flag(local-dev)
then:
dependencies:
- test-dev
else:
dependencies:
- my-simple-package
- test-lib

internal-libraries:
test-lib:
source-dirs:
- test

test-dev:
source-dirs:
- test
- src
when:
- condition: flag(local-dev)
then:
buildable: true
else:
buildable: false
```

Then, we can set the `local-dev` flag in our `cabal.project.local`, so that we
use the `test-dev` target locally:

```cabal
package my-simple-package
flags: +local-dev
```


## haskell-language-server

Defining the `test-dev` component does tend to confuse
`haskell-language-server`, as a single file is now in multiple components. Fix
this by writing [an `hie.yaml`][hie-yaml] like this:

```yaml
cradle:
cabal:
component: test-dev
```

[hie-yaml]: https://haskell-language-server.readthedocs.io/en/stable/configuration.html#configuring-your-project-build