commercialhaskell / stack

The Haskell Tool Stack
http://haskellstack.org
BSD 3-Clause "New" or "Revised" License
3.95k stars 842 forks source link

What is the difference between `packages` and `extra-deps` in stack.yaml #6492

Closed chansey97 closed 4 months ago

chansey97 commented 4 months ago

For example (just an experiment for the confusion),

I have a project that depends on Yampa-0.14.6, which further depends on simple-affine-space-0.2.1, see Dependencies

The following is the project directory structure:

my-project
|   my-project.cabal
|   package.yaml
|   Setup.hs
|   stack.yaml
|
+---src
|   |  ... XXX.hs
|
+---app
|   |  Main.hs
|
+---simple-affine-space-0.2.1
|   |   simple-affine-space.cabal
|   |   Setup.hs
|   \---src
|       \--- ... YYY.hs

Note that the simple-affine-space-0.2.1, which is used by Yampa, is my own modified version. Its source code us on my local disk, i.e. my-project/simple-affine-space-0.2.1 as you have seen.

The my-project.cabal is something like:

...
library
  hs-source-dirs: src
  build-depends:
      base >=4.7 && <5
    , Yampa ==0.14.6
    , gloss
  ...

executable my-project-exe
  main-is: Main.hs
  hs-source-dirs:  app
  build-depends:
      base >=4.7 && <5
    , Yampa ==0.14.6
    , gloss
    , my-project
  ...
...

The question is that should I treat the simple-affine-space-0.2.1 as "project package" or "extra-deps"?

More precisely, should the stack.yaml be

packages:
- .
- ./simple-affine-space-0.2.1

extra-deps: []

or

packages: 
- .

extra-deps: 
- ./simple-affine-space-0.2.1

I have tried these two methods, both built and run successfully.

I also observed that

  1. Whenever I edit the source code of simple-affine-space-0.2.1 and build, the Yampa will build automatically as well.

  2. The ghc-pkgs (i.e. binaries) of simple-affine-space and Yampa are generated in the current project directory, i.e. my-project/.stack-work/install/0f5530d4/lib/x86_64-windows-ghc-9.4.8/

  3. Use stack exec -- ghc-pkg list to see the layered package database. The local database (also known as a mutable database) shows

       Yampa-0.14.6
       simple-affine-space-0.2.1
       my-project-0.1.0.0

That's good.

The problem is that I can't see any difference between the two! No matter which method (packages or extra-deps) I use, the results are almost the same.

I have read docs from packages , extra-deps, and multi-package-project, but still unclear.

The docs also mentioned that

When adding upstream packages directly to your project it is important to distinguish local packages from the upstream dependency packages. Otherwise you may have trouble running stack ghci. See stack.yaml documentation for more details.

I can't understand what that mean.

So what is the difference between packages and extra-deps in stack.yaml?

Can anyone explain further?

Thanks.

Stack version

Version 2.15.1

mpilgrem commented 4 months ago

@chansey97, I'll have a go. packages are local. extra-deps can be local too. However, when it comes to building, with packages, Stack allows you to identify a specific component of the package to be built. You can't do that with a local extra-dep. Further, with an extra-dep, Stack will always build the library (if present) and all executables (if any) and will ignore test suites and benchmarks.

That is explained here: https://docs.haskellstack.org/en/stable/build_command/#components

hasufell commented 4 months ago

Why can't we run tests for dependencies?

mpilgrem commented 4 months ago

@hasufell, these design decisions are long before my time. In one sense, the answer to your question is because local mutable extra-deps are not part of a Stack project's packages. That is, if a local package is something you want to 'do detailed things with', treat it as one of the Stack project's packages. If a local package is something you simply want your project to depend on, treat it as one of the project's extra dependencies.

chansey97 commented 4 months ago

@mpilgrem Thanks.

It sounds like there isn't much difference in the underlying mechanisms between these two:

Stack project's packages: can also have the "dependencies behavior". The Yampa-0.14.6 depends on simple-affine-space-0.2.1, but simple-affine-space-0.2.1 can be a project's packages:.

Nevertheless, there is still indeed a subtle difference between project's packages and dependencies in stack.

I am reading stack docs.

From https://docs.haskellstack.org/en/v2.15.1/faq/#why-doesnt-stack-apply-my-ghc-options-to-my-dependencies, it said that

By default, Stack applies command line GHC options only to local packages (these are all the packages that are specified in the packages section of your stack.yaml file).

I guess that the "local packages" means project packages, not extra-deps (although extra-deps can be local).

If the simple-affine-space-0.2.1 is set as an extra-deps, the option --ghc-options would not pass, because it now is treated as a "local dependency" instead of a project's package.

If simple-affine-space-0.2.1 is set as a project's package, --ghc-options will be pass.

mpilgrem commented 4 months ago

I've considered whether your question meant that the online documentation should be improved, but this topic is already addressed:

chansey97 commented 4 months ago

@mpilgrem Yeah, the main confusion for me here was that "local (project) packages" vs. "dependencies", because "local (project) packages" can also have "dependencies behavior" and dependencies can also be "local".

Anyway, I think this issue can be closed now. Thanks.

mpilgrem commented 4 months ago

@chansey97, in the light of that I made some changes to documentation (online, in app, and in code) to implement the preferred 'project package' v 'dependency' terminology (and purge 'local') set out in https://docs.haskellstack.org/en/stable/build_overview/.