I have a fresh installation of stack and ghci:
$ stack --version
Version 1.6.3, Git revision b27e629b8c4ce369e3b8273f04db193b060000db (5454 commits) x86_64 hpack-0.20.0
$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 8.2.1
I make a new project:
$ stack new so-mve
Downloading template "new-template" to create project "so-mve" in so-mve/
... blah blah blah ...
Looking for .cabal or package.yaml files to use to init the project.
Using cabal packages:
- so-mve/
Selecting the best among 12 snapshots...
* Matches lts-10.3
Selected resolver: lts-10.3
Initialising configuration using resolver: lts-10.3
Total number of user packages considered: 1
Writing configuration to file: so-mve/stack.yaml
All done.
Looks pretty good:
$ tree so-mve
so-mve
├── ChangeLog.md
├── LICENSE
├── README.md
├── Setup.hs
├── app
│ └── Main.hs
├── package.yaml
├── so-mve.cabal
├── src
│ └── Lib.hs
├── stack.yaml
└── test
└── Spec.hs
It builds and runs:
$ cd so-mve
$ stack build
so-mve-0.1.0.0: build (lib + exe)
Preprocessing library for so-mve-0.1.0.0..
Building library for so-mve-0.1.0.0..
Preprocessing executable 'so-mve-exe' for so-mve-0.1.0.0..
Building executable 'so-mve-exe' for so-mve-0.1.0.0..
so-mve-0.1.0.0: copy/register
Installing library in /...blah-blah.../so-mve/.stack-work/install/x86_64-osx/lts-10.3/8.2.2/lib/x86_64-osx-ghc-8.2.2/so-mve-0.1.0.0-5kG2WnHWwo99IiYYGoxrcC
Installing executable so-mve-exe in /...blah-blah.../so-mve/.stack-work/install/x86_64-osx/lts-10.3/8.2.2/bin
Registering library for so-mve-0.1.0.0..
$ stack exec so-mve-exe
someFunc
Tests run:
$ stack test
blah blah blah
[2 of 2] Compiling Main ( test/Spec.hs, .stack-work/dist/x86_64-osx/Cabal-2.0.1.0/build/so-mve-test/so-mve-test-tmp/Main.o )
...blah-blah-blah...
Progress: 1/2Test suite not yet implemented
so-mve-0.1.0.0: Test suite so-mve-test passed
Completed 2 action(s).
I triple check that HUnit is installed
$ stack install HUnit
Populated index cache.
I add one line to test/Spec.hs
$ cat test/Spec.hs
import Test.HUnit
main :: IO ()
main = putStrLn "Test suite not yet implemented"
Doesn't work:
$ stack test
so-mve-0.1.0.0: unregistering (components added: test:so-mve-test)
so-mve-0.1.0.0: build (lib + exe + test)
Preprocessing library for so-mve-0.1.0.0..
Building library for so-mve-0.1.0.0..
Preprocessing executable 'so-mve-exe' for so-mve-0.1.0.0..
Building executable 'so-mve-exe' for so-mve-0.1.0.0..
Preprocessing test suite 'so-mve-test' for so-mve-0.1.0.0..
Building test suite 'so-mve-test' for so-mve-0.1.0.0..
[2 of 2] Compiling Main ( test/Spec.hs, .stack-work/dist/x86_64-osx/Cabal-2.0.1.0/build/so-mve-test/so-mve-test-tmp/Main.o )
/...blah-blah.../so-mve/test/Spec.hs:1:1: error:
Could not find module ‘Test.HUnit’
Use -v to see a list of the files searched for.
|
1 | import Test.HUnit
| ^^^^^^^^^^^^^^^^^
Progress: 1/2
-- While building custom Setup.hs for package so-mve-0.1.0.0 using:
/Users/XXXXXXXX/.stack/setup-exe-cache/x86_64-osx/Cabal-simple_mPHDZzAJ_2.0.1.0_ghc-8.2.2 --builddir=.stack-work/dist/x86_64-osx/Cabal-2.0.1.0 build lib:so-mve exe:so-mve-exe test:so-mve-test --ghc-options " -ddump-hi -ddump-to-file -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
I don't have trouble importing other libraries, like Text.Read and Text.Printf.
I googled around a bunch, but didn't find an answer. Any ideas for me?
You just need to add HUnit to the dependencies for your test project. When using stack, you should edit the package.yaml file to specify dependencies. In particular, your test configuration should look something like:
tests:
so-mve-test:
main: Spec.hs
source-dirs: test
ghc-options:
- ...
dependencies:
- HUnit
This is documented in the latest Stack Guide, under the section Adding Dependencies.
You installed HUnit globally with stack, but that doesn't mean it is specified for your project.
Your cabal file for the project needs to specify a dependency on HUnit:
--so-mve.cabal
...
test-suite so-mve
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, HUnit
...
Text.Read and Text.Printf are both included in base, so you don't need to specify an additional dependency.
As pointed out in the comments, since you're using a package.yaml (as opposed to a stack.yaml) configuration with the newer version of stack, you'll need to specify the dependency there instead of the .cabal file:
tests:
so-mve-test:
main: Spec.hs
source-dirs: test
ghc-options:
- -threaded
dependencies:
- HUnit
Related
Full reproducible project here: https://github.com/chrissound/215
I have the following simple cabal file which defines:
a library (source under src-lib)
executable (source under src) in the same project (which depends on the above local library)
cabal-version: 1.12
name: HaskellNixCabalStarter
version: 0.1.0.0
author: HaskellNixCabalStarter
maintainer: HaskellNixCabalStarter
license: MIT
build-type: Simple
library
exposed-modules:
Hello
other-modules:
Paths_HaskellNixCabalStarter
hs-source-dirs:
src-lib
build-depends:
base >=4.12 && <4.13
default-language: Haskell2010
executable app
main-is: Main.hs
other-modules:
Paths_HaskellNixCabalStarter
hs-source-dirs:
src
build-depends:
HaskellNixCabalStarter
, base >=4.12 && <4.13
default-language: Haskell2010
I can open a GHCi repl with:
cabal v2-repl app
However, upon GHCi reloading (:r), it will only reload changes in the app executable, and disregard any changes in the library.
This seems like very limiting / incorrect behavior. How can I fix this / workaround this?
There is a workaround, you either
run cabal repl and then :load src/Main.hs, or
with cabal repl app you'd need to :load src/Main.hs src-lib/Hello.hs.
Now :reload also reloads changes from dependencies.
In the first case it's the :load that somehow also starts loading/following the dependencies. (Not sure why cabal repl app isn't doing exactly the same.)
On the second case you need to explicitly name the modules you want to follow. Also, you need to have the module in who's namespace you want to be in, first. So :load src/Main.hs ..others...
See this on reddit. It appears that cabal can only have one "unit" loaded, but loading other sources with :load seems to subvert that.
I don't think it can be done (yet?). Evidence:
jeff#jbb-dell:cabal-experim$ tree
.
├── cabal.project
├── P1
│ ├── app
│ │ ├── Lib.hs
│ │ └── Main.hs
│ └── P1.cabal
└── P2
├── P2.cabal
└── src
└── MyLib.hs
jeff#jbb-dell:cabal-experim$ cabal repl P1 P2
cabal: Cannot open a repl for multiple components at once. The targets 'P1'
and 'P2' refer to different components.
The reason for this limitation is that current versions of ghci do not support
loading multiple components as source. Load just one component and when you
make changes to a dependent component then quit and reload.
I use stack and a package.yaml file for hpack to compile my haskell project. It has three executables backed by one library. As one would expect the executables are all defining a Main module:
$ head -n1 app/*
==> app/Foo.hs <==
module Main where
==> app/Bar.hs <==
module Main where
==> app/Baz.hs <==
module Main where
And I use this package.yaml which looks very similar (to me) to the one linked from the official docs for hpack (the third one).
name: myproject
dependencies:
- base
library:
source-dirs: src
executables:
foo:
main: Foo.hs
source-dirs: app
dependencies: myproject
bar:
main: Bar.hs
source-dirs: app
dependencies: myproject
baz:
main: Baz.hs
source-dirs: app
dependencies: myproject
But when I stack build I get the error, that the module name does not match
the file name:
Building all executables for `myproject' once. After a successful build of all of them, only specified executables will be rebuilt.
myproject-0.0.0: build (lib + exe)
Preprocessing library for myproject-0.0.0..
Building library for myproject-0.0.0..
[1 of 2] Compiling Lib ( src/Lib.hs, .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.2.0.1/build/Lib.o )
[2 of 2] Compiling Paths_myproject ( .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.2.0.1/build/autogen/Paths_myproject.hs, .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.2.0.1/build/Paths_myproject.o )
Preprocessing executable 'bar' for myproject-0.0.0..
Building executable 'bar' for myproject-0.0.0..
/home/luc/test/app/Baz.hs:1:8: error:
File name does not match module name:
Saw: ‘Main’
Expected: ‘Baz’
|
1 | module Main where
| ^^^^
-- While building package myproject-0.0.0 using:
/home/luc/.stack/setup-exe-cache/x86_64-linux-tinfo6/Cabal-simple_mPHDZzAJ_2.2.0.1_ghc-8.4.4 --builddir=.stack-work/dist/x86_64-linux-tinfo6/Cabal-2.2.0.1 build lib:myproject exe:bar exe:baz exe:foo --ghc-options " -ddump-hi -ddump-to-file -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
The only difference between my setup and the example that I found was the capital letters of the files in app/. And indeed, if I change them to lower case (in the filesystem and the package.yaml) it all builds correctly.
But why is that and where is that documented?
I think app should not be considered as a convention to be a folder of all final applications. In my projects I always split these to foo/Main.hs and bar/Main.hs for foo and bar targets. Hence
package.yaml should contain
executables:
foo:
main: Main.hs
source-dirs: foo
dependencies:
- myproject
bar:
main: Main.hs
source-dirs: bar
dependencies:
- myproject
And treat myproject just as a library for them
Given the following directory structure:
root
├── scripts
│ └── script1.hs
└── source
├── librarymodule.hs
└── libraryconfig.txt
Where "librarymodule.hs" would be a library exporting multiple functions, where the output is influenced by the contents of the libraryconfig.txt file in his directory.
script1.hs is the file needing to use the functions declared in librarymodule.hs.
I can't find a solution on the internet for a structure as given above and hoped someone could help out.
GHC has a -i option. Under root/scripts/, this will add root/source/ to the search path:
ghc -i../source script1.hs
Also consider packaging your library using cabal so you can install it and use it anywhere without worrying about paths.
Here is a minimal example of a library with data-files:
source/
├── mylibrary.cabal
├── LibraryModule.hs
└── libraryconfig.txt
mylibrary.cabal
name: mylibrary
version: 0.0.1
build-type: Simple
cabal-version: >= 1.10
data-files: libraryconfig.txt
library
exposed-modules: LibraryModule
other-modules: Paths_mylibrary
build-depends: base
default-language: Haskell2010
LibraryModule.hs
module LibraryModule where
import Paths_mylibrary -- This module will be generated by cabal
-- Some function that uses the data-file
printConfig :: IO ()
printConfig = do
n <- getDataFileName "libraryconfig.txt"
-- Paths_mylibrary.getDataFileName resolves paths for files associated with mylibrary
c <- readFile n
print c
See this link for information about the Paths_* module: https://www.haskell.org/cabal/users-guide/developing-packages.html#accessing-data-files-from-package-code
Now running cabal install should install mylibrary.
Then, under scripts/script1.hs, you can just run ghc script1.hs, using the library you installed.
Haskell beginner here.
I am struggling to find a nice way to run my test-suites that I have defined in my .cabal file. Given that you add test-suite sections in the .cabal file I would expect that you can run all of them with a single command like stack runtests.
The best answer I found is this one:
Haskell Stack Ghci test-suite suggesting that you have to run
stack ghci --test module:test:libtests
However, there are two things that irritate me and I think that there must be a better way doing it.
It is cumbersome to call stack ghci --test module:test:libtests explicitly. I don't want to do that if I have more test-suites when projects get larger.
Even worse, I end up in an interactive session and have to call main myself. This does not scale.
Isn't there a better way to run your test-suites for a project in stack? Of course I could do some shell scripting, but hey stack should know how to run my tests, I specified everything in the .cabal file.
I tried stack runghc --test but that doesn't help.
Project setup:
.
├── app
│ └── Main.hs
├── LICENSE
├── README.md
├── Setup.hs
├── src
│ ├── Lib.hs
│ └── WordNumber.hs
├── stack.yaml
├── test
│ └── Spec.hs
└── WordNumber.cabal
WordNumber.cabal
name: WordNumber
version: 0.1.0.0
-- synopsis:
-- description:
homepage: https://github.com/githubuser/WordNumber#readme
license: BSD3
license-file: LICENSE
author: Author name here
maintainer: example#example.com
copyright: 2017 Author name here
category: Web
build-type: Simple
extra-source-files: README.md
cabal-version: >=1.10
library
hs-source-dirs: src
exposed-modules: Lib, WordNumber
build-depends: base >= 4.7 && < 5
default-language: Haskell2010
executable wordnumber
hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, WordNumber
default-language: Haskell2010
test-suite wordnumber-test
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, WordNumber
, hspec
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010
Update:
Actually I feel a bit stupid for not finding the answer myself. It is either stack test or stack build --test and also documented.
However, for people following the HaskellBook it might not be that obvious. For some reason all tests in the testing chapter are executed in the cumbersome way and running tests with stack test is never mentioned.
stack test runs tests located in a .cabal file. It runs stack build if required, so you don't need to build manually before testing.
See further: https://docs.haskellstack.org/en/stable/GUIDE/#stack-test
I try to generate documentation for my executable using cabal haddock. My project structure looks like this:
~/.../project_name
project_name.cabal
Setup.hs
src/
Main.hs
Data/
...
test/
MainTestSuite
...
When I run cabal haddock --executable it fails with the following error message:
module ‘projects-0.1.0.0:Main’ is defined in multiple files: dist/build/tmp-8215/src/Main.hs
dist/build/tmp-8215/./Setup.hs
The Source.hs file has these contents:
import Distribution.Simple
main = defaultMain
The ghc Version is 7.8.3 and the haddock version is 2.14.3.