@@ -26,11 +26,11 @@ import Data.Ord (Down(..))
26
26
import Data.String (IsString (.. ))
27
27
import qualified Data.Text as T
28
28
import Data.Foldable (toList )
29
- import Control.Exception ( IOException , try , catch )
29
+ import Control.Exception
30
30
import System.FilePath
31
31
import System.Directory (getCurrentDirectory , canonicalizePath , findExecutable )
32
32
import System.Exit
33
- import System.Process (readCreateProcess , shell )
33
+ import System.Process (readCreateProcessWithExitCode , shell )
34
34
35
35
-- | Find the cradle that the given File belongs to.
36
36
--
@@ -76,42 +76,76 @@ isCabalCradle =
76
76
. BIOS. actionName
77
77
. BIOS. cradleOptsProg
78
78
79
-
80
- getProjectGhcPath :: Cradle -> IO (Maybe FilePath )
81
- getProjectGhcPath crdl = do
79
+ -- | Execute @ghc@ that is based on the given cradle.
80
+ -- Output must be a single line. If an error is raised, e.g. the command
81
+ -- failed, a @Nothing@ is returned.
82
+ -- The exact error is written to logs.
83
+ --
84
+ -- E.g. for a stack cradle, we use `stack ghc` and for a cabal cradle
85
+ -- we are taking the @ghc@ that is on the path.
86
+ execProjectGhc :: Cradle -> [String ] -> IO (Maybe String )
87
+ execProjectGhc crdl args = do
82
88
isStackInstalled <- isJust <$> findExecutable " stack"
83
- isCabalInstalled <- isJust <$> findExecutable " cabal"
89
+ -- isCabalInstalled <- isJust <$> findExecutable "cabal"
84
90
ghcpath <- if isStackCradle crdl && isStackInstalled
85
- then
86
- catch (Just <$> tryCommand " stack path --compiler-exe" ) $ \ (_ :: IOException ) -> do
87
- errorm " Command `stack path --compiler-exe` failed."
88
- return Nothing
89
- else if isCabalCradle crdl && isCabalInstalled then do
90
- ghcCabalVersion <- catch (Just <$> tryCommand " cabal v2-exec -v0 ghc -- --numeric-version" ) $ \ (_ :: IOException ) -> do
91
- errorm " Command `cabal v2-exec -v0 ghc -- --numeric-version` failed."
92
- return Nothing
93
- case ghcCabalVersion of
94
- Just ghcNumericVersion -> do
95
- let ghcVersion = " ghc-" ++ ghcNumericVersion
96
- logm $ " Ghc Version to find: " ++ ghcVersion
97
- findExecutable ghcVersion
98
- Nothing -> return Nothing
91
+ then do
92
+ logm " Use Stack GHC"
93
+ catch (Just <$> tryCommand stackCmd) $ \ (_ :: IOException ) -> do
94
+ errorm $ " Command `" ++ stackCmd ++ " ` failed."
95
+ execWithGhc
96
+ -- The command `cabal v2-exec -v0 ghc` only works if the project has been
97
+ -- built already.
98
+ -- This command must work though before the project is build.
99
+ -- Therefore, fallback to "ghc" on the path.
100
+ --
101
+ -- else if isCabalCradle crdl && isCabalInstalled then do
102
+ -- let cmd = "cabal v2-exec -v0 ghc -- " ++ unwords args
103
+ -- catch (Just <$> tryCommand cmd) $ \(_ ::IOException) -> do
104
+ -- errorm $ "Command `" ++ cmd ++ "` failed."
105
+ -- return Nothing
99
106
else do
100
- logm " Neither cabal nor stack project, look for ghc project. "
101
- findExecutable " ghc "
102
- logm $ " Found ghc path : " ++ show ghcpath
107
+ logm " Use Plain GHC "
108
+ execWithGhc
109
+ debugm $ " Output from : " ++ show ghcpath
103
110
return ghcpath
111
+ where
112
+ stackCmd = " stack ghc -- " ++ unwords args
113
+ plainCmd = " ghc " ++ unwords args
104
114
105
- tryCommand :: String -> IO String
106
- tryCommand cmd =
107
- T. unpack . T. strip . T. pack <$> readCreateProcess (shell cmd) " "
115
+ execWithGhc =
116
+ catch (Just <$> tryCommand plainCmd) $ \ (_ :: IOException ) -> do
117
+ errorm $ " Command `" ++ plainCmd ++ " ` failed."
118
+ return Nothing
108
119
120
+ tryCommand :: String -> IO String
121
+ tryCommand cmd = do
122
+ (code, sout, serr) <- readCreateProcessWithExitCode (shell cmd) " "
123
+ case code of
124
+ ExitFailure e -> do
125
+ let errmsg = concat
126
+ [ " `"
127
+ , cmd
128
+ , " `: Exit failure: "
129
+ , show e
130
+ , " , stdout: "
131
+ , sout
132
+ , " , stderr: "
133
+ , serr
134
+ ]
135
+ errorm errmsg
136
+ throwIO $ userError errmsg
137
+
138
+ ExitSuccess -> return $ T. unpack . T. strip . head . T. lines $ T. pack sout
139
+
140
+
141
+ -- | Get the directory of the libdir based on the project ghc.
109
142
getProjectGhcLibDir :: Cradle -> IO (Maybe FilePath )
110
- getProjectGhcLibDir crdl = do
111
- mGhcPath <- getProjectGhcPath crdl
112
- case mGhcPath of
113
- Nothing -> return Nothing
114
- Just ghcPath -> catch (Just <$> tryCommand (ghcPath ++ " --print-libdir" )) $ \ (_ :: IOException ) -> return Nothing
143
+ getProjectGhcLibDir crdl =
144
+ catch
145
+ (execProjectGhc crdl [" --print-libdir" ])
146
+ $ \ (_ :: IOException ) -> do
147
+ logm " Could not obtain the libdir."
148
+ return Nothing
115
149
116
150
-- ---------------------------------------------------------------------
117
151
0 commit comments