Cabal: N executables without building all the modules N times?

Hi libraries@, (Let me know if there's a better place for Cabal questions. This list is linked from https://www.haskell.org/cabal/ as a place to ask questions.) I have a project with lots of modules, and lots of executables that use those modules. How should I structure my .cabal file if I want cabal to only build the common modules once? I have found I can do it as follows, but I am wondering if there's a way to do it without step 1: 1. Create a "library_src" directory with the source for all the shared modules. Put the source files for the executables somewhere else. 2. Create a .cabal file with one "library" stanza with "hs-source-dirs: library_source", and several executable stanzas. If I leave out step 1 and put all the source files in the same place, then the compiler builds them separately for each executable, and I get a "missing-home-modules" warning. Is it just a fact of life that I need to separate my source into separate directories if I want this to work properly? Here's a small example, with four files, where I left out step 1 (i.e. put everything in the same directory). It does not behave the way I want it to: it builds the Library module three times if I run "cabal v2-build" and "cabal v2-test", and it shows the "missing-home-modules" warning. It also still builds if I remove "mhm" from build-depends of the executable and test-suite; I'd rather it failed to build if I did that. mhm.cabal: cabal-version: 2.2 name: mhm version: 0 library exposed-modules: Library default-language: Haskell2010 build-depends: base >=4.12 && <4.13 executable e main-is: e.hs build-depends: mhm, base >=4.12 && <4.13 default-language: Haskell2010 test-suite t type: exitcode-stdio-1.0 main-is: t.hs build-depends: mhm, base >=4.12 && <4.13 default-language: Haskell2010 Library.hs: module Library where n :: Int n = 5 e.hs: module Main where import Library main = print n t.hs: module Main where import Library main = print n

Hey James, yes, if you want to avoid duplicate compilation, you need to define a `library` with a separate `hs-source-dirs` and use that library in the `build-depends` of your executables. See https://stackoverflow.com/questions/12305970/how-to-make-a-haskell-cabal-pro... and the linked question. Cheers, Niklas

On 2020-08-10 22:35, Niklas Hambüchen wrote:
Hey James,
yes, if you want to avoid duplicate compilation, you need to define a `library` with a separate `hs-source-dirs` and use that library in the `build-depends` of your executables.
See
https://stackoverflow.com/questions/12305970/how-to-make-a-haskell-cabal-pro...
and the linked question.
Cheers, Niklas
Thanks! That's exactly the information I was looking for. I guess I did not use the right search terms. -- James

On Mon, 10 Aug 2020, James Cook wrote:
Hi libraries@,
(Let me know if there's a better place for Cabal questions. This list is linked from https://www.haskell.org/cabal/ as a place to ask questions.)
I have a project with lots of modules, and lots of executables that use those modules. How should I structure my .cabal file if I want cabal to only build the common modules once?
I have found I can do it as follows, but I am wondering if there's a way to do it without step 1:
1. Create a "library_src" directory with the source for all the shared modules. Put the source files for the executables somewhere else.
2. Create a .cabal file with one "library" stanza with "hs-source-dirs: library_source", and several executable stanzas.
I use to setup directory 'src' for the library, 'test' for test code and, say, 'example' for executables.
If I leave out step 1 and put all the source files in the same place, then the compiler builds them separately for each executable, and I get a "missing-home-modules" warning.
Is it just a fact of life that I need to separate my source into separate directories if I want this to work properly?
Yes. Problem is, that Cabal calls GHC's 'make' feature and that one searches for appropriate modules in its search path. Btw. you give a Library section a name you get a private sub-library of private modules that can be shared between the public library and e.g. the test suite.
participants (3)
-
Henning Thielemann
-
James Cook
-
Niklas Hambüchen