Can I use cabal to handle non-Haskell libraries? - haskell

There have been attempt in other package managers to build brigdes to other ecosystems. E.g., there is composer-npm-bridge, which allows to pull packages from node registry into a PHP project. Is it possible to build something like this using cabal? More concretely, how would one go about pulling packages from luarocks into a Haskell project?

It is in principle possible: with build-type: custom, cabal will compile and run your Setup.hs in place of its own build mechanisms, and you can put arbitrary Haskell code in Setup.hs. Alternately, if you can fit your setup process into the usual configure-make-make install dance, then the build-type: configure option may be just the ticket.
See the user's guide for more complete details on these configuration options.

Related

Cabal - add build dependency with Cabal instead of manually mangling with the file

Do I need to manually edit the *.cabal file's build-depends section to add package as a project dependency?
Or perhaps there is a more convenient way that is not as error prone as manually mangling with build files is.
Thinking about functionality that pretty much any package manager I used has, namely
apt install
npm i
nuget install
Install Package
and so on. Does such functionality exist in Cabal?
There is no better way at the moment. The answer #danidiaz gave is essentially correct -- cabal-edit will automatically update cabal files for you. The plan is to import similar functionality into cabal directly. This was remains blocked on an exactprinter that can parse and emit cabal files precisely -- and work on that exactprinter is now underway.

Will users be diverted from a package if it's not passing `cabal check` for `cabal` `1.22` due to the absence of `Setup.hs`?

stack new usually creates a default Setup.hs file. I removed it from a project and it still builds alright for any lts resolver down to lts-2. It also passes cabal check at least for cabal version 1.24. (Though not for cabal 1.22.)
Can I conclude from this result that including a default Setup.hs in a project is not trendy anymore and I can drop it? In particular, will many prospective users be diverted from installing the package if it's not passing cabal check for cabal 1.22?
P.S. This question is more specific than the other, similar one in that I want to know, specifically, if the package not passing cabal check for a certain version of cabal due to the absence of an otherwise unnecessary Setup.hs will be counted against that package in some situations, and whether there are any other downsides to not having a Setup.hs in a project, considering the current state of the Haskell ecosystem. Whether a Setup.hs is necessary or useful overall is not a question here.
If you run cabal sdist on a project without a Setup.hs file, cabal creates one for you -- try it!
As such, there's no point to removing the file, because it will just get regenerated when you package for distribution anyway.

Stack: How can I use a multi-package dependency in `Setup.hs`?

I have a stack multi-package project where the "multi-package" is zip-conduit-0.2.2.2 (I needed to tweak some dependency versions to get it to compile with nightly-2015-10-12).
I use zip-conduit in the main package and I also want to in Setup.hs in order to be able to package up zip files.
I have build-type: Custom in my cabal file and stack build attempts to build Setup.hs. The problem is that building Setup.hs cannot find the dependency zip-conduit-0.2.2.2.
Can I use a multi-package dependency in Setup.hs? If so how? and if not, what is my alternative?
Note: I have seen this reference https://github.com/commercialhaskell/stack/pull/899, but I don't understand it.
It looks like you need to set the explicit-setup-deps setting to true for that package. It's unfortunate that Stack can't handle this situation automatically, but without dependency information in .cabal files, there seems to be no alternative.
See the linked issues from the documentation if you're interested in the history here.
I don't think it is possible to declare package dependencies for Setup.hs itself.
Some ideas:
Require that the dependent packages have already been installed.
Have Setup.hs shell out to an external command to perform the zipping, and just require that the external command has to exist.
Make the installer program an additional exe target in the cabal file. Before proceeding with the build of the library, Setup.hs can build the installer program target, then build the library, then use the built installer exe to install the library.

How to build a sandboxed cabal project with a custom version of a dependency that is not on hackage (e.g. a checkout from github)

If a have a library checked out locally that builds with cabal that is used by an application. I would like to build my application against the the local library rather than something from hackage but I'm not sure how to do this. This seems like something I should be able to do, I'm just don't seem to be able to work out how.
Sandboxing
In case it matters or complicates things, the application is in a cabal sandbox with the cabal-sandbox-config file in the route directory of the application.
What I'm Trying to accomplish
I'm building Yesod application and I want to tweak the behaviour of one of the dependencies (shakespeare). I would like to build my application against my tweaked version.
Use cabal sandbox add-source, which is designed specifically for this use case.
Example:
$ git clone https://github.com/SomeUser/SomeDependency
$ cd /path/to/my-project
$ cabal sandbox add-source /path/to/SomeDependency
$ cabal build
As a bonus, if you later update SomeDependency and try to rebuild my-project, cabal will notice that and reinstall SomeDependency.
Option 1:
You can just clone the project, and then run a cabal install in the cloned directory.
git clone https://github.com/yesodweb/shakespeare.git
This will give you a directory shakespeare which will contain a .cabal file.
So just enter the directory and run a cabal install. This will install shakespeare. Now continue with installing your project.
The key point:
You need to install shakespeare yourself first so that when you compile your own project, ghc or cabal doesn't try to install the shakespeare dependency (from hackage by default) on its own.
Option 2:
Install hackage-server
Upload a copy of shakespeare (your tweaked version) to your local hackage
Edit your cabal config to prioritize your local hackage over the haskell-hackage
remote-repo: hackage.haskell.org:http://hackage.haskell.org/packages/archive
remote-repo: local.hackage:http://local.hackage/packages/archive
This might make sense if you're going to be tweaking several packages, but you're probably better off not doing this because among other things, keeping track of updates to your tweaked versions is going to be a nightmare.

how to iterate in snap framework without cabal install

I love the snap framework but I hate running 'cabal install' with each iteration (minor code change) I want to try out.
Is there an alternative for rapid iteration?
Start with
cabal install --reinstall -fhint snap
Then, for your project:
cabal clean
cabal configure -fdevelopment
cabal build
./dist/build/projname/projname
You shouldn't ever use cabal install for binaries that you don't want to be able to execute from arbitrary locations, anyway. You should be using cabal build for things you only want to run locally.
You will need to run cabal build and start the program again when you change Main.hs or your project's .cabal file.
If you have any further questions, comment - I'm the guy who implemented this functionality for
Snap.
Yesod provides yesod devel which automatically reloads code changes. I am not aware of a comparable capability in snap, but it is highly likely that they can reuse much of the Yesod code that does this.
Given the existence of Snap.Loader.Devel I'm guessing they might already provide something like what you are asking for, but I can't find the documentation on how to use it. The FAQ question How do I run my app in development mode still requires a cabal install; it's unclear from the docs whether you only need to do this once, or every time the code changes.

Resources