I've written an application in Haskell and it's starting to become slightly useful to users. However my application isn't targeted at technically adept folks, let alone Haskell developers, so building my application from source isn't really something I can expect them to do.
So to make my application available to my users, I would like build the application myself, put its executable, data files, dependencies, the dependencies' data files, required licensing information and other required files into one archive and put that archive up onto a website. Now users can download that archive, unpack it and have everything required to run my application.
The process I described above seems like a fairly common way to distribute binaries of applications to me. However, I can't figure out what tools to use or how to configure them to build my application into a binary distribution described above.
Cabal (the library) seems to have the features that are required for this. Usual Setup.hs
scripts (without cabal (the tool) or stack as wrappers) support options such as --prefix
and --enable-relocatable
that let you install a package to the given prefix and compile them in such a way as to ensure that data files can still be located if the prefix (as a whole) is moved somewhere else.
But using the raw Setup.hs
has the downside that it doesn't handle automatically installing dependencies. And since many decently sized Haskell applications will have hundreds of dependencies (or at least mine does), configuring and building each of them by hand isn't really feasible.
The obvious solution to the problem of installing dependencies would be to use a wrapper tool such as cabal (the tool) or stack, since they are specifically made to deal with the problem of large dependency trees. However, they all seem to have problems preventing me from building my application as a binary distribution:
stack build
doesn't have the options --prefix
or --enable-relocatable
and instead always installs to .stack-work
and ~/.stack
.
cabal v2-*
has the options --prefix
and --enable-relocatable
but seems to ignore them entirely and instead always installs to dist-newstyle
and ~/.cabal
.
cabal v1-*
seems to do what I want for very simple cases. However, for more complicated cases it produces obscure build failures, where GHC complains about not finding modules from dependencies and cabal complains about partially installed packages. But even putting these failures aside, using legacy commands for a new workflow doesn't seems like a good idea in general.
So, since I seem to be out of luck with these tools, what other tools can i use to build Haskell applications into binary distributions? Or maybe one of the tools I listed actually does what I want and I'm just using it the wrong way?
Some limitations in scope:
To create a new project using Cabal, you should first be in a specific directory set aside for the project. Then you can use cabal init -n to create a project. This will auto-generate a . cabal file for you with defaults in all the metadata fields.
Stack's functions Stack handles the management of your toolchain (including GHC — the Glasgow Haskell Compiler — and, for Windows users, MSYS2), building and registering libraries, building build tool dependencies, and more.
Stack installs the Stackage libraries in ~/. stack and any project libraries or extra dependencies in a . stack-work directory within each project's directory.
A workaround is to use cabal repl
like this (from the directory with your-package.cabal
):
$ cabal repl -b Cabal
...
ghci> :load /path/to/Setup.hs
...
ghci> :main configure --prefix=/my/prefix
...
ghci> :main build
...
ghci> :main copy --destdir=/my/dest/dir
...
That should take care of building all your dependencies, while still being able to use Setup.hs
.
I think this can still cause issues if your dependencies use data-files
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With