How can I use my own build of a package with stack? - haskell

The bigger picture is that I'm trying to use the sdl2 package from Stackage (lts 8.1). Though, I'm having a bit of an issue; The package is missing a compiler flag, as detailed in this issue on GitHub. As such, it doesn't build properly.
However, if I clone the repository, I can add the missing compiler flag to the .cabal file and build it myself, which solves the issue. I now have a working build of the package.
So my question is: How can I, in a separate project, use my own working build of the sdl2 package, instead of the one from Stackage?

There are a few ways of doing that with Stack. The one I like the most, and which sounds like a good fit for your scenario, is uploading the repository with your fork to GitHub (or wherever else you find appropriate) and then adding a reference to the online repository as an extra-dep to the packages section of stack.yaml. For the sake of illustration, here is the packages section for a project of mine in which I had to do that:
packages:
- '.'
- location:
git: https://github.com/duplode/threepenny-gui
commit: 7e4e3a41cbb5e55312d4375612790d633ccf1e7a
extra-dep: true

Related

Install package that is not on stackage but on hackage

I'm trying to use a library that's on hackage, but not on stackage.
Currently, the code doesn't seem to be hosted on git anywhere (although I could "fork" it).
Are there any better ways than to just download the library locally and tell stack.yaml where to find it?
The library is parse-dimacs by the way.
stack allows you to specify dependencies that are not included in the (Stackage) snapshot as extra-deps in your stack.yaml.
To use parse-dimacs in your project, you'd add this stanza to your stack.yaml:
extra-deps:
- parse-dimacs-1.3

What does 'no specified version' mean in my Cabal build?

The recent Travis CI build of the development version of my Haskell package reports the error
MissingH must match >=1.3.0.1, but the stack configuration has no specified version (latest matching version is 1.4.0.1)
when building for GHC 8.6.1, even though I have
MissingH >=1.3.0.1
in my build-depends.
I don't understand this error: it seems contradictory. I have no upper limit on MissingH, so why is it erroring and not using the latest?
You need to add MissingH to stack.yaml.
extra-deps:
- 'MissingH-1.4.0.1'
Your package's *.cabal file says what versions of dependencies are compatible with your package. It is a loose specification, not all combinations may actually work (because they may have conflicting bounds on transitive dependencies, or there is some unforeseen breakage with a particular version you haven't tested with).
In contrast, stack.yaml describes a particular snapshot of packages, pinned to specific versions. This precisely says "my package is known to work with those versions". Of course, it is tedious to maintain the version of every dependency, and for that the Stackage team maintains a "resolver", a curated set of package versions known to work together, that you can use to specify the version of many packages at once, by setting the resolver: field of stack.yaml appropriately. A resolver only lists a subset of packages on Hackage, so when one of your dependencies is not in there, you need to add it to your stack.yaml as an extra-dep.
Update: following the discussion, some more details about configuring travis are necessary.
First, my current preferred solution for CI of Haskell projects is to not bother with stack and use instead https://github.com/haskell-CI/haskell-ci which generates a travis script using cabal-install.
Now for a less radical solution.
Currently the travis script is only varying the --resolver option, but as far as I can tell there is no command line option to add an extra-dep. It seems stack.yaml files are the only way for that. Furthermore, we only want to specify MissingH as an extra-dep for the latest nightlies, because LTS'es already include it.
Thus I suggest the following:
Create a separate stack.yaml for the nightly resolver only, call it something else since you already have one, for example stack-nightly.yaml
packages:
- .
extra-deps:
- 'MissingH-1.4.0.1'
Set an environment variable to point to stack-nightly.yaml when the resolver is a nightly, maybe:
env:
...
- $RESOLVER=nightly STACK_YAML=stack-nightly.yaml
# Not sure of the syntax.
Otherwise you can use the --stack-yaml command line option.

How does Stack decide on dependencies?

I just made a fork to fix a bug in html-conduit, which my templating library depended on. I maintain an app that depends on that templating library.
So, I updated my library's stack.yaml to point to the fork:
extra-deps:
[...]
- git: https://github.com/emhoracek/xml.git
commit: 3e1bd12882d7c452d76e39e1db1b95577f38d4d7
subdirs:
- xml-conduit
- html-conduit
And wrote a test to make sure that updating that dependency fixed the bug. It did! Yay.
Then I updated my app to point to the updated templating library:
packages:
[...]
- location:
git: https://github.com/positiondev/larceny
commit: ba743c58ff4ac2606f67336e5e557deacb416ed8
extra-dep: true
I checked to make sure that this fixed the bug in my app, but it didn't. Until I added my fork of html-conduit to my app's extra-deps, it still had the bug.
What's going on? Why doesn't Stack use the version of html-conduit I specified in my library's stack.yaml when it's deciding what version my app should use?
Any stack command only references a single stack.yaml file - the one that's in the current directory, or maybe some parent directory. Libraries you depend on don't need to have a stack.yaml file, and it's ignored if it exists.
This keeps the version specification simple. There are no rules for handling the case where two stack.yaml files ask for different versions of the same library, because no build ever consults two stack.yaml files.
On the other hand, the .cabal file for each library is consulted, so you will get an error early in the build if some .cabal file requires a library for which the stack.yaml doesn't specify a version, or if the version bounds in a .cabal don't match the specific version in stack.yaml.

Installing local package with Stack

Is it possible to install package from sources with something similar to stack build package-name? (latter works with packages on Stackage, but not with custom ones)
Um, stack build (within the source directory)?
Stack doesn't really have a notion of installing libraries though, it only installs executables. To “install” locally-sourced packages, you need to specify what for you want them installed: add them as dependencies to another project, via a location: field in the packages: field in that project's stack.yaml file.
That's arguably sensible since, one might say, there's nothing you can do with an installed library except invoking it in another Haskell project (or in a REPL, which you can get with stack ghci). I personally don't hold with that though, I like actually being able to say install that library now. Which is one of the reasons I have always stuck to good old cabal-install rather than Stack. With that, you can just
cabal install
from within the source directory.
Cabal-install has often been criticised: its local installs can easily get out of sync and then you have weird dependency conflicts and need to rebuild lots of stuff. I never found this that much of a problem, and anyway this has been adressed in recent Cabal through Nix-style builds, which never produce conflicts.

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)

Resources