1 -----------------------------------------------------------------------------
3 -----------------------------------------------------------------------------
6 -- Module : Distribution.Client.Run
7 -- Maintainer : cabal-devel@haskell.org
8 -- Portability : portable
10 -- Implementation of the 'run' command.
11 module Distribution
.Client
.Run
(run
, splitRunArgs
)
14 import Distribution
.Client
.Compat
.Prelude
17 import Distribution
.Types
.LocalBuildInfo
(componentNameTargets
')
18 import Distribution
.Types
.TargetInfo
(targetCLBI
)
20 import Distribution
.Client
.Utils
(tryCanonicalizePath
)
22 import Distribution
.PackageDescription
24 , BuildInfo
(buildable
)
26 , PackageDescription
(..)
29 import Distribution
.Simple
.Build
.PathsModule
(pkgPathEnvVar
)
30 import Distribution
.Simple
.BuildPaths
(exeExtension
)
31 import Distribution
.Simple
.Compiler
(CompilerFlavor
(..), compilerFlavor
)
32 import Distribution
.Simple
.LocalBuildInfo
37 import Distribution
.Simple
.Utils
41 , rawSystemExitWithEnv
44 import Distribution
.System
(Platform
(..))
45 import Distribution
.Types
.UnqualComponentName
47 import qualified Distribution
.Simple
.GHCJS
as GHCJS
49 import Distribution
.Client
.Errors
50 import Distribution
.Compat
.Environment
(getEnvironment
)
51 import System
.Directory
(getCurrentDirectory)
52 import System
.FilePath ((<.>), (</>))
54 -- | Return the executable to run and any extra arguments that should be
55 -- forwarded to it. Die in case of error.
60 -> IO (Executable
, [String])
61 splitRunArgs verbosity lbi args
=
62 case whichExecutable
of -- Either err (wasManuallyChosen, exe, paramsRest)
64 warn verbosity `traverse_` maybeWarning
-- If there is a warning, print it.
65 dieWithException verbosity
$ SplitRunArgs err
66 Right
(True, exe
, xs
) -> return (exe
, xs
)
67 Right
(False, exe
, xs
) -> do
69 " Interpreting all parameters to `run` as a parameter to"
70 ++ " the default executable."
71 -- If there is a warning, print it together with the addition.
72 warn verbosity `traverse_`
fmap (++ addition) maybeWarning
75 pkg_descr
= localPkgDescr lbi
78 String -- Error string.
79 ( Bool -- If it was manually chosen.
80 , Executable
-- The executable.
81 , [String] -- The remaining parameters.
83 whichExecutable
= case (enabledExes
, args
) of
84 ([], _
) -> Left
"Couldn't find any enabled executables."
85 ([exe
], []) -> return (False, exe
, [])
87 | x
== unUnqualComponentName
(exeName exe
) -> return (True, exe
, xs
)
88 |
otherwise -> return (False, exe
, args
)
91 "This package contains multiple executables. "
92 ++ "You must pass the executable name as the first argument "
95 case find (\exe
-> unUnqualComponentName
(exeName exe
) == x
) enabledExes
of
96 Nothing
-> Left
$ "No executable named '" ++ x
++ "'."
97 Just exe
-> return (True, exe
, xs
)
99 enabledExes
= filter (buildable
. buildInfo
) (executables pkg_descr
)
101 maybeWarning
:: Maybe String
102 maybeWarning
= case args
of
104 (x
: _
) -> lookup (mkUnqualComponentName x
) components
106 components
:: [(UnqualComponentName
, String)] -- Component name, message.
108 [ (name
, "The executable '" ++ prettyShow name
++ "' is disabled.")
109 | e
<- executables pkg_descr
110 , not . buildable
. buildInfo
$ e
111 , let name
= exeName e
114 , "There is a test-suite '"
117 ++ " but the `run` command is only for executables."
119 | t
<- testSuites pkg_descr
120 , let name
= testName t
123 , "There is a benchmark '"
126 ++ " but the `run` command is only for executables."
128 | b
<- benchmarks pkg_descr
129 , let name
= benchmarkName b
132 -- | Run a given executable.
133 run
:: Verbosity
-> LocalBuildInfo
-> Executable
-> [String] -> IO ()
134 run verbosity lbi exe exeArgs
= do
135 curDir
<- getCurrentDirectory
136 let buildPref
= buildDir lbi
137 pkg_descr
= localPkgDescr lbi
139 ( pkgPathEnvVar pkg_descr
"datadir"
140 , curDir
</> dataDir pkg_descr
144 let exeName
' = prettyShow
$ exeName exe
145 in case compilerFlavor
(compiler lbi
) of
147 let (script
, cmd
, cmdArgs
) =
150 (buildPref
</> exeName
' </> exeName
')
151 script
' <- tryCanonicalizePath script
152 return (cmd
, cmdArgs
++ [script
'])
155 tryCanonicalizePath
$
156 buildPref
</> exeName
' </> (exeName
' <.> exeExtension
(hostPlatform lbi
))
159 env
<- (dataDirEnvVar
:) <$> getEnvironment
160 -- Add (DY)LD_LIBRARY_PATH if needed
164 let (Platform _ os
) = hostPlatform lbi
165 clbi
<- case componentNameTargets
' pkg_descr lbi
(CExeName
(exeName exe
)) of
166 [target
] -> return (targetCLBI target
)
167 [] -> dieWithException verbosity CouldNotFindExecutable
168 _
-> dieWithException verbosity FoundMultipleMatchingExes
169 paths
<- depLibraryPaths
True False lbi clbi
170 return (addLibraryPath os paths env
)
172 notice verbosity
$ "Running " ++ prettyShow
(exeName exe
) ++ "..."
173 rawSystemExitWithEnv verbosity path
(runArgs
++ exeArgs
) env
'