How to avoid duplicate builds for modules in a 'common' stanza across components?

My cabal package originally had this structure:

- lib
  - Foo.App.*
  - Foo.Lib.*
- exeuctables
  - bar-exe
  - baz-exe
  - ...

I wanted to prevent the modules in Foo.App from being built with the library, as they are only used by executables. I restructured it like this:

- lib
  - Foo.Lib.*
- common app-deps
  - Foo.App.*
- exeuctables
  - bar-exe (import app-deps)
  - baz-exe (import app-deps)
  - ...

However, this seems to be causing the modules in Foo.App to be built twice - once during the bar-exe build and once during baz-exe build. I’m inferring this from the significantly increased build time and multiple GHC processes that appear when using the new layout.

Additionally, there are many FromJSON/ToJSON instance derivations from aeson in Foo.App.*. I believe this is causing instance resolution to occur for each executable build.

How can I prevent this duplication while maintaining the separation of concerns between library and executable-specific code?

1 Like

Try hosting the Foo.App modules in a sub-library upon which your other components may then depend.

4 Likes

Thanks! I didn’t know sub-library exists.

1 Like

I’m surprised Cabal doesn’t warn about this. There’s a lot that doesn’t work very well when a module is used in two places.

Then again, in my ideal world, there’d just be a single directory per component, and no need to explicitly list modules at all.

4 Likes