Skip to content

Add --with-repl flag to modify program the "repl" starts with #10996

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mpickering
Copy link
Collaborator

Programs like doctest and hie-bios want to use cabal-install in order
to discover the correct options to start a GHC session. Previously they
used the --with-compiler option, but this led to complications since
the wrapper was called for compiling all dependencies and so on, the
shim had to be more complicated and forward arguments onto the user's
version of GHC.

The --with-repl command allows you to pass a program which is used
instead of GHC at the final invocation of the repl. Therefore the
wrappers don't have to deal with being a complete shim but can
concentrate on intercepting the arguments at the end.

This commit removes the special hack to not use response files with
--interactive mode. Tools are expected to deal with them appropiately,
which is much easier now only one invocation is passed to the wrapper.

Fixes #9115


Template Α: This PR modifies behaviour or interface

Include the following checklist in your PR:

@mpickering mpickering changed the title Wip/for repl Add --with-repl flag to modify program the "repl" starts with Jun 17, 2025
@mpickering
Copy link
Collaborator Author

mpickering commented Jun 17, 2025

@sol @fendor Can you please test this patch works for your use case?

TODO

  • Documentation
  • Changelog

@fendor
Copy link
Collaborator

fendor commented Jun 17, 2025

haskell/hie-bios#466

> hie-bios debug src/HIE/Bios.hs                                                                                                       
Root directory:        /home/hugin/Documents/haskell/hie-bios
Component directory:   /home/hugin/Documents/haskell/hie-bios
GHC options:           @/tmp/ghci84462-0.rsp
GHC library directory: CradleSuccess "/home/hugin/.ghcup/ghc/9.6.7/lib/ghc-9.6.7/lib"
GHC version:           CradleSuccess "9.6.7"
Config Location:       No explicit config found
Cradle:                Cradle{ cradleRootDir = "/home/hugin/Documents/haskell/hie-bios", cradleOptsProg = CradleAction: Cabal}
Dependencies:          hie-bios.cabal cabal.project cabal.project.local

The branch passes the test-suite with the cabal binary from this branch.

@mpickering mpickering force-pushed the wip/for-repl branch 10 times, most recently from c037a88 to 8d7c567 Compare June 23, 2025 11:20
@sol
Copy link
Member

sol commented Jun 23, 2025

I'm in the process of testing this with doctest and I think ran in the exact issue this PR is gonna address. doctest fails with:

/home/sol/.cache/hie-bios/wrapper-b54f81dea4c0e6d1626911c526bc4e36: line 4: : No such file or directory

What I think happened here:

  1. I opened a Haskell file of some project that depends on ghc-path in vim
  2. HLS started building dependencies through the wrapper script, putting a corrupted version of ghc-path into the store
  3. Later, when I built doctest it picked up the corrupted ghc-path package from the store, resulting in a broken doctest executable.

@fendor please correct me if I'm wrong, but I think you are building dependencies through the wrapper script, right? This is generally not safe! What you should do instead:

  1. First ensure that all dependencies are already built, without using the wrapper script (e.g. cabal build --only-dependencies)
  2. Only after all dependencies are in place, invoke cabal repl --with-ghc ...
  3. As a long-term solution, switch to --with-repl ASAP

HLS is currently corrupting the cabal store and I assume the average users will not have the expertise to figure out what is even going on in a situation like this.

Possibly, cabal should include the canonical path to the used compiler into the package hashes?

@sol
Copy link
Member

sol commented Jun 24, 2025

doctest works with sol/doctest#470.

@mpickering thanks a lot for working on this. I think this will make things quite more robust.

@ulysses4ever
Copy link
Collaborator

@sol you should be an approving contributor on this repo iirc. Could you please formally approve this PR if you're happy with it?

@ulysses4ever
Copy link
Collaborator

sol you should be an approving contributor on this repo iirc. Could you please formally approve this PR if you're happy with it?

Same to @fendor

@mpickering
Copy link
Collaborator Author

@sol You should be aware that using --with-repl requires the user is using Cabal >=3.15 library. A user may have a custom setup which is built against Cabal-3.14, and that wouldn't support the flag. I added a constraint to ensure that an up-to-date Cabal library version is chosen if required.

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, one nitpick in the documentation

@fendor
Copy link
Collaborator

fendor commented Jun 25, 2025

HLS is currently corrupting the cabal store and I assume the average users will not have the expertise to figure out what is even going on in a situation like this.

Why is the current hie-bios approach corrupting the cabal store? Not doubting you, just want to understand what's going on.

EDIT: oh I should have read the full comment, so ghc-paths is the issue? Yeah, that's not great.

@sol
Copy link
Member

sol commented Jun 25, 2025

HLS is currently corrupting the cabal store and I assume the average users will not have the expertise to figure out what is even going on in a situation like this.

Why is the current hie-bios approach corrupting the cabal store? Not doubting you, just want to understand what's going on.

  1. If you build ghc-paths through the wrapper script, then ghc-paths is borked as it will produce paths to your wrapper script instead of to ghc.
  2. If you later have an install plan that includes ghc-path then the broken package from the store is reused (even if you don't build through any wrapper script!).
  3. The only real way to get rid of the broken package is to rm -rf the store directory.

@fendor Does this make sense?

@mpickering
Copy link
Collaborator Author

@sol I'm not sure what the bug is exactly, but it seems like a different bug which is exposed by using the hie-bios wrapper.

In general, relying on the existence of a ghc binary to still be present at the path which was used to build ghc-paths is not going to work. This issue isn't specific to the wrapper. You could imagine building ghc-paths on a different server for example.

@fendor
Copy link
Collaborator

fendor commented Jun 25, 2025

It makes sense! I doubt we will change that now since the wrapper is finally going to be phased out, anyway, but I understand now.

@sol
Copy link
Member

sol commented Jun 25, 2025

@sol I'm not sure what the bug is exactly, but it seems like a different bug which is exposed by using the hie-bios wrapper.

It's not a "bug" that you could easily fix, at least not that I could think of. But you could argue that ghc-paths is conceptionally broken, I guess. However this approach has been used by haddock and doctest for a very long time and I'm not aware of a better approach.

simonmar/ghc-paths#4 (comment)

@sol
Copy link
Member

sol commented Jun 25, 2025

@sol you should be an approving contributor on this repo iirc. Could you please formally approve this PR if you're happy with it?

We already have two approvals.

I can still offer to do a proper code review, but that would need to wait until tomorrow. It's late here already.

@geekosaur
Copy link
Collaborator

People have been noting that ghc-paths is a horrible, unstable hack that nevertheless gets the job done for years, I think?

@ulysses4ever
Copy link
Collaborator

@sol I'd appreciate if you could do a proper review at your convenience, if it's possible during this week. We still have things to do before 3.16 is finalized, so it'd only be wise to get this feature scrutinized as much as we can afford in the time we have.

@ulysses4ever
Copy link
Collaborator

@mpickering do you plan to look into the CI failures?

@mpickering
Copy link
Collaborator Author

I have been looking all day, They are some bug on windows

Running: "D:\a\_temp\cabal-testsuite-12064\cabal-multi.dist\work\.\dist\build\x86_64-windows\ghc-9.8.4\cabal-with-repl-exe-0.1.0.0\x\test-exe\build\test-exe\test-exe" "@D:\a\_temp\cabal-testsuite-12064\cabal-multi.dist\tmp\ghc5CDD.rsp"

"My specific executable"

D:\a\_temp\cabal-testsuite-12064\cabal-multi.dist\work\.\dist\multi-out-63884\paths\cabal-with-repl-exe-0.1.0.0-inplace-test-exe: removeDirectoryRecursive:removeContentsRecursive:removePathRecursive:removeContentsRecursive:removePathRecursive:DeleteFile "\\\\?\\D:\\a\\_temp\\cabal-testsuite-12064\\cabal-multi.dist\\work\\dist\\multi-out-63884\\paths\\cabal-with-repl-exe-0.1.0.0-inplace-test-exe": permission denied (The process cannot access the file because it is being used by another process.)

I can't reproduce it locally and I don't know how to fix it. It seems that the test completes, but then when the folder is cleaned up the deletion fails because it thinks the executable is still being used for something.

@ulysses4ever
Copy link
Collaborator

Oh my, classic Windows... Well, worst case we could disable these tests on Windows.

@mpickering
Copy link
Collaborator Author

I am going to skip the test on windows as I don't have time to investigate this to the root.

@mpickering
Copy link
Collaborator Author

@jasagredo Perhaps you could try and reproduce this if you had a spare moment. I have used your helpful skipIfCIAndWindows helper.

@mpickering mpickering force-pushed the wip/for-repl branch 2 times, most recently from 8ad3ce7 to e42c5f7 Compare June 26, 2025 09:11
@jasagredo
Copy link
Collaborator

@mpickering I can give it a look, however not in the near future as I am quite busy these weeks 😢

@mpickering
Copy link
Collaborator Author

@mpickering I can give it a look, however not in the near future as I am quite busy these weeks 😢

No problem, just wanted to flag it up in case you were interested.

@ulysses4ever
Copy link
Collaborator

FTR I created a label "re: --with-repl" for future issues: re: --with-repl

@mpickering may be it's a good time to set the merge label so that the countdown for last two days starts? If any last-minute reviews come in in that period, any comments they will have will block merging, so we'll still have time to discuss.

Copy link
Member

@sol sol left a comment

Choose a reason for hiding this comment

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

@mpickering I'm grateful that you put in the work to solve this in a clean way.

The code looks good to me.

  1. There's one comment that disrupted my reading flow somehow. I left two alternative suggestions, please feel free to cherry pick whatever you think is useful.
  2. There's still some code duplication in the code dealing with constraints. It's not a big issue, but as replAction is already spanning over 270 lines of code, personally I would take every opportunity to keep things in check.
  3. Not really excited about response files in general, but I guess they're a necessary evil for Windows/macOS. I left a comment, but no action needed.

@mpickering mpickering added the merge me Tell Mergify Bot to merge label Jun 30, 2025
@mpickering
Copy link
Collaborator Author

Thanks @sol for the great review. A pleasure doing business with you. I applied the changes you suggested and now assigned to merge.

Programs like doctest and hie-bios want to use `cabal-install` in order
to discover the correct options to start a GHC session.  Previously they
used the `--with-compiler` option, but this led to complications since
the wrapper was called for compiling all dependencies and so on, the
shim had to be more complicated and forward arguments onto the user's
version of GHC.

The `--with-repl` command allows you to pass a program which is used
instead of GHC at the final invocation of the repl. Therefore the
wrappers don't have to deal with being a complete shim but can
concentrate on intercepting the arguments at the end.

This commit removes the special hack to not use response files with
--interactive mode. Tools are expected to deal with them appropiately,
which is much easier now only one invocation is passed to the wrapper.

Fixes #9115
@mergify mergify bot added the ready and waiting Mergify is waiting out the cooldown period label Jun 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
attention: needs-review cabal-install: cmd/repl merge me Tell Mergify Bot to merge re: --with-repl ready and waiting Mergify is waiting out the cooldown period
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature request: Add --with-repl option
6 participants