I have a directory structure like this
.
├── Main.hs
├── mynot.cabal
├── Notification.hs
└── Server.hs
where mynot.cabal
looks like this
cabal-version: 3.0
name: mynot
version: 0.1.0.0
common common
default-language: GHC2021
build-depends: base
executable mynot
import: common
main-is: Main.hs
build-depends: dbus
, async
, containers
, extra
, flow
other-modules: Server
, Notification
library server
import: common
exposed-modules: Server
build-depends: async
, containers
, dbus
, extra
, flow
other-modules: Notification
library notification
import: common
exposed-modules: Notification
build-depends: containers
, dbus
, extra
but extra
is really only needed by Notification.hs
, and I have no clue why I need to list it also under the other stanzas for cabal build
to succeed.
I found this, and gave it a try, e.g via
$ mkdir exe
$ mv Main.hs exe/.
and then adding hs-source-dirs: exe
in the executable
stanza, but the build fails like this
Resolving dependencies...
Build profile: -w ghc-9.4.8 -O1
In order, the following will be built (use -v for more details):
- mynot-0.1.0.0 (exe:mynot) (configuration changed)
- mynot-0.1.0.0 (lib:notification) (configuration changed)
- mynot-0.1.0.0 (lib:server) (configuration changed)
Configuring executable 'mynot' for mynot-0.1.0.0..
Configuring library 'notification' for mynot-0.1.0.0..
Configuring library 'server' for mynot-0.1.0.0..
Preprocessing library 'notification' for mynot-0.1.0.0..
Building library 'notification' for mynot-0.1.0.0..
Preprocessing executable 'mynot' for mynot-0.1.0.0..
Error: cabal-3.10.2.1: can't find source for Server in exe,
/home/enrico/mynot/dist-newstyle/build/x86_64-linux/ghc-9.4.8/mynot-0.1.0.0/x/mynot/build/mynot/autogen,
/home/enrico/mynot/dist-newstyle/build/x86_64-linux/ghc-9.4.8/mynot-0.1.0.0/x/mynot/build/global-autogen
Preprocessing library 'server' for mynot-0.1.0.0..
Building library 'server' for mynot-0.1.0.0..
Error: cabal: Failed to build exe:mynot from mynot-0.1.0.0.
Is something wrong with my project or just something missing in it?
When you use a different hs-source-dirs
then that will also influence where cabal will look for the other-modules
.
Instead of using other-modules
like that, you should add the components to each others build-depends
like this:
executable mynot
import: common
main-is: Main.hs
build-depends: dbus
, async
, containers
, flow
, mynot:server
, mynot:notification
hs-source-dirs: exe
library server
import: common
exposed-modules: Server
build-depends: async
, containers
, dbus
, flow
, mynot:notification
hs-source-dirs: server
library notification
import: common
exposed-modules: Notification
build-depends: containers
, dbus
, extra
hs-source-dirs: notification
And you do apparently need to create directories for each component, so the file structure should look like this:
.
├── exe/Main.hs
├── mynot.cabal
├── notification/Notification.hs
└── server/Server.hs
Of course you can use different names for the directories if you change the hs-source-dirs
fields too.
Generally, you want each module to be listed in only a single component. Otherwise each component will rebuild that module separately.