Can you have an executable and library in the same cabal package - haskell

I'm new using cabal and I need my package to include a small executable as well as the whole library.
Is it possible to do so (to export an executable AND a library) or does a cabal package have a type (executable OR binary).
Is it also possible to export many executable in the same packagke ?

Yes you can. For example, here is the corresponding excerpt of the HaskellStarter project, that I highly recommend:
-- configuration for building a library
library
hs-source-dirs: src
exposed-modules:
HaskellStarter.CommitPrinter
other-modules:
HaskellStarter.Util
build-depends:
base >= 4 && < 5,
github >= 0.7.4 && < 0.8
-- configuration for an executable
executable githubCommitPrinter
hs-source-dirs: executables
main-is: Main.hs
build-depends:
base >= 4 && < 5,
haskell-starter
Notice how the library is reused in the executable dependencies.

Related

Cabal: How to configure transitive build-dependencies in the same project

I have a cabal project. It has library and test targets.
Test target depends on library because it tests the library's functionalities.
The problem is, whenever I add a package dependency to library (say, cryptohash-sha1)
library Lib
exposed-modules: Lib
other-extensions: DeriveGeneric
build-depends: base >=4.13 && <4.14,
cryptohash-sha1,
and run the test, I get error
Could not load module ‘Crypto.Hash.SHA1’.
It is a member of the hidden package ‘cryptohash-sha1-0.11.100.1’.
Perhaps you need to add ‘cryptohash-sha1’ to the build-depends in your .cabal file
What I do in this situation is to add the same package to test target
test-suite json-generator-test
hs-source-dirs: test, src
main-is: Test.hs
other-modules: Lib
build-depends: base >=4.13 && <4.14
cryptohash-sha1,
Only then the test would run.
I want test target to automatically depend on all the packages from library target. How can I do that?
You can use a cabal feature called common stanzas. You can read more about it in the following blog post:
https://vrom911.github.io/blog/common-stanzas
With this approach, you can put all common dependencies in a separate stanza, and just import it in both the library and test suite:
common common-dependencies
build-depends: base >=4.13 && <4.14
, cryptohash-sha1
library Lib
import: common-dependencies
exposed-modules: Lib
other-extensions: DeriveGeneric
test-suite json-generator-test
import: common-dependencies
hs-source-dirs: test, src
main-is: Test.hs
other-modules: Lib

How to make Stack only build one executable? stack build :exe1 doesn't work?

I have multiple executables in one of my Stack projects:
executable m1
hs-source-dirs: src
main-is: Main1.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
executable m2
hs-source-dirs: src
main-is: Main2.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
I would like to build only one of them at a time. From the documentation and this other question, it would seem that the following command should work:
stack build :m2
but what actually happens is that both executables, m1 and m2, are always built regardless of whether I include the package name, the package type, etc.
What could be causing this?
It's not possible at the moment. See https://github.com/commercialhaskell/stack/issues/1406

Shared cabal "build-depends" (Haskell) [duplicate]

Here's a .cabal file:
Name: myprogram
Version: 0.1
-- blah blah blah
Cabal-version: >=1.9.2
Executable myprogram
HS-source-dirs: src
Main-is: Main.hs
Build-depends: attoparsec == 0.10.*,
base == 4.3.*,
-- long long list of packages
Test-Suite test
HS-source-dirs: test, src
Type: exitcode-stdio-1.0
Main-is: Main.hs
Build-depends: attoparsec == 0.10.*,
base == 4.3.*,
-- long long list of packages
QuickCheck == 2.4.*
Is there any way I can replace the long list of build-depends packages for the test suite with "same as for the executable, plus QuickCheck"?
Edit: version information.
cabal-dev 0.9
cabal-install 0.10.2
Cabal library 1.10.2.0
GHC 7.0.4
Haskell Platform 2011.4.0.0
NOTE: superseded by phadej's answer suggesting common stanzas.
Is there any way I can replace the long list of build-depends packages for the test suite with "same as for the executable, plus QuickCheck"?
Not that I know of. However, there is a way to only mention the list of build-depends packages once, by structuring your project into three targets:
a library that contains all your code, and needs the long build-depends list.
an executable that consists of only one file, and depends on base and the library from above.
a test-suite that depends on the library from above, and the testing packages you are using.
Maybe this approach is what indygemma's answer proposes, but the Cabal file proposed there will not quite achieve it, as Norman Ramsey points out in a comment. Here's the main points of what you need in a Cabal file. For a full example that works for me, you can look at this Cabal file.
name: my-program
version: ...
library
hs-source-dirs: src-lib
build-depends: base, containers, ...
exposed-modules: My.Program.Main, ...
executable my-program
hs-source-dirs: src-exec
main-is: my-program.hs
Build-depends: base, my-program
test-suite tests
type: exitcode-stdio-1.0
hs-source-dirs: src-test
main-is: tests.hs
other-modules: ...
build-depends: base, my-program, test-framework, ...
Important points:
There are three separate source directories for the three targets. This is necessary to stop GHC from recompiling library files when building the other targets.
All of the application code is in the library. The executable is just a wrapper, like this:
import My.Program.Main (realMain)
main = realMain
The library exposes all modules that are necessary for testing.
The last point highlights the drawback of this approach: You end up having to expose internal modules. The main benefit of this approach is that you have less duplication in the Cabal file, and maybe more importantly, less duplication in the build process: The library code will be built only once, and then linked into both the executable and the test-suite.
Since version 2.2 Cabal supports common stanzas, to dedup build info fields:
https://cabal.readthedocs.io/en/latest/developing-packages.html#common-stanzas
cabal-version: 2.2
name: myprogram
version: 0.1
-- blah blah blah
common deps
build-depends: base ^>= 4.11,
-- long long list of packages
ghc-options: -Wall
library
import: deps
exposed-modules: Foo
test-suite tests
import: deps
type: exitcode-stdio-1.0
main-is: Tests.hs
build-depends: foo
You could also consider using hpack instead of writing the .cabal file by hand:
In hpack's package.yaml format, you can specify a common dependencies field whose entries are added to every components' build-depends field when generating the .cabal file.
For example, see hpack's own package.yaml and the generated hpack.cabal.
To start using hpack with an existing package, you can use hpack-convert which will generate the package.yaml from an existing .cabal file.
To create a new package that uses hpack, you can use stack's simple-hpack template like so: stack new mypkg simple-hpack.
If you use stack for development, you don't have to call hpack manually to regenerate the .cabal file from an updated package.yaml – stack will do that automatically.
No easy way:
you can use m4 and specify your dependencies once, but then you will need to reprocess your Cabal file through m4 whenever you change it.
you can move the code you are testing out to a library, and then specify the library in your Build-depends for the test. That requires you to install a library even just to run the test.
You can just not put the test in the cabal file at all. Build it with ghc --make, which will pull in dependencies. But then you lose cabal integration.
There is an optional library section for .cabal files, which solves your problem.
name: myprogram
version: 0.1
-- blah blah blah
cabal-version: >=1.9.2
library
build-depends: attoparsec == 0.10.*
, base == 4.3.*
-- long long list of packages
executable myprogram
hs-source-dirs: src
main-is: Main.hs
test-suite test
hs-source-dirs: test, src
type: exitcode-stdio-1.0
main-is: Main.hs
build-depends: QuickCheck == 2.4.*

Variable in Cabal (Haskell)

I am trying to write a package in Haskell. This package contains a library and an executable. I am specifying this in the Cabal file. There are three basic components of the library:
1) There are the exposed modules of the library
2) There are internal build-dependencies that should not be exported as part of the library
3) There are external build-dependencies.
There is a bit of overlap in the Cabal file. For the library I write:
exposed-modules: The List of Exposed Modules
other-modules: The List of other modules
build-depends: The List of build dependencies
Then for the executable
other-modules: The list of exposed modules and other modules are needed in the executable
build-depends: The list of build dependencies
What would be nice is if Cabal lets me have a variable.
V1 = List exposed modules
V2 = List other modules
V3 = List build dependencies
Then in the executable, for example, I could do
other-modules: V1,V2
build-depends: V3
Alternatively, I would take a recommendation for a better way to use the Cabal system!
No, this is not possible yet. I think we have a feature request for something like this on the issue tracker somewhere. Note, however, that your executable can depend on the library defined in the same .cabal file, so you don't have to share exposed-modules and other-modules:
Name: some-package
Version: 0.1
[...]
Library
build-depends: some-dependency >= 1.0, ...
exposed-modules: A, B, C
other-modules: C, D, E
[...]
Executable some-exe
main-is: SomeExe.hs
build-depends: some-package == 0.1
For a real-world example, see here.

How to avoid recompiling in this cabal file?

I've been working on this Haskell project, and I have a cabal file for it. Now, my project is structured as a library that implements a simple interpreter. I also have a very short Main file which needs to be build into an executable to call the library. What I want to do is:
1) compile the library and expose some of the modules
2) compile the executable
I have a cabal file that works and seems to do this. The problem is that when it compiles the executable it recompiles all the modules which have already been compiled in step (1). I don't quite understand why it does this - is there any way to stop it, short of creating two separate cabal files?
I don't really want to create two separate cabal files, because cabal doesn't seem to like having both the cabal files in the same directory, and I don't really want to set up a separate project directory for the second step, since it basically just amounts to compiling a single file.
cabal-version: >= 1.6
build-type: Simple
name: HaSC
version: 0.2.3
license: OtherLicense
category: Language
author: Chris B
maintainer: Chris B
copyright: Chris B 2010 - 2011
synopsis: (HA)skell (S)ound (C)hange applier (HaSC) library
description: HaSC implements a little language for applying sound changes to words
homepage: http://www.chrisdb.me.uk/redmine/projects/haskell-sound-change
stability: Alpha
data-files: doc/HaSCDoc.pdf
license-file: LICENSE
library
build-depends:
base >= 4.3,
containers >= 0.3,
parsec >= 3,
parallel >= 3.1,
deepseq >= 1.1,
mtl >= 1.1,
transformers >= 0.2,
text >= 0.10,
text-icu >= 0.6.3,
pretty >= 1,
directory >= 1.1,
filepath >= 1.2
hs-source-dirs: src
exposed-modules: HaSC.IO.Disk,
HaSC.IO.Memory,
HaSC.Exec
other-modules: HaSC.AST,
HaSC.IO,
HaSC.IdentMap,
HaSC.Parse,
HaSC.Regex,
HaSC.Representation,
HaSC.Transformations,
HaSC.Search,
HaSC.State
executable HaSC
GHC-Options: -rtsopts
hs-source-dirs: src
main-is: Main.hs
In your executable section, add the library in Build-Depends so that the executable depends on the library.
There's a small gotcha, though: You also have to move the Main.hs of the executable (and any other source files specific to the executable) to a different subdirectory and specify a different Hs-Source-Dirs so that it doesn't pick up the library modules by being in the same folder.
executable HaSC
Build-Depends: HaSC
Main-Is: Main.hs
Hs-Source-Dirs: foo -- Directory you moved Main.hs to
For this to work, you will need to specify Cabal-Version >= 1.8. See Cabal ticket #89 for the details.

Resources