Skip to content

Set builddir for cabal #264

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 16, 2020
Merged

Set builddir for cabal #264

merged 3 commits into from
Nov 16, 2020

Conversation

wz1000
Copy link
Contributor

@wz1000 wz1000 commented Nov 11, 2020

Should fix #195

@fendor
Copy link
Collaborator

fendor commented Nov 11, 2020

cc @jneira, @bubba , @mpickering

@fendor fendor requested review from mpickering, fendor and jneira and removed request for mpickering November 11, 2020 10:14
@fendor
Copy link
Collaborator

fendor commented Nov 11, 2020

I think this is a good compromise, it fixes #195, with no costs for the future.

@wz1000
Copy link
Contributor Author

wz1000 commented Nov 11, 2020

What needs to change here?

  Cradle
    { cradleRootDir    = wdir
    , cradleOptsProg   = CradleAction
        { actionName = Types.Cabal
        , runCradle = cabalAction wdir mc
        , runGhcCmd = \args -> do
            -- Workaround for a cabal-install bug on 3.0.0.0:
            -- ./dist-newstyle/tmp/environment.-24811: createDirectory: does not exist (No such file or directory)
            -- (It's ok to pass 'dist-newstyle' here, as it can only be changed
            -- with the --builddir flag and not cabal.project, which we aren't
            -- using in our call to v2-exec)
            createDirectoryIfMissing True (wdir </> "dist-newstyle" </> "tmp")
            -- Need to pass -v0 otherwise we get "resolving dependencies..."
            readProcessWithCwd
              wdir "cabal" (["v2-exec", "ghc", "-v0", "--"] ++ args) ""
        }
    }

@jneira
Copy link
Member

jneira commented Nov 11, 2020

Not sure if always use another builddir without user explicit consent could drive to unexpected results (for the user) when they change config files (cabal.project, .cabal) f.e.
The builds could be out of sync and the user will not know why. Build products will be duplicated and they will not know it either.

Now hie-bios is using with-compiler and afaik it makes part of the cache stale and trigger the rebuild. Not sure if it still reuses something (the deps plan?).
But when show-build-info lands the main build could be reused entirely, so we will have to remove this to no duplicate it without no gain. So it will have costs in the future imo.

I would prefer to, at least, use a environment variable (HIE_BIOS_BUILD_DIR) and use it for both stack and cabal (for being symmetric) only if the users have set it explicitly, in the location they choose.

Ideally it should be a field in the hie.yaml and i think we could keep it while cabal does not honour builddir in the project config file (never? 😛). It would allow to have different config settings between the normal compilation and the used one in the ide, even after show-build-info.

@lukel97
Copy link
Contributor

lukel97 commented Nov 11, 2020

Has anyone combed through ghcide/hls/the rest of his-bios to see if we've hardcoded dist-newstyle anywhere?

@wz1000
Copy link
Contributor Author

wz1000 commented Nov 11, 2020

The builds could be out of sync and the user will not know why

I don't think so - nix style builds are supposed to be deterministic given a cabal.project(.local) and a index state.

Build products will be duplicated and they will not know it either.

ghcide already duplicates build products in ~/.cache/ghcide. This is a very reasonable thing to do, and the only way to ensure the IDE doesn't mess with the usual build configuration. There have been lots of bug reports over the years about running cabal/stack concurrently with the IDE messing things up. This should fix that.

@wz1000
Copy link
Contributor Author

wz1000 commented Nov 11, 2020

Has anyone combed through ghcide/hls/the rest of his-bios to see if we've hardcoded dist-newstyle anywhere?

I took a quick look and this was the only other concerning occurrence I found.

@wz1000
Copy link
Contributor Author

wz1000 commented Nov 11, 2020

But when show-build-info lands the main build could be reused entirely, so we will have to remove this to no duplicate it without no gain. So it will have costs in the future imo.

I think we want to keep this even with show-build-info for the aforementioned bug reports about running the build concurrently with the IDE.

