Maintaining test-suite dependencies with cabal

Dear reader, I have a single executable package in Cabal[1] and I have added a test for it using an example configuration from the ltc package[2]. With my test on my executable I can't depend on the main package, but I seem to have to repeat the dependencies of my executable, or split off functionality into a library. [3] Can I easily depend on the dependencies of another package or should I create a library and depend on that in my test and executable? All source is at: https://github.com/bneijt/after/ Greetings, Bram [1] https://github.com/bneijt/after/blob/master/after.cabal [2] https://github.com/scvalex/ltc/blob/master/ltc.cabal [3] A part of my cabal file added below executable after main-is: Main.hs build-depends: base >=4.7 && <4.8, options ==1.*, directory ==1.2.*, parallel-io ==0.3.*, filepath ==1.3.*, unix ==2.7.* hs-source-dirs: src ghc-options: -Wall default-language: Haskell2010 test-suite afterTests hs-source-dirs: test src main-is: AfterTest.hs type: exitcode-stdio-1.0 build-depends: base >=4.7 && <4.8, unix ==2.7.*, -- Here because of after depending on it directory ==1.2.*, -- Here because of after depending on it filepath ==1.3.*, -- Here because of after depending on it test-framework, test-framework-hunit, HUnit default-language: Haskell2010

I have found that splitting functionality off into a library is way too
useful for a lot of things anyway, so I'd just do that.
On Aug 22, 2014 6:49 PM, "Bram Neijt"
Dear reader,
I have a single executable package in Cabal[1] and I have added a test for it using an example configuration from the ltc package[2].
With my test on my executable I can't depend on the main package, but I seem to have to repeat the dependencies of my executable, or split off functionality into a library. [3]
Can I easily depend on the dependencies of another package or should I create a library and depend on that in my test and executable?
All source is at: https://github.com/bneijt/after/
Greetings,
Bram
[1] https://github.com/bneijt/after/blob/master/after.cabal [2] https://github.com/scvalex/ltc/blob/master/ltc.cabal [3] A part of my cabal file added below
executable after main-is: Main.hs build-depends: base >=4.7 && <4.8, options ==1.*, directory ==1.2.*, parallel-io ==0.3.*, filepath ==1.3.*, unix ==2.7.* hs-source-dirs: src ghc-options: -Wall default-language: Haskell2010
test-suite afterTests hs-source-dirs: test src main-is: AfterTest.hs type: exitcode-stdio-1.0 build-depends: base >=4.7 && <4.8, unix ==2.7.*, -- Here because of after depending on it directory ==1.2.*, -- Here because of after depending on it filepath ==1.3.*, -- Here because of after depending on it test-framework, test-framework-hunit, HUnit default-language: Haskell2010 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On 08/22/2014 06:03 PM, Tobias Dammers wrote:
I have found that splitting functionality off into a library is way too useful for a lot of things anyway, so I'd just do that. On Aug 22, 2014 6:49 PM, "Bram Neijt"
wrote: Dear reader,
I have a single executable package in Cabal[1] and I have added a test for it using an example configuration from the ltc package[2].
With my test on my executable I can't depend on the main package, but I seem to have to repeat the dependencies of my executable, or split off functionality into a library. [3]
Can I easily depend on the dependencies of another package or should I create a library and depend on that in my test and executable?
All source is at: https://github.com/bneijt/after/
Greetings,
Bram [snip]
+1 to this, just stick it into a library section. You can even have your executable be just ‘main = realMain’ and everything else (including realMain) in the library. There's a benefit of someone being able to come along and go ‘hey, this program does these useful things, I sure could use some of them for my own program’ which is great. -- Mateusz K.

On Fri, Aug 22, 2014 at 12:49 PM, Bram Neijt
Can I easily depend on the dependencies of another package or should I create a library and depend on that in my test and executable?
There's no way to do what you're trying to do without putting your functionality into a library. Cabal then has a feature that allows you to depend on the library in your executables and test suites. Then you don't repeat your library dependencies in your executables and test suites. This feature has, however, some unresolved bugs: https://github.com/haskell/cabal/issues/1919 so I wouldn't recommend its use unless you are willing to deal with some bugs. I would just gulp and deal with the duplication in your Cabal file (and the longer compile times) or, alternatively, adopt a tool to deal directly with the problem of duplication, such as: https://hackage.haskell.org/package/cartel But a tool like Cartel does nothing about compile times. If compile times are really a concern, I would just put the library in a completely separate package and package the executables and tests separately.

On Fri, Aug 22, 2014 at 10:22 AM, Omari Norman
But a tool like Cartel does nothing about compile times. If compile times are really a concern, I would just put the library in a completely separate package and package the executables and tests separately.
One way to help reduce compile times (a bit anyway) is to separate the executables and tests into parallel source directories from your library code. I generally use a layout like this: <project dir>/ - project.cabal - src/ - apps/ - tests/resources/ - tests/src/ Library code goes in src, application Main's go in apps/, test source goes in tests/src/ and any necessary data files go in tests/resources. Then tests and apps defined in the cabal file depend on the library, and the source for the library is not rebuilt for each executable/test declaration in the cabal file (generally speaking; with flags and custom builds you can cause just about anything...) --Rogan

I have split up my dependencies and placed them in separate
directories. This was all pretty easy to do, however I do have one
thing I don't understand.
My Main.hs[1] includes: import After (afterPartialCmdline, afterPid)
And my after.cabal[2] has a library exposing the After module.
It looks like me that Main.hs only uses functions from After, however
if I don't list "Process" in the "exposed-modules:" I get a linker
error:
Linking dist/build/after/after ...
/home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.text+0x90a):
undefined reference to `afterzm0zi1zi2zi0_Process_psCmdLine4_closure'
/home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.text+0x945):
undefined reference to `afterzm0zi1zi2zi0_Process_psListing2_closure'
/home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.text+0x4a3):
undefined reference to `afterzm0zi1zi2zi0_Process_psCmdLine1_info'
/home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.text+0x6ca):
undefined reference to `afterzm0zi1zi2zi0_Process_psCmdLine1_info'
/home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.data+0xf0):
undefined reference to `afterzm0zi1zi2zi0_Process_psCmdLine1_closure'
/home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.data+0x108):
undefined reference to `afterzm0zi1zi2zi0_Process_psListing2_closure'
/home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.data+0x118):
undefined reference to `afterzm0zi1zi2zi0_Process_psCmdLine4_closure'
collect2: error: ld returned 1 exit status
Why do I have to mention "Process" in the exposed modules list?
Doesn't this mean that I eventuall have to mention all my modules in
the exposed modules list, and then what is the point of having to
mention them in the first place?
Greetings,
Bram
[1] https://github.com/bneijt/after/blob/master/src/main/Main.hs
[2] https://github.com/bneijt/after/blob/master/after.cabal
On Thu, Sep 4, 2014 at 10:36 PM, Rogan Creswick
On Fri, Aug 22, 2014 at 10:22 AM, Omari Norman
wrote: But a tool like Cartel does nothing about compile times. If compile times are really a concern, I would just put the library in a completely separate package and package the executables and tests separately.
One way to help reduce compile times (a bit anyway) is to separate the executables and tests into parallel source directories from your library code. I generally use a layout like this:
<project dir>/ - project.cabal - src/ - apps/ - tests/resources/ - tests/src/
Library code goes in src, application Main's go in apps/, test source goes in tests/src/ and any necessary data files go in tests/resources.
Then tests and apps defined in the cabal file depend on the library, and the source for the library is not rebuilt for each executable/test declaration in the cabal file (generally speaking; with flags and custom builds you can cause just about anything...)
--Rogan

You shoud list 'Process' in the 'other-modules' section of your
library. Every module should be either in the exposed or other modules
list. Ideally cabal would check this for you, see
https://github.com/haskell/cabal/pull/1455
Regards,
Erik
On Sat, Sep 6, 2014 at 12:19 PM, Bram Neijt
I have split up my dependencies and placed them in separate directories. This was all pretty easy to do, however I do have one thing I don't understand.
My Main.hs[1] includes: import After (afterPartialCmdline, afterPid) And my after.cabal[2] has a library exposing the After module.
It looks like me that Main.hs only uses functions from After, however if I don't list "Process" in the "exposed-modules:" I get a linker error:
Linking dist/build/after/after ... /home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.text+0x90a): undefined reference to `afterzm0zi1zi2zi0_Process_psCmdLine4_closure' /home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.text+0x945): undefined reference to `afterzm0zi1zi2zi0_Process_psListing2_closure' /home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.text+0x4a3): undefined reference to `afterzm0zi1zi2zi0_Process_psCmdLine1_info' /home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.text+0x6ca): undefined reference to `afterzm0zi1zi2zi0_Process_psCmdLine1_info' /home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.data+0xf0): undefined reference to `afterzm0zi1zi2zi0_Process_psCmdLine1_closure' /home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.data+0x108): undefined reference to `afterzm0zi1zi2zi0_Process_psListing2_closure' /home/bram/program/after/dist/build/libHSafter-0.1.2.0.a(After.o):(.data+0x118): undefined reference to `afterzm0zi1zi2zi0_Process_psCmdLine4_closure' collect2: error: ld returned 1 exit status
Why do I have to mention "Process" in the exposed modules list?
Doesn't this mean that I eventuall have to mention all my modules in the exposed modules list, and then what is the point of having to mention them in the first place?
Greetings,
Bram
[1] https://github.com/bneijt/after/blob/master/src/main/Main.hs [2] https://github.com/bneijt/after/blob/master/after.cabal
On Thu, Sep 4, 2014 at 10:36 PM, Rogan Creswick
wrote: On Fri, Aug 22, 2014 at 10:22 AM, Omari Norman
wrote: But a tool like Cartel does nothing about compile times. If compile times are really a concern, I would just put the library in a completely separate package and package the executables and tests separately.
One way to help reduce compile times (a bit anyway) is to separate the executables and tests into parallel source directories from your library code. I generally use a layout like this:
<project dir>/ - project.cabal - src/ - apps/ - tests/resources/ - tests/src/
Library code goes in src, application Main's go in apps/, test source goes in tests/src/ and any necessary data files go in tests/resources.
Then tests and apps defined in the cabal file depend on the library, and the source for the library is not rebuilt for each executable/test declaration in the cabal file (generally speaking; with flags and custom builds you can cause just about anything...)
--Rogan
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (6)
-
Bram Neijt
-
Erik Hesselink
-
Mateusz Kowalczyk
-
Omari Norman
-
Rogan Creswick
-
Tobias Dammers