Building only remote dependencies with Stack

I’m trying to create a multistage Dockerfile for my Haskell project.

As first stage, I would like to build only the remote dependencies, meaning all the dependencies which are available on the web.

In other terms, I would like to build whatever I can can, given only stack.yaml, stack.yaml.lock and package.yaml.

I tried with stack build --only-snapshot, but that fails when searching for a local dependency (i.e. a dependency which is in a local folder).

Is there a way to achieve this?

Have you tried stack build --only-dependencies?

Yes, that builds more things than --only-snapshot. In particular, it builds all the local dependencies

Does it build the project itself?? I think it shouldn’t do that. May you share the output??

It does not build the project itself. But it builds all other local dependencies

The error I get is /path/of/the/local/dependency: getDirectoryContents:openDirStream: does not exist (No such file or directory)

Sorry, I am not undestanding. How is your porject structured? do you have multiple packages? do each package depends on other local packages? etc…

You’re right, more details could help.

The project is structured as follows

foo
  bar
    src
      ...
    stack.yaml
    package.yaml
  src
    ...
  stack.yaml
  package.yaml

The foo package has bar declared as extra-dep in stack.yaml.

I would like to build all the remote dependencies of foo given only stack.yaml and package.yaml (I mean, these are the only two files available in the file-system and seen by Stack).

What I tried so far fails telling me that the bar folder does not exist

um… I stopped using stack a while ago but IIRC, you have one stack.yaml per project and one package.yaml per package within a project (a project may have multiple packages). Hence your project should look like this

bar
  src
  ...
  package.yaml
foo
  src
  ...
  package.yaml
stack.yaml

where stack.yaml contains

resolver: lts...
packages:
- foo
- bar

This way foo and bar are project packages, not dependencies. I think you don’t need to declare bar as an extra dependency but just a dependency in foo/package.yaml. Maybe this way when you run stack build --only-deps it will not build bar as it is a project package. Notice I am not so sure about this…

1 Like

unfortunately this is not a change I can make to the project, at least for the moment

um… so I don’t think you can achive what you want as your are explicitly saying that bar is an external dependency (hence not part of project itself). Maybe you can look into the documentation for some flag like skip or something like that.

Also you can try to create a volume in docker pointing to .stack-work folder (if that’s the name), if you want to speed up the docker builds

Wait! Maybe you can add bar as a current project packge. I don’t know if stack overwrites stack.yaml for subdirectories but I think it does

so, given your project structure

foo
  bar
    src
      ...
    stack.yaml
    package.yaml
  src
    ...
  stack.yaml
  package.yaml

modify foo/stack.yaml so It is:

resolver: ...
packages:
- .
- ./bar
extra-deps:
- do not include bar here, but in foo/package.yaml

Maybe that could work… I don’t know. of course, you have to build with stack build --only-dependencies

maybe that’s something I can try, thanks for the hint

To summarize:

  • –only-dependencies/–only-snapshot takes extra-deps into account, even if it’s a local package
  • You can move a package from extra-deps into packages if you want to treat it as “part of this project”
1 Like