@fendor
Copy link
Collaborator

fendor commented Nov 11, 2020

Using an environment variable seems sensible to me, and I agree it makes sense to have compiler artifacts for the IDE separated from the rest. IMO, cabal should handle it correctly, sooner or later (e.g. create a ide directory within dist-newstyle).

I am currently rather opposed to adding fields to hie.yaml unless they really make sense. Adding fields for working around bugs, feels bad design and I fear it will render the hie.yaml specification unwieldy and hard to change in the future.

Neither HLS nor ghcide will use a hard-coded dist-newstyle, otherwise it should be changed ASAP anyways, as it breaks the abstraction provided by hie-bios.

@jneira
Copy link
Member

jneira commented Nov 12, 2020

I don't think so - nix style builds are supposed to be deterministic given a cabal.project(.local) and a index state.

I worry about the "are supposed to be" part. But also by the fact user commands like cabal clean will no affect the hie-bios build, so users will have to look for the cache directory to delete it manually (if they know what have to do). I see you has included the absolute path in that directory to help found it.

I cant think of more concrete issues now but i guess that they could arise. I have to admit it doesn't seem like a convincing argument

here have been lots of bug reports over the years about running cabal/stack concurrently with the IDE messing things up. This should fix that.

But that bug is not deterministic, right? I did not hit it frequently myself, so we can offer the env var as a temporary workaround for a bug that should be fixed.

I think we want to keep this even with show-build-info for the aforementioned bug reports about running the build concurrently with the IDE.

I dont know much about s-b-i internals but i expect it will query lazily all possible info and only trigger update commands if needed, so it is supposed to trigger less that bug. In that case we will want to give it all possible info previously generated by the user so the default will have to be to share the same builddir, imo.

I am currently rather opposed to adding fields to hie.yaml unless they really make sense. Adding fields for working around bugs, feels bad design and I fear it will render the hie.yaml specification unwieldy and hard to change in the future.

Fair enough, the configuration (and its interactions) can grow exponentially if we dont consider carefully additions. I would add the project-file anyways, to make the api symmetric between stack and cabal and wait (or submit a pr!) to make cabal honour builddir in the project file. To have a way to keep different settings for the ide seems to be useful.

@fendor
Copy link
Collaborator

fendor commented Nov 12, 2020

I would add the project-file anyways, to make the api symmetric between stack and cabal

Yeah, that seems sensible to me, too.

by the fact user commands like cabal clean will no affect the hie-bios build

True, but stuff like that already happens as the .hie and .hi files are located in ~/.cache/ghcide/....

@jneira
Copy link
Member

jneira commented Nov 12, 2020

True, but stuff like that already happens as the .hie and .hi files are lcoated in ~/.cache/ghcide/... already.

Well, that files are not generated by cabal directly but they belongs to ghc, no? .hie ones are not even generated by default in my cabal builds. Handle ghc is a ghcide business so makes sense that it puts them in a cache, independent of the build tools (moreover if those files are not being generated by default or for some ghc versions).

I think the problematic ones would be the generated directly by cabal (cache dir, pakagedb's, setup-config, etc)
I remember i had to delete the ghcide cache file only on time some time ago but i do cabal clean's daily.

Maybe i am being too cautious without real reasons so go ahead if you think it will be reliable enough. 😃

@fendor
Copy link
Collaborator

fendor commented Nov 14, 2020

On Linux, I absolutely never have to execute cabal clean. The only issue I encountered was that my cabal store got corrupted by the internal libraries thingy of cabal-helper.
Imo, this is the only thing blocking this PR right now, how often does that happen and can the IDE get stuck because of it.

@fendor
Copy link
Collaborator

fendor commented Nov 14, 2020

cc @ndmitchell and @pepeiborra, since this change affects all IDE users.

@pepeiborra
Copy link
Contributor

I am supportive of this change

Copy link
Member

@jneira jneira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with this then. If we hit real issues thereafter we can make it opt-in or at least opt-out.

@wz1000 wz1000 changed the title set builddir for cabal set builddir/workdir for cabal and stack Nov 16, 2020
@wz1000
Copy link
Contributor Author

wz1000 commented Nov 16, 2020

This should be ready now, please review again.

@wz1000
Copy link
Contributor Author

wz1000 commented Nov 16, 2020

Hmm commercialhaskell/stack#2954

@jneira
Copy link
Member

jneira commented Nov 16, 2020

Adding suppor for stack has another caveat: hie-bios is gonna ignore the work-dir set in the stack.yaml users can give to hie-bios via stack-yaml field in hie.yaml.

We are using it as a workaround for some issues and this would fix it but i would not use it if user is using that field (stack-yaml).

@wz1000 wz1000 changed the title set builddir/workdir for cabal and stack Set builddir for cabal Nov 16, 2020
@wz1000
Copy link
Contributor Author

wz1000 commented Nov 16, 2020

I have reverted the stack change, someone who uses it can pick it back up if they want.

Copy link
Collaborator

@fendor fendor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@fendor fendor merged commit 604dfb0 into haskell:master Nov 16, 2020
This was referenced Dec 16, 2020
fendor added a commit to fendor/hie-bios that referenced this pull request Dec 16, 2020
@michaelpj
Copy link
Contributor

I'd love to have a Hackage release with this in.

@fendor
Copy link
Collaborator

fendor commented Jan 7, 2021

This is blocked on the current behaviour of ghcide/hls. With this PR, Paths_* modules can't be properly found and you are greeted with a lot of "No cradle found for Paths_* module" and "No cradle found for..." messages.

I am pretty sure, the issue is how we cache results in https://github.com/haskell/haskell-language-server/blob/master/ghcide/session-loader/Development/IDE/Session.hs#L122 but I got side-tracked by the holidays and so on.
Essentially, Ghcide asks for each module where its hie.yaml is and then uses the internal caches but since Paths_* is now in some ~/.cache/.../Paths_* it can't find the appropriate hie.yaml, therefore the message.

A fix could be to maintain an additional cache for all FilePaths to their respective ComponentOptions directly.

I plan to get back to it this weekend.

fendor added a commit to fendor/haskell-language-server that referenced this pull request Jan 11, 2021
Achieves this by adding a HashMap from NormalizedFilePath
to its respective hie.yaml location.
This works nicely with the existing implementation, but
increases the memory usage by an considerable amount.

This change is motivated by haskell/hie-bios#264
where we set the build-dir for cabal based projects to some config
directory in order to avoid recompilation issues whenever users invoked
`cabal build`.
However, this uncovered an issue in the existing code-base, as HLS will
ask for the compilation options for generated modules, such as
`Paths_*`, by looking for the responsible `hie.yaml` file and using an
internal cache for the options. This used to be fine, until the
aforementioned hie-bios change, since now `Paths_*` module will be in
some `~/.cache/hie-bios/...` directory, which has no responsible
`hie.yaml` which is why we see error messages such: `No hie.yaml found,
use implicit hie-bios`.
fendor added a commit to fendor/haskell-language-server that referenced this pull request Jan 11, 2021
Achieves this by adding a HashMap from NormalizedFilePath
to its respective hie.yaml location.
This works nicely with the existing implementation, but
increases the memory usage by an considerable amount.

This change is motivated by haskell/hie-bios#264
where we set the build-dir for cabal based projects to some config
directory in order to avoid recompilation issues whenever users invoked
`cabal build`.
However, this uncovered an issue in the existing code-base, as HLS will
ask for the compilation options for generated modules, such as
`Paths_*`, by looking for the responsible `hie.yaml` file and using an
internal cache for the options. This used to be fine, until the
aforementioned hie-bios change, since now `Paths_*` module will be in
some `~/.cache/hie-bios/...` directory, which has no responsible
`hie.yaml` which is why we see error messages such: `No hie.yaml found,
use implicit hie-bios`.
fendor added a commit to fendor/haskell-language-server that referenced this pull request Jan 28, 2021
Achieves this by adding a HashMap from NormalizedFilePath
to its respective hie.yaml location.
This works nicely with the existing implementation, but
increases the memory usage by an considerable amount.

This change is motivated by haskell/hie-bios#264
where we set the build-dir for cabal based projects to some config
directory in order to avoid recompilation issues whenever users invoked
`cabal build`.
However, this uncovered an issue in the existing code-base, as HLS will
ask for the compilation options for generated modules, such as
`Paths_*`, by looking for the responsible `hie.yaml` file and using an
internal cache for the options. This used to be fine, until the
aforementioned hie-bios change, since now `Paths_*` module will be in
some `~/.cache/hie-bios/...` directory, which has no responsible
`hie.yaml` which is why we see error messages such: `No hie.yaml found,
use implicit hie-bios`.
fendor added a commit to fendor/haskell-language-server that referenced this pull request Jan 28, 2021
Achieves this by adding a HashMap from NormalizedFilePath
to its respective hie.yaml location.
This works nicely with the existing implementation, but
increases the memory usage by an considerable amount.

This change is motivated by haskell/hie-bios#264
where we set the build-dir for cabal based projects to some config
directory in order to avoid recompilation issues whenever users invoked
`cabal build`.
However, this uncovered an issue in the existing code-base, as HLS will
ask for the compilation options for generated modules, such as
`Paths_*`, by looking for the responsible `hie.yaml` file and using an
internal cache for the options. This used to be fine, until the
aforementioned hie-bios change, since now `Paths_*` module will be in
some `~/.cache/hie-bios/...` directory, which has no responsible
`hie.yaml` which is why we see error messages such: `No hie.yaml found,
use implicit hie-bios`.
fendor added a commit to fendor/haskell-language-server that referenced this pull request Jan 28, 2021
Achieves this by adding a HashMap from NormalizedFilePath
to its respective hie.yaml location.
This works nicely with the existing implementation, but
increases the memory usage by an considerable amount.

This change is motivated by haskell/hie-bios#264
where we set the build-dir for cabal based projects to some config
directory in order to avoid recompilation issues whenever users invoked
`cabal build`.
However, this uncovered an issue in the existing code-base, as HLS will
ask for the compilation options for generated modules, such as
`Paths_*`, by looking for the responsible `hie.yaml` file and using an
internal cache for the options. This used to be fine, until the
aforementioned hie-bios change, since now `Paths_*` module will be in
some `~/.cache/hie-bios/...` directory, which has no responsible
`hie.yaml` which is why we see error messages such: `No hie.yaml found,
use implicit hie-bios`.
mergify bot added a commit to haskell/haskell-language-server that referenced this pull request Jan 29, 2021
* Add custom cache layer for session loading

Achieves this by adding a HashMap from NormalizedFilePath
to its respective hie.yaml location.
This works nicely with the existing implementation, but
increases the memory usage by an considerable amount.

This change is motivated by haskell/hie-bios#264
where we set the build-dir for cabal based projects to some config
directory in order to avoid recompilation issues whenever users invoked
`cabal build`.
However, this uncovered an issue in the existing code-base, as HLS will
ask for the compilation options for generated modules, such as
`Paths_*`, by looking for the responsible `hie.yaml` file and using an
internal cache for the options. This used to be fine, until the
aforementioned hie-bios change, since now `Paths_*` module will be in
some `~/.cache/hie-bios/...` directory, which has no responsible
`hie.yaml` which is why we see error messages such: `No hie.yaml found,
use implicit hie-bios`.

* Apply suggestions from code review

modifyVar with evaluate

Co-authored-by: Pepe Iborra <[email protected]>
Co-authored-by: Pepe Iborra <[email protected]>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
@fendor fendor mentioned this pull request Jan 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cabal cradle causes me to constantly need to run cabal configure
6 participants