Skip to content

Commit dc8e137

Browse files
committed
Load session using cabal's --with-repl command
This avoids quite a lot of hacky implementations to find the correct GHC version, libdir and ghc-pkg location, as well as global package db stuff. There is a corner case which we need to handle: ``` cabal >= 3.15 && lib:Cabal <3.15 ``` In other words, when a custom-setup imposes a restriction on the `lib:Cabal` version, and this `lib:Cabal` version doesn't support the `--with-repl` flag, then we can't use `--with-repl`. We detect this by looking at the error message of the cabal command, it looks roughly like this: Error: [Cabal-7107] Could not resolve dependencies: [__0] trying: cabal-with-custom-setup-0.1.0.0 (user goal) [__1] next goal: cabal-with-custom-setup:setup.Cabal (dependency of cabal-with-custom-setup) [__1] rejecting: cabal-with-custom-setup:setup.Cabal; 3.10.3.0/installed-3.10.3.0, ... (constraint from --with-repl requires >=3.15) ... We check the error message for the existence of `constraint from --with-repl requires >=3.15` and then fall back to using the old approach which doesn't use response files or `--with-repl` flag. Additionally, we extract a new `Process` module which contains helpers for cradle actions.
1 parent 5715478 commit dc8e137

File tree

24 files changed

+359
-122
lines changed

24 files changed

+359
-122
lines changed

.github/workflows/haskell.yml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,22 @@ jobs:
1515
strategy:
1616
fail-fast: false
1717
matrix:
18-
cabal: ['3.14.1.0', '3.10.2.0']
19-
ghc: ['9.12.2', '9.10.1', '9.8.4', '9.6.7', '9.4.8']
18+
cabal: ['head', '3.14.1.0', '3.10.2.0']
19+
ghc: ['9.12.2', '9.10.1', '9.8.4', '9.6.7']
2020
os: [ubuntu-latest, macOS-latest, windows-latest]
21+
exclude:
22+
- cabal: 'head'
23+
os: macOS-latest
24+
- cabal: '3.10.2.0'
25+
ghc: '9.12.2'
2126

2227
steps:
2328
- uses: actions/checkout@v4
2429
- id: extra-ghc
2530
uses: haskell-actions/setup@v2
2631
with:
2732
cabal-version: ${{ matrix.cabal }}
28-
ghc-version: '9.2.8' # This needs to be in-sync with 'extraGhcVersion'
33+
ghc-version: '9.4.8' # This needs to be in-sync with 'extraGhcVersion'
2934

3035
- uses: haskell-actions/setup@v2
3136
with:
@@ -35,7 +40,7 @@ jobs:
3540

3641
- name: Print extra ghc version
3742
# Needs to be in sync with 'extraGhcVersion'
38-
run: ghc-9.2.8 --version
43+
run: ghc-9.4.8 --version
3944

4045
- name: Print normal ghc version
4146
run: ghc --version
@@ -93,3 +98,6 @@ jobs:
9398
ghc-version: ${{ matrix.ghc }}
9499
- name: Compile Windows wrapper
95100
run: ghc -hide-all-packages -package base -package directory -package process -Wall -Werror wrappers/cabal.hs -o CabalWrapper
101+
102+
- name: Compile `--with-repl` Windows wrapper
103+
run: ghc -hide-all-packages -package base -package directory -package process -Wall -Werror wrappers/cabal-with-repl.hs -o CabalWithReplWrapper

hie-bios.cabal

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,20 @@ Build-Type: Simple
1515
extra-doc-files: ChangeLog.md
1616
Extra-Source-Files: README.md
1717
wrappers/cabal
18+
wrappers/cabal-with-repl
1819
wrappers/cabal.hs
20+
wrappers/cabal-with-repl.hs
1921
tests/configs/*.yaml
2022
tests/projects/cabal-with-ghc/cabal-with-ghc.cabal
2123
tests/projects/cabal-with-ghc/cabal.project
2224
tests/projects/cabal-with-ghc/hie.yaml
2325
tests/projects/cabal-with-ghc/src/MyLib.hs
2426
tests/projects/cabal-with-ghc-and-project/cabal-with-ghc.cabal
25-
tests/projects/cabal-with-ghc-and-project/cabal.project.9.2.8
27+
tests/projects/cabal-with-ghc-and-project/cabal.project.extra
2628
tests/projects/cabal-with-ghc-and-project/hie.yaml
2729
tests/projects/cabal-with-ghc-and-project/src/MyLib.hs
2830
tests/projects/cabal-with-project/cabal-with-project.cabal
29-
tests/projects/cabal-with-project/cabal.project.9.2.8
31+
tests/projects/cabal-with-project/cabal.project.extra
3032
tests/projects/cabal-with-project/hie.yaml
3133
tests/projects/cabal-with-project/src/MyLib.hs
3234
tests/projects/symlink-test/a/A.hs
@@ -47,7 +49,7 @@ Extra-Source-Files: README.md
4749
tests/projects/multi-cabal-with-project/appA/src/Lib.hs
4850
tests/projects/multi-cabal-with-project/appB/appB.cabal
4951
tests/projects/multi-cabal-with-project/appB/src/Lib.hs
50-
tests/projects/multi-cabal-with-project/cabal.project.9.2.8
52+
tests/projects/multi-cabal-with-project/cabal.project.extra
5153
tests/projects/multi-cabal-with-project/hie.yaml
5254
tests/projects/monorepo-cabal/cabal.project
5355
tests/projects/monorepo-cabal/hie.yaml
@@ -144,7 +146,7 @@ Extra-Source-Files: README.md
144146
tests/projects/failing-multi-repl-cabal-project/multi-repl-cabal-fail/src/Lib.hs
145147
tests/projects/failing-multi-repl-cabal-project/NotInPath.hs
146148

147-
tested-with: GHC ==9.4.8 || ==9.6.7 || ==9.8.4 || ==9.10.1 || ==9.12.2
149+
tested-with: GHC ==9.6.7 || ==9.8.4 || ==9.10.1 || ==9.12.2
148150

149151
Library
150152
Default-Language: Haskell2010

src/HIE/Bios/Cradle.hs

Lines changed: 228 additions & 87 deletions
Large diffs are not rendered by default.

src/HIE/Bios/Process.hs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
{-# LANGUAGE BangPatterns #-}
22
{-# LANGUAGE TupleSections #-}
33
{-# LANGUAGE ScopedTypeVariables #-}
4-
module HIE.Bios.Process where
4+
module HIE.Bios.Process
5+
( CreateProcess(..)
6+
-- * Run processes with extra environment variables
7+
, readProcessWithCwd
8+
, readProcessWithCwd_
9+
, readProcessWithCwd'
10+
, readProcessWithOutputs
11+
, getCleanEnvironment
12+
-- * Find file utilities
13+
, findFileUpwards
14+
, findFileUpwardsPredicate
15+
, findFile
16+
)
17+
where
518

619
import Control.Applicative (optional)
720
import Control.DeepSeq

src/HIE/Bios/Types.hs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import qualified Control.Monad.Fail as Fail
1616
import Data.Maybe (fromMaybe)
1717
import qualified Data.Text as T
1818
import Prettyprinter
19-
import System.Process.Extra (CreateProcess (env, cmdspec), CmdSpec (..))
19+
import System.Process.Extra (CreateProcess (env, cmdspec), CmdSpec (..), showCommandForUser)
2020

2121
----------------------------------------------------------------
2222
-- Environment variables used by hie-bios.
@@ -106,6 +106,7 @@ data Log
106106
| LogComputedCradleLoadStyle !T.Text !LoadStyle
107107
| LogLoadWithContextUnsupported !T.Text !(Maybe T.Text)
108108
| LogCabalLoad !FilePath !(Maybe String) ![FilePath] ![FilePath]
109+
| LogCabalLibraryTooOld [String]
109110
| LogCabalPath !T.Text
110111
deriving (Show)
111112

@@ -148,6 +149,9 @@ instance Pretty Log where
148149
<> line <> indent 4 "from project: " <+> pretty projectFile
149150
<> line <> indent 4 "with prefixes:" <+> pretty prefixes
150151
<> line <> indent 4 "with actual loading files:" <+> pretty crs
152+
pretty (LogCabalLibraryTooOld err) =
153+
"'lib:Cabal' is too old to use '--with-repl' flag. Requires 'lib:Cabal' >= 3.15. Original error:" <> line
154+
<> vcat (fmap pretty err)
151155
pretty (LogCabalPath err) =
152156
"Could not parse json output of 'cabal path': "
153157
<> line <> indent 4 (pretty err)
@@ -316,12 +320,18 @@ data ComponentOptions = ComponentOptions {
316320
-- | Prettify 'CmdSpec', so we can show the command to a user
317321
prettyCmdSpec :: CmdSpec -> String
318322
prettyCmdSpec (ShellCommand s) = s
319-
prettyCmdSpec (RawCommand cmd args) = cmd ++ " " ++ unwords args
323+
prettyCmdSpec (RawCommand cmd args) = showCommandForUser cmd args
320324

321325
-- | Pretty print hie-bios's relevant environment variables.
322326
prettyProcessEnv :: CreateProcess -> [String]
323327
prettyProcessEnv p =
324328
[ key <> ": " <> value
329+
| (key, value) <- hieBiosProcessEnv p
330+
]
331+
332+
hieBiosProcessEnv :: CreateProcess -> [(String, String)]
333+
hieBiosProcessEnv p =
334+
[ (key, value)
325335
| (key, value) <- fromMaybe [] (env p)
326336
, key `elem` [ hie_bios_output
327337
, hie_bios_ghc

src/HIE/Bios/Wrappers.hs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
1-
{-# LANGUAGE TemplateHaskell #-}
21
{-# LANGUAGE QuasiQuotes #-}
3-
{-# LANGUAGE CPP #-}
4-
module HIE.Bios.Wrappers (cabalWrapper, cabalWrapperHs) where
2+
{-# LANGUAGE TemplateHaskell #-}
53

6-
import Data.FileEmbed
7-
#if __GLASGOW_HASKELL__ >= 903
8-
hiding (makeRelativeToProject)
9-
#endif
10-
import Language.Haskell.TH.Syntax
4+
module HIE.Bios.Wrappers (
5+
cabalWrapper,
6+
cabalWithReplWrapper,
7+
cabalWrapperHs,
8+
cabalWithReplWrapperHs,
9+
) where
10+
11+
import Data.FileEmbed ( embedStringFile )
12+
import Language.Haskell.TH.Syntax ( makeRelativeToProject )
1113

1214
cabalWrapper :: String
1315
cabalWrapper = $(makeRelativeToProject "wrappers/cabal" >>= embedStringFile)
1416

1517
cabalWrapperHs :: String
1618
cabalWrapperHs = $(makeRelativeToProject "wrappers/cabal.hs" >>= embedStringFile)
1719

20+
cabalWithReplWrapper :: String
21+
cabalWithReplWrapper = $(makeRelativeToProject "wrappers/cabal-with-repl" >>= embedStringFile)
22+
23+
cabalWithReplWrapperHs :: String
24+
cabalWithReplWrapperHs = $(makeRelativeToProject "wrappers/cabal-with-repl.hs" >>= embedStringFile)

tests/BiosTests.hs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ import HIE.Bios.Cradle
1818
import Control.Monad ( forM_ )
1919
import Data.List ( sort, isPrefixOf )
2020
import Data.Typeable
21+
import System.Exit (ExitCode(ExitSuccess, ExitFailure))
2122
import System.Directory
2223
import System.FilePath ((</>), makeRelative)
23-
import System.Exit (ExitCode(ExitSuccess, ExitFailure))
24+
import System.Info.Extra (isWindows)
2425
import Control.Monad.Extra (unlessM)
2526
import qualified HIE.Bios.Ghc.Gap as Gap
2627
import Control.Monad.IO.Class
@@ -34,7 +35,7 @@ argDynamic = ["-dynamic" | Gap.hostIsDynamic]
3435
-- If you change this version, make sure to also update 'cabal.project'
3536
-- in 'tests\/projects\/cabal-with-ghc'.
3637
extraGhcVersion :: String
37-
extraGhcVersion = "9.2.8"
38+
extraGhcVersion = "9.4.8"
3839

3940
extraGhc :: String
4041
extraGhc = "ghc-" ++ extraGhcVersion
@@ -123,7 +124,11 @@ biosTestCases =
123124
cradleErrorExitCode @?= ExitSuccess
124125
cradleErrorDependencies `shouldMatchList` []
125126
length cradleErrorStderr @?= 1
126-
"Couldn't execute myGhc" `isPrefixOf` head cradleErrorStderr @? "Error message should contain basic information"
127+
let errorCtx = head cradleErrorStderr
128+
-- On windows, this error message contains '"' around the executable name
129+
if isWindows
130+
then "Couldn't execute \"myGhc\"" `isPrefixOf` errorCtx @? "Error message should contain error information"
131+
else "Couldn't execute myGhc" `isPrefixOf` errorCtx @? "Error message should contain error information"
127132
, biosTestCase "simple-bios-shell" $ runTestEnv "./simple-bios-shell" $ do
128133
testDirectoryM isBiosCradle "B.hs"
129134
, biosTestCase "simple-bios-shell-deps" $ runTestEnv "./simple-bios-shell" $ do
@@ -242,6 +247,12 @@ cabalTestCases extraGhcDep =
242247
loadRuntimeGhcVersion
243248
assertGhcVersionIs extraGhcVersion
244249
]
250+
, biosTestCase "force older Cabal version in custom setup" $ runTestEnv "cabal-with-custom-setup" $ do
251+
-- Specifically tests whether cabal 3.16 works as expected with
252+
-- an older lib:Cabal version that doesn't support '--with-repl'.
253+
-- This test doesn't hurt for other cases as well, so we enable it for
254+
-- all configurations.
255+
testDirectoryM isCabalCradle "src/MyLib.hs"
245256
]
246257
]
247258
where
@@ -358,7 +369,6 @@ biosTestCase name assertion = askOption @VerboseLogging (\case
358369
VerboseLogging verbose -> testCase name (assertion verbose)
359370
)
360371

361-
362372
-- ------------------------------------------------------------------
363373
-- Stack related helper functions
364374
-- ------------------------------------------------------------------

tests/ParserTests.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ main = defaultMain $
6262
,("./tests", StackType (Just "parser-tests") Nothing)]))]))
6363
-- Assertions for cabal.project files
6464
assertParser "cabal-with-project.yaml"
65-
(noDeps (Cabal $ CabalType Nothing (Just "cabal.project.9.2.8")))
65+
(noDeps (Cabal $ CabalType Nothing (Just "cabal.project.extra")))
6666
assertParser "cabal-with-both.yaml"
67-
(noDeps (Cabal $ CabalType (Just "hie-bios:hie") (Just "cabal.project.9.2.8")))
67+
(noDeps (Cabal $ CabalType (Just "hie-bios:hie") (Just "cabal.project.extra")))
6868
assertParser "multi-cabal-with-project.yaml"
69-
(noDeps (CabalMulti (CabalType Nothing (Just "cabal.project.9.2.8"))
69+
(noDeps (CabalMulti (CabalType Nothing (Just "cabal.project.extra"))
7070
[("./src", CabalType (Just "lib:hie-bios") Nothing)
7171
,("./vendor", CabalType (Just "parser-tests") Nothing)]))
7272
-- Assertions for stack.yaml files

tests/configs/cabal-with-both.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
cradle:
22
cabal:
3-
cabalProject: "cabal.project.9.2.8"
3+
cabalProject: "cabal.project.extra"
44
component: "hie-bios:hie"

tests/configs/cabal-with-project.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
cradle:
22
cabal:
3-
cabalProject: "cabal.project.9.2.8"
3+
cabalProject: "cabal.project.extra"

0 commit comments

Comments
 (0)