What's the difference between `stack install NAME` and `NAME` in the build-depends of project.cabal file? - haskell

What is the difference between adding package_name under the build-depends: section in a project's .cabal file, versus doing stack install package_name within that project's directory?

stack install will just install the package to the appropriate place (the current snapshot database for libraries in Stackage, the sandbox in ./.stack-work for other libraries, ~/.local/bin or your system's equivalent thereof for executables). Adding a library to build-depends specifies it as a dependency of your project, and leads to the library being installed next time you do a stack build. If you are actually using the library in your project you must add it to build-depends, otherwise you won't be able to build the project (or even play with the library using stack ghci).
N.B.: As of stack-0.1.3.1, stack install NAME is just a synonym for stack build --copy-bins NAME. The --copy-bins option tells stack to copy any executables to ~/.local/bin. If your package is just a library with no executables, stack install NAME is the same as stack build NAME.

Related

Stack won't resolve a 'hidden' dependency

I am working on my first major Haskell application, and want to add mockery to create disposable test WAI threads. Importing mockery and running stack test resulted in the compiler error:
Failed to load interface for ‘Test.Mockery.Directory’
It is a member of the hidden package ‘mockery-0.3.5’.
Perhaps you need to add ‘mockery’ to the build-depends in your .cabal file.
Use -v to see a list of the files searched for.
So, I added mockery to my cabal file under test dependencies. However, when I run stack build or stack test mockery is automatically removed from the cabal file.
I have also tried listing mockery-0.3.5 under extra-deps in the stack.yaml file. This unsurprisingly didn't work, since mockery is part of my lts, and extra deps is for packages outside of lts.
How can I get stack to recognize that mockery should be included as a dependency to to project?
Here is my stack.yaml:
flags: {}
ghc-options:
! '*': -Wall
packages:
- .
extra-deps: [
]
resolver: lts-9.5
I'm using stack version 1.5.1
I imagine this is a stupid build issue and look forward to confronting my obvious oversight.
In stack.yaml you declare the Stackage LTS version, a curated list of hackage dependencies that you want to depend on. You can also depend on local packages and packages in git that are not in Hackage. You may also change the versions of the packages in LTS as long as they respect the constraints of the other dependencies.
package.yaml is the build file. Any packages you want to import directly in your Haskell code must be declared in here as dependencies, even if they are explicitly declared in the stack.yaml.
Finally, when you see It is a member of the hidden package, that means that one of your dependencies is using that package, but it is not declared as a dependency in your build file.

Stack not resolving dependencies properly

I'm trying to set up Hakyll on a fresh Ubuntu 16.04 instance, but I can't seem to get the Stack-based setup instructions right.
Starting out with stack install hakyll, I get:
Error: While constructing the build plan, the following exceptions were encountered:
In the dependencies for hakyll-4.9.3.0:
http-conduit-2.1.11 must match >=2.2 && <2.3 (latest applicable is 2.2.3)
Plan construction failed.
I got a similar error when tying to stack-install http-conduit-2.1.11, this time with:
Error: While constructing the build plan, the following exceptions were encountered:
In the dependencies for http-conduit-2.2.3:
http-client-0.4.31.2 must match >=0.5 && <0.6 (latest applicable is 0.5.5)
http-client-tls-0.2.4.1 must match >=0.3 && <0.4 (latest applicable is 0.3.3.1)
Plan construction failed.
After resolving dependencies for this (also using Stack), I tried once again to stack install http-conduit-2.1.11, but I once again got the same dependency error.
The packages http-client-0.4.31.2 and http-client-tls-0.2.4.1 appear in my ~/.stack/precompiled/x86_64-linux/ghc-8.0.1/1.24.0.0/, which isn't explicitly in my $PATH, however that feels like an extremely hacky solution, and I haven't found any documentation recommending this approach.
How can I correctly install Hakyll on my machine?
Dependency management with stack is meant to be reproducible and declarative, that means that a stack project will only compile once all dependencies are recorded in the .cabal file(s) of the project and once the stack.yaml of the project defines versions for these dependencies either in the resolver or the extra-deps section.
Your confusion seems to stem from a misunderstanding of what stack install does. The command line help has this to say about it:
build Build the package(s) in this directory/configuration
install Shortcut for 'build --copy-bins'
...
--[no-]copy-bins Enable/disable copying binaries to the local-bin-path
(see 'stack path')
stack install does not save any dependencies.
So the proper way of making hakyll available as a dependency to your code is:
Create a proper stack project with stack init if you already have a Cabal package, or stack new if you don't.
Add hakyll to the library or executable build-depends in your .cabal file.
Attempt to stack build and follow the instructions in any error messages until all issues are resolved.
A simpler solution than #sjakobi's in this case was to specify a resolver as a command line option when starting a new Stack project:
stack install hakyll --resolver=5.11 --install-ghc

Haskell stack with global ghc

Is it possible to use stack with an already installed ghc without stack installing a local copy of ghc or cabal?
Yes. If the ghc in PATH is of right version for the selected snapshot, stack will happily use it.
% ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.8.4
% stack --resolver=lts-2.22 install packdeps
Run from outside a project, using implicit global project config
Using resolver: lts-2.22 specified on command line
packdeps-0.4.1: unregistering
packdeps-0.4.2: download
...
% stack --resolver=nightly-2015-12-25 install packdeps
Run from outside a project, using implicit global project config
Using resolver: nightly-2015-12-25 specified on command line
Compiler version mismatched, found ghc-7.8.4 (x86_64), but expected minor version match with ghc-7.10.3 (x86_64) (based on resolver setting in /Users/phadej/.stack/global/stack.yaml).
Try running "stack setup" to install the correct GHC into /Users/phadej/.stack/programs/x86_64-osx/
You can also skip ghc check --skip-ghc-check:
% stack --resolver=nightly-2015-12-25 --skip-ghc-check install packdeps
Run from outside a project, using implicit global project config
Using resolver: nightly-2015-12-25 specified on command line
split-0.2.2: configure
...
but that might be a bad idea

Despite stack solver, Could not find module `Test.Hspec'

This is my stack.yaml file declaring hspec as a extra dependency:
# Specifies the GHC version and set of packages available (e.g., lts-3.5, nightly-2015-09-21, ghc-7.10.2)
resolver: lts-3.8
# Local packages, usually specified by relative directory name
packages:
- '.'
# Packages to be pulled from upstream that are not in the resolver (e.g., acme-missiles-0.3)
extra-deps:
- hspec-2.2.0
when I run stack solver it says there is no change to be done:
root#5d7daa2aec0a:/src/test_stack/a-test/src# stack solver
This command is not guaranteed to give you a perfect build plan
It's possible that even with the changes generated below, you will still need to do some manual tweaking
Asking cabal to calculate a build plan, please wait
No needed changes found
To automatically modify your stack.yaml file, rerun with '--modify-stack-yaml'
this is my source file (only to check that I could use Hspec with stack):
module Main where
import Test.Hspec
main :: IO ()
main = do
putStrLn "hello world"
and when I run stack build I get:
2015-10-05 22:24:08.450413: [warn] Could not find module `Test.Hspec' #(stack_Bp003b8iWaELtdr693pSPs:Stack.Build.Execute src/Stack/Build/Execute.hs:1241:35)
I thought stack solver was ensuring that extra dependencies are ok.
What I am doing wrong ?
It's the first time I use stack.
While stack replaces cabal-install, the command line tool for building and installing packages, it still uses the Cabal packaging infrastructure. In particular, that means projects built with stack are still Cabal-compatible packages with .cabal files, and all of their dependencies should be listed in the build-depends section of the .cabal file with appropriate version ranges. That holds even if the dependency is also specified in the stack.yaml file extra-deps field, as that field serves a different purpose (namely, giving stack an exact version to use when building the package).

Difference between new-template.cabal and stack.yaml

I want to use reactive-banana in my new Haskell project. I never used cabal-install or stack before. I created a directory and initialized project files in it using stack new. I see now 2 files in the directory: new-template.cabal and stack.yaml.
How do I set dependencies and make sure they are downloaded and compiled?
At first I tried to add - reactive-banana-0.8.0.2 in stack.yaml under extra-deps:, but both stack build and stack solver didn't download it. Then I augmented a part called library in new-template.cabal to this:
library
hs-source-dirs: src
exposed-modules: Lib
build-depends: base >= 4.7 && < 5
, reactive-banana >= 0.8
default-language: Haskell2010
Every time I tried to run stack build, it crashed with an error and suggestion to add some package to stack.yaml under extra-deps:, and this happened three times until finally all packages installed, and I could import them in stack ghci REPL.
So my question is, what is the idiomatic way to use stack? Which of these 2 files should I use to specify dependencies and other project metadata? What is the sample workflow of an average Haskell developer with stack?
When using stack I generally don't put any versions bounds in my .cabal file. I let the resolver and extra-deps setting in the stack.yaml file determine which versions of packages to select.
Here is a stack.yaml file which brings in reactive-banana-0.8.1.2:
flags: {}
packages:
- '.'
extra-deps:
- reactive-banana-0.8.1.2
- psqueues-0.2.0.2
resolver: lts-2.17
In my .cabal file I just have:
build-depends: base >= 4.7 && < 5, reactive-banana
The reactive-banana version is pinned by the stack.yaml file.
If you want to use GHC 7.10 change the resolver to something like nightly-2015-06-17.
I determine the extra-deps iteratively, by just running stack build and adding whatever dependencies are missing to the stack.yaml file until all dependencies are satisfied.
You will only need to do this with packages which are not in Stackage - like reactive-banana. A great many of commonly used packages are in Stackage and their versions will be determined by the resolver setting.
In the default configuration, stack works with two package databases: a centralised per-user one and a project-specific one. The centralised database only pulls packages from Stackage, a subset of Hackage with known-to-be-compatible packages, while you can put whatever you want on the project-specific database. All packages you use must be in the cabal file, but those not on Stackage (that is, the ones that will go to the project-specific database) must also be listed in the extra-deps section of stack.yaml. reactive-banana is not on Stackage, so you need to add it to stack.yaml, like this:
# etc.
extra-deps:
- reactive-banana-0.8.1.2
# etc.
stack solver can fill in the extra dependencies in stack.yaml for you.

Resources