Skip to content

Commit f02772a

Browse files
authored
Merge pull request #11101 from fendor/fendor/interactive-is-the-first-argument-3.16
Always pass '--interactive' as the first ghc argument
2 parents 651120c + 01b8c86 commit f02772a

File tree

9 files changed

+120
-3
lines changed

9 files changed

+120
-3
lines changed

Cabal/src/Distribution/Simple/Program/GHC.hs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,22 @@ runGHCWithResponseFile fileNameTemplate encoding tempFileOptions verbosity ghcPr
692692

693693
runProgramInvocation verbosity newInvocation
694694

695+
-- Note [Make --interactive the first argument to GHC]
696+
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
697+
-- The ghc argument @--interactive@ needs to be the first argument to the
698+
-- ghc invocation, because Haskell Language Server used to rely on this.
699+
-- This was initially changed for Cabal 3.16, but it broke all existing Haskell
700+
-- Language Server prebuilt binaries.
701+
-- To avoid this, we uphold this assumption in Haskell Language Server until the next
702+
-- Cabal release (3.18).
703+
--
704+
-- The solution is to make sure that @--interactive@ is not passed as an argument in
705+
-- the response file that is usually passed to ghc.
706+
-- Instead, we filter out @--interactive@ and always pass it as the first argument,
707+
-- if it exists.
708+
--
709+
-- We plan to remove this Hack in Cabal 3.18.
710+
695711
-- Start the repl. Either use `ghc`, or the program specified by the --with-repl flag.
696712
runReplProgram
697713
:: Maybe FilePath
@@ -704,11 +720,23 @@ runReplProgram
704720
-> Maybe (SymbolicPath CWD (Dir Pkg))
705721
-> GhcOptions
706722
-> IO ()
707-
runReplProgram withReplProg tempFileOptions verbosity ghcProg comp platform mbWorkDir ghcOpts =
723+
runReplProgram withReplProg _tempFileOptions verbosity ghcProg comp platform mbWorkDir ghcOpts =
708724
let replProg = case withReplProg of
709725
Just path -> ghcProg{programLocation = FoundOnSystem path}
710726
Nothing -> ghcProg
711-
in runGHCWithResponseFile "ghci.rsp" Nothing tempFileOptions verbosity replProg comp platform mbWorkDir ghcOpts
727+
in do
728+
-- in runGHCWithResponseFile "ghci.rsp" Nothing tempFileOptions verbosity replProg comp platform mbWorkDir ghcOpts
729+
-- See Note [Make --interactive the first argument to GHC]
730+
-- In Cabal 3.18, restore the line above.
731+
invocation <- ghcInvocation verbosity replProg comp platform mbWorkDir ghcOpts
732+
let invocation' =
733+
let
734+
argsWithoutInteractive = filter (/= "--interactive") (progInvokeArgs invocation)
735+
in
736+
invocation
737+
{ progInvokeArgs = ["--interactive"] <> argsWithoutInteractive
738+
}
739+
runProgramInvocation verbosity invocation'
712740

713741
ghcInvocation
714742
:: Verbosity

cabal-install/src/Distribution/Client/CmdRepl.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,8 @@ replAction flags@NixStyleFlags{extraFlags = r@ReplFlags{..}, ..} targetStrings g
481481
unit_files_ordered :: [FilePath]
482482
unit_files_ordered =
483483
let (active_unit_files, other_units) = partition (\fp -> Just fp == active_unit_fp) unit_files
484-
in -- GHC considers the last unit passed to be the active one
484+
in -- older GHC versions consider the last unit passed to be the active one.
485+
-- GHC 9.14 no longer has the notion of "active" units.
485486
other_units ++ active_unit_files
486487

487488
convertParStrat :: ParStratX Int -> ParStratX String
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import System.Environment
2+
import Control.Monad
3+
4+
main :: IO ()
5+
main = putStrLn . unwords =<< getArgs
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
cabal-version: 2.4
2+
name: cabal-with-repl-exe
3+
version: 0.1.0.0
4+
build-type: Simple
5+
6+
executable test-exe
7+
main-is: Main.hs
8+
build-depends: base
9+
default-language: Haskell2010
10+
11+
library internal1
12+
hs-source-dirs: source1
13+
build-depends: base
14+
exposed-modules: Lib1
15+
default-language: Haskell2010
16+
17+
library internal2
18+
hs-source-dirs: source2
19+
build-depends: base
20+
exposed-modules: Lib2
21+
default-language: Haskell2010
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: .
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
import Distribution.Simple.Program
3+
import Distribution.Simple.Program.GHC
4+
import Distribution.Simple.Utils
5+
import Test.Cabal.Prelude
6+
7+
-- On windows this test passed but then fails in CI with
8+
--
9+
-- 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.)
10+
--
11+
12+
main = do
13+
-- Test that '--with-repl' with one target lists '--interactive' as the first argument
14+
-- This test should be deleted, once we reach Cabal 3.18, and enough HLS
15+
-- binaries have been released that support response file syntax.
16+
-- See Note [Make --interactive the first argument to GHC]
17+
mkTest "repl-single-target" $ \exePath -> do
18+
res <- cabalWithStdin "v2-repl" ["--with-repl=" ++ exePath, "test-exe"] ""
19+
assertOutputMatches "^--interactive" res
20+
mkTest "repl-multi-target" $ \exePath -> do
21+
requireGhcSupportsMultiRepl
22+
res <- cabalWithStdin "v2-repl" ["--enable-multi-repl", "--with-repl=" ++ exePath, "internal1", "internal2"] ""
23+
assertOutputMatches "^--interactive" res
24+
mkTest "repl-multi-target-all" $ \exePath -> do
25+
requireGhcSupportsMultiRepl
26+
res <- cabalWithStdin "v2-repl" ["--enable-multi-repl", "--with-repl=" ++ exePath, "all"] ""
27+
assertOutputMatches "^--interactive" res
28+
29+
30+
mkTest name act = do
31+
skipIfCIAndWindows 11026
32+
cabalTest' name $ recordMode DoNotRecord $ do
33+
-- Build the executable
34+
cabal' "v2-build" ["test-exe"]
35+
-- Get the path to the built executable
36+
withPlan $ do
37+
exePath <- planExePath "cabal-with-repl-exe" "test-exe"
38+
act exePath
39+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Lib1 where
2+
3+
y :: Int
4+
y = 42
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Lib2 where
2+
3+
x :: Int
4+
x = 42

changelog.d/pr-11101

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
synopsis: Always pass '--interactive' as the first ghc argument
2+
packages: Cabal
3+
prs: #11101
4+
issues: #11099
5+
description: {
6+
We recently changed Cabal to use response files for all GHC arguments by default.
7+
Unfortunately, this broke a couple of downstream consumers of cabal, notably Haskell Language Server and doctest, which both assume that `--interactive` is the first argument of the `ghc` invocation by `cabal repl`.
8+
9+
This regression was fixed by implementing the `--with-repl` (#9115) argument, and tools, such as hie-bios and doctest, have been updated to take advantage of this. However, this renders already published HLS binaries, so any HLS version <=2.12.0.0, incompatible with `cabal-3.16`, as these old binaries can't be easily updated.
10+
11+
In other words, no released HLS binary (at the point of this commit), is compatible with the cabal-3.16.0.0. Users have to build HLS from source to have a working toolchain.
12+
13+
To give us a slightly better migration window, we undo some of the improvements to cabal, and make sure that `--interactive` is always passed as the first argument to the underlying `ghc` invocation. This hack is supposed to be temporary, and removed for cabal 3.18.
14+
}

0 commit comments

Comments
 (0)