Prevent rebuilding external dependency - haskell

I'm new to Haskell.
I cloned a Haskell project (pandoc) from github, and compiled it with:
stack setup
stack install --test
After a while, the project is built.
Now I want to build another project (pandoc-crossref), an extension to the first one and which depends on it.
There is an extra-deps entry for pandoc in stack.yaml:
extra-deps:
...
- pandoc-2.0.1.1
...
In the README.md of the pandoc-crossref project I can see:
Pandoc will also be built, if it's not installed as a Haskell library system-wide.
But when I try to build pandoc-crossref, pandoc is built again.
What does installed as a Haskell library system-wide mean? Is it possible to prevent the first project being built again? Maybe by using the --extra-lib-dirs option?

Related

Stack: 'hdevtools is a library dependency, but the package provides no library needed since my-app is a build target.'

I was trying to add hdevtools to my stack project, so I ran stack build hdevtools. The install seemed to work successfully, and my text editor stopped reporting imported libraries installed via stack (like aeson and tasty) as missing.
However, things went wrong when I added this line to the dependencies section of my package.yaml file:
- hdevtools >= 0.1 && < 1
And then tried to run stack build again. I received the following error output:
Error: While constructing the build plan, the following exceptions were encountered:
In the dependencies for my-app-name-0.1.0.0:
hdevtools is a library dependency, but the package provides no library
needed since my-app-name is a build target.
Some different approaches to resolving this:
* Consider trying 'stack solver', which uses the cabal-install solver to attempt
to find some working build configuration. This can be convenient when dealing
with many complicated constraint errors, but results may be unpredictable.
Plan construction failed.
I tried running stack solver, but that threw the exception documented here.
How can I declare hdevtools as a dependency of my project?
#alexis-king recommends using stack build --copy-compiler-tool hdevtools in this guide, in the section titled Setting up editor integration.
This works for the current project, and other projects using the same GHC version, but you will need to run it again when you upgrade to a new GHC version.
More context from King's guide:
As mentioned above, stack install is not what you want. Tools like ghc-mod, hlint, hoogle, weeder, and intero work best when installed as part of the sandbox, not globally, since that ensures they will match the current GHC version your project is using.
How can I declare hdevtools as a dependency of my project?
hdevtool is an executable and cabal doesn't have a concept of development dependencies (like in other package managers like npm etc). So, all you can do is install hdevtools globally and make it work.

Create hackage package that can be installed with stack

When running stack sdist in my project directory, the stack.yaml file isn't included in the tarball (this seems to be expected).
Consequently, when I upload the tarball to hackage, then stack install mypackage it complains about missing dependencies (extra-deps) which I specified in the stack.yaml file.
$ stack install pandoc-placetable
Run from outside a project, using implicit global project config
Using resolver: lts-5.17 from implicit global project's config file: ~/.stack/global-project/stack.yaml
While constructing the BuildPlan the following exceptions were encountered:
-- Failure when adding dependencies:
spreadsheet: needed (>=0.1.3 && <0.1.4), not present in build plan (latest applicable is 0.1.3.4)
needed for package: pandoc-placetable-0.4
-- While attempting to add dependency,
Could not find package spreadsheet in known packages
Recommended action: try adding the following to your extra-deps in /Users/maurobieg/.stack/global-project/stack.yaml
- spreadsheet-0.1.3.4
Or what's the recommended way to make a hackage package stack-installable if it has further hackage dependencies?
Update: I just added extra-source-files: stack.yaml to the cabal file and the stack.yaml is indeed included in the tarbal of the newly published version. Nevertheless, stack install pandoc-placetable-0.4.1 still comes up with the same error.
I could also just tell people who don't want to install cabal-install on their system to clone from GitHub, then build with stack. Is that the recommended approach for tiny packages? Or should I ask them to include the dependency of pandoc-placetable (i.e. spreadsheet) in their global stack.yaml? Smells like polluting a global file...
As mentioned by #mgsloan in the comments above: There's an open stack issue about using stack.yaml from hackage package.
I guess until it's fixed I'll just tell people to clone from GitHub (or as mentioned by #MichaelSnoyman to stack unpack) and then cd into the newly created directory and stack install there.

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 install/use a local version of package using Stack?

The situation is, I am trying to install Netwire using Stack. However, there is a problem in the latest netwire 5.0.1, as reported by dhobbs: http://hub.darcs.net/ertes/netwire/issue/13
Since I don't know when the problem will ever be fixed, I downloaded the repo and made the change myself. However, I don't understand how to install such a locally patched version. stack install does not install that into ~/.stack. Does anyone have an idea?
Update
Now I am developing some other libraries using Stack. How do I make another project use that libraries? Hard coding a relative path looks incredibly ugly.
So you have a project where you want to use your locally patched Netwire version and in your project you have a stack.yml, as an example:
flags: {}
packages:
- '.'
extra-deps: {}
resolver: lts-3.7
You also have an dependency on netwire declared in your cabal file.
To use you patched Netwire in this project of yours you simply put the patched Netwire package in a subdirectory of your project, perhaps called netwire, and update your stack.yml as such:
flags: {}
packages:
- '.'
- netwire
extra-deps: {}
resolver: lts-3.7
Now stack build will build your project with the patched Netwire version.
You can also put the modified source online (if the license permits) and refer to the source using either a tarball URL
- https://example.com/netwire.tar.gz
or a git repository and commit reference:
- location:
git: git#example.com/netwire
commit: 6a86ee32e5b869a877151f74064572225e1a0398
(Check out the documentation for more info: https://docs.haskellstack.org/en/stable/yaml_configuration/#packages-and-extra-deps)

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.

Resources