My project structure is as follows:
~/.../project_name
project_name.cabal
Setup.hs
src/
Main.hs
Data/
...
test/
MainTestSuite
...
I have (amongst others) the following lines in my project.cabal:
build-type: Simple
...
executable project_name
main-is: Main.hs
...
hs-source-dirs: src
When I cabal configure (works fine) and then cabal build I get the error message:
cabal: can't find source for Setup in src, dist/build/autogen
It works when I put Source.hs in src but this seems messy to me and I haven't seen this in other projects, where Source.hs is always in the project root. How do I get cabal to find Source.hs?
As an aside: What's the purpose of Source.hs anyways?
The problem was caused by accidently adding the Source file as a dependency in other-modules in the cabal-file of the project ... that caused all the trouble.
hs-source-dirs: ., src comes to mind as a fast fix.
That's what my projects use, and I generate my cabal files automatically (so I suppose that's the default).
Related
I want to create an sdist package for my Haskell project.
For simplicity let's assume the following project structure:
/ root
| src
| MyLib.hs
| test
| MyLibTest.hs
| Changelog.md
| MyProject.cabal
| LICENSE
There are two targets defined in the cabal file
library
exposed-modules: MyLib
hs-source-dirs: src
-- ...
test-suite: MyProject-test
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: MyLibTest.hs
-- ...
When I execute cabal new-sdist --list-only I get the following list:
./changelog.md
./MyProject.cabal
./LICENSE
./src/MyLib.hs
./test/MyLibTest.hs
My question: is it ok to include the test-related files in the sdist package or shall I remove them (if so - how)?
Well if you try to generate a library-only sdist, you get this error:
$ cabal new-sdist --list-only <library-name>
cabal: The component library cannot be packaged for distribution on its own.
Only entire packages may be packaged for distribution.
So I'd say it's recommended to upload the whole thing.
Hackage does let you preview a library before publishing it, using package candidates. I'd say upload your source tarball as a package candidate, and double check your tests don't show up.
This bugs me time and again, basically if I create a test-suite in the cabal configuration I add the projects src folder to the test suites hs-source-dirs section and repeat all dependencies in build-depends. A typical project might look like:
-- in file "foo.cabal"
library
build-depends: a, b, c
exposed-modules: Foo, Bar
hs-source-dirs: src
test-suite tests
build-depends: foo, a, b, c
hs-source-dirs: test
The other option is to include src in the test suites hs-source-dirs as well.
Both of them require me to specify all build dependencies in the test case, as far as I know. Is there a way around this?
It should work as is but there is a reported bug when you use it with cabal repl
Overall it seems work with cabal test but if you try to load the test-file into cabal repl you might get an error like this:
Could not find module ‘XYZ’
It is a member of the hidden package ‘XZY-[ver]’.
Perhaps you need to add ‘XYZ’ to the build-depends in your .cabal file.
Use -v to see a list of the files searched for.
So right now it might be a good idea to indeed copy the dependencies but hopefully this will get resolved shortly
If you declare a library + executable sections in a cabal file while avoiding double compilation of the library by putting the library into a hs-source-dirs directory, you cannot usually run your project with ghci and runhaskell anymore, especially if the executables have helper modules themselves.
What is a recommended project layout that
only builds what is needed once
allows using runhaskell
has a clean structure without hacks?
Let's assume you have a mylib library, and mylib-commandline and mylib-server executables.
You use hs-source-dirs for the library and each executable so that each has their own project root, avoiding double compilation:
mylib/ # Project root
mylib.cabal
src/ # Root for the library
tests/
mylib-commandline/ # Root for the command line utility + helper modules
mylib-server/ # Root for the web service + helper modules
Full directory layout:
mylib/ # Project root
mylib.cabal
src/ # Root for the library
Web/
Mylib.hs # Main library module
Mylib/
ModuleA # Mylib.ModuleA
ModuleB # Mylib.ModuleB
tests/
...
mylib-commandline/ # Root for the command line utility
Main.hs # "module Main where" stub with "main = Web.Mylib.Commandline.Main.main"
Web/
Mylib/
Commandline/
Main.hs # CLI entry point
Arguments.hs # Programm command line arguments parser
mylib-server/ # Root for the web service
Server.hs # "module Main where" stub with "main = Web.Mylib.Server.Main.main"
Web/
Mylib/
Server/
Main.hs # Server entry point
Arguments.hs # Server command line arguments parser
The stub-like entry point file mylib-commandline/Main.hs looks like this:
module Main where
import qualified Web.Mylib.Server.Main as MylibServer
main :: IO ()
main = MylibServer.main
You need them because an executable must start on a module simply called Main.
Your mylib.cabal looks like this:
library
hs-source-dirs: src
exposed-modules:
Web.Mylib
Web.Mylib.ModuleA
Web.Mylib.ModuleB
build-depends:
base >= 4 && <= 5
, [other dependencies of the library]
executable mylib-commandline
hs-source-dirs: mylib-commandline
main-is: Main.hs
other-modules:
Web.Mylib.Commandline.Main
Web.Mylib.Commandline.Arguments
build-depends:
base >= 4 && <= 5
, mylib
, [other depencencies for the CLI]
executable mylib-server
hs-source-dirs: mylib-server
main-is: Server.hs
other-modules:
Web.Mylib.Server.Main
build-depends:
base >= 4 && <= 5
, mylib
, warp >= X.X
, [other dependencies for the server]
cabal build will build the library and the two executables without double compilation of the library, because each is in their own hs-source-dirs and the executables depend on the library.
You can still run the executables with runghc from your project root, using the -i switch to tell where it shall look for modules (using : as separator):
runhaskell -isrc:mylib-commandline mylib-commandline/Main.hs
runhaskell -isrc:mylib-server mylib-server/Server.hs
This way, you can have a clean layout, executables with helper modules, and everything still works with runhaskell/runghc and ghci. To avoid typing this flag repeatedly, you can add something similar to
:set -isrc:mylib-commandline:mylib-server
to your .ghci file.
Note that sometimes should split your code into separate packages, e.g. mylib, mylib-commandline and mylib-server.
You can use cabal repl to start ghci with the configuration from the cabal file and cabal run to compile and run the executables. Unlike runhaskell and ghci, using cabal repl and cabal run also picks up dependencies from cabal sandboxes correctly.
I have a src directory. In this directory I have Main.hs file and Test directory. In the Test directory I have Test.hs module. I need to compile it with cabal.
In my cabal file I have:
Executable main
-- .hs or .lhs file containing the Main module.
Main-is: src/Main.hs
and
-- Modules not exported by this package.
Other-modules: Test.Test
When I do cabal configure it's OK, but when I try to cabal build I get the following error:
cabal build
Preprocessing executables for main-0.0.1...
cabal: can't find source for Test/Test in ., dist/build/autogen
How can I correctly build Main.hs and some other directories with .hs files?
Thank you.
If Test.Test is defined in src/Test/Test.hs, you need
hs-source-dirs: src
in the Executable section of your Cabal file. Note that your main-is file path should be relative to the source directory, so in this case, you should change it to Main.hs.
According to the wiki entry,
It packages up the files needed to build the project
I have a simple executables-only .cabal project, which basically contains
Executable myprog
hs-source-dirs: src
main-is: MyMain.hs
and is made up of some additional .hs files below src/ beyond src/MyMain.hs. E.g., src/Utils.hs and a few others.
cabal build has no problems building myprog, and compiles the required additional .hs files below src/, but cabal sdist does not, thus creating a dysfunctional source-tarball. What am I doing wrong? How do I tell cabal to include all source files below hs-source-dirs?
As a side-note, with GNU Autotools, there was a make distcheck target, which would first build a source-tarball, and then try to build the project via the newly generated source-tarball, thus ensuring everything's ok. Is there something similar for cabal, in order to make sure my source-tarball is sound?
You should list the other Haskell files in the .cabal file, inside the Executable stanza.
other-modules: Utils AFewOthers
The distribution only includes source files that are listed in your .cabal file. Cabal has no other way to detect which source files are in your package. You could still build because cabal build calls ghc --make, and ghc will find and compile all the source files it needs.