{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
module Distribution.Simple.Program.Run (
ProgramInvocation(..),
IOEncoding(..),
emptyProgramInvocation,
simpleProgramInvocation,
programInvocation,
multiStageProgramInvocation,
runProgramInvocation,
getProgramInvocationOutput,
getProgramInvocationLBS,
getProgramInvocationOutputAndErrors,
getEffectiveEnvironment,
) where
import Distribution.Compat.Prelude
import Prelude ()
import Distribution.Compat.Environment
import Distribution.Simple.Program.Types
import Distribution.Simple.Utils
import Distribution.Utils.Generic
import Distribution.Verbosity
import System.FilePath (searchPathSeparator)
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Map as Map
data ProgramInvocation = ProgramInvocation {
ProgramInvocation -> String
progInvokePath :: FilePath,
ProgramInvocation -> [String]
progInvokeArgs :: [String],
ProgramInvocation -> [(String, Maybe String)]
progInvokeEnv :: [(String, Maybe String)],
ProgramInvocation -> [String]
progInvokePathEnv :: [FilePath],
ProgramInvocation -> Maybe String
progInvokeCwd :: Maybe FilePath,
ProgramInvocation -> Maybe IOData
progInvokeInput :: Maybe IOData,
ProgramInvocation -> IOEncoding
progInvokeInputEncoding :: IOEncoding,
ProgramInvocation -> IOEncoding
progInvokeOutputEncoding :: IOEncoding
}
data IOEncoding = IOEncodingText
| IOEncodingUTF8
encodeToIOData :: IOEncoding -> IOData -> IOData
encodeToIOData :: IOEncoding -> IOData -> IOData
encodeToIOData IOEncoding
_ iod :: IOData
iod@(IODataBinary ByteString
_) = IOData
iod
encodeToIOData IOEncoding
IOEncodingText iod :: IOData
iod@(IODataText String
_) = IOData
iod
encodeToIOData IOEncoding
IOEncodingUTF8 (IODataText String
str) = ByteString -> IOData
IODataBinary (String -> ByteString
toUTF8LBS String
str)
emptyProgramInvocation :: ProgramInvocation
emptyProgramInvocation :: ProgramInvocation
emptyProgramInvocation =
ProgramInvocation {
progInvokePath :: String
progInvokePath = String
"",
progInvokeArgs :: [String]
progInvokeArgs = [],
progInvokeEnv :: [(String, Maybe String)]
progInvokeEnv = [],
progInvokePathEnv :: [String]
progInvokePathEnv = [],
progInvokeCwd :: Maybe String
progInvokeCwd = forall a. Maybe a
Nothing,
progInvokeInput :: Maybe IOData
progInvokeInput = forall a. Maybe a
Nothing,
progInvokeInputEncoding :: IOEncoding
progInvokeInputEncoding = IOEncoding
IOEncodingText,
progInvokeOutputEncoding :: IOEncoding
progInvokeOutputEncoding = IOEncoding
IOEncodingText
}
simpleProgramInvocation :: FilePath -> [String] -> ProgramInvocation
simpleProgramInvocation :: String -> [String] -> ProgramInvocation
simpleProgramInvocation String
path [String]
args =
ProgramInvocation
emptyProgramInvocation {
progInvokePath :: String
progInvokePath = String
path,
progInvokeArgs :: [String]
progInvokeArgs = [String]
args
}
programInvocation :: ConfiguredProgram -> [String] -> ProgramInvocation
programInvocation :: ConfiguredProgram -> [String] -> ProgramInvocation
programInvocation ConfiguredProgram
prog [String]
args =
ProgramInvocation
emptyProgramInvocation {
progInvokePath :: String
progInvokePath = ConfiguredProgram -> String
programPath ConfiguredProgram
prog,
progInvokeArgs :: [String]
progInvokeArgs = ConfiguredProgram -> [String]
programDefaultArgs ConfiguredProgram
prog
forall a. [a] -> [a] -> [a]
++ [String]
args
forall a. [a] -> [a] -> [a]
++ ConfiguredProgram -> [String]
programOverrideArgs ConfiguredProgram
prog,
progInvokeEnv :: [(String, Maybe String)]
progInvokeEnv = ConfiguredProgram -> [(String, Maybe String)]
programOverrideEnv ConfiguredProgram
prog
}
runProgramInvocation :: Verbosity -> ProgramInvocation -> IO ()
runProgramInvocation :: Verbosity -> ProgramInvocation -> IO ()
runProgramInvocation Verbosity
verbosity
ProgramInvocation {
progInvokePath :: ProgramInvocation -> String
progInvokePath = String
path,
progInvokeArgs :: ProgramInvocation -> [String]
progInvokeArgs = [String]
args,
progInvokeEnv :: ProgramInvocation -> [(String, Maybe String)]
progInvokeEnv = [],
progInvokePathEnv :: ProgramInvocation -> [String]
progInvokePathEnv = [],
progInvokeCwd :: ProgramInvocation -> Maybe String
progInvokeCwd = Maybe String
Nothing,
progInvokeInput :: ProgramInvocation -> Maybe IOData
progInvokeInput = Maybe IOData
Nothing
} =
Verbosity -> String -> [String] -> IO ()
rawSystemExit Verbosity
verbosity String
path [String]
args
runProgramInvocation Verbosity
verbosity
ProgramInvocation {
progInvokePath :: ProgramInvocation -> String
progInvokePath = String
path,
progInvokeArgs :: ProgramInvocation -> [String]
progInvokeArgs = [String]
args,
progInvokeEnv :: ProgramInvocation -> [(String, Maybe String)]
progInvokeEnv = [(String, Maybe String)]
envOverrides,
progInvokePathEnv :: ProgramInvocation -> [String]
progInvokePathEnv = [String]
extraPath,
progInvokeCwd :: ProgramInvocation -> Maybe String
progInvokeCwd = Maybe String
mcwd,
progInvokeInput :: ProgramInvocation -> Maybe IOData
progInvokeInput = Maybe IOData
Nothing
} = do
[(String, Maybe String)]
pathOverride <- [(String, Maybe String)] -> [String] -> IO [(String, Maybe String)]
getExtraPathEnv [(String, Maybe String)]
envOverrides [String]
extraPath
Maybe [(String, String)]
menv <- [(String, Maybe String)] -> IO (Maybe [(String, String)])
getEffectiveEnvironment ([(String, Maybe String)]
envOverrides forall a. [a] -> [a] -> [a]
++ [(String, Maybe String)]
pathOverride)
ExitCode
exitCode <- Verbosity
-> String
-> [String]
-> Maybe String
-> Maybe [(String, String)]
-> Maybe Handle
-> Maybe Handle
-> Maybe Handle
-> IO ExitCode
rawSystemIOWithEnv Verbosity
verbosity
String
path [String]
args
Maybe String
mcwd Maybe [(String, String)]
menv
forall a. Maybe a
Nothing forall a. Maybe a
Nothing forall a. Maybe a
Nothing
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ExitCode
exitCode forall a. Eq a => a -> a -> Bool
/= ExitCode
ExitSuccess) forall a b. (a -> b) -> a -> b
$
forall a. ExitCode -> IO a
exitWith ExitCode
exitCode
runProgramInvocation Verbosity
verbosity
ProgramInvocation {
progInvokePath :: ProgramInvocation -> String
progInvokePath = String
path,
progInvokeArgs :: ProgramInvocation -> [String]
progInvokeArgs = [String]
args,
progInvokeEnv :: ProgramInvocation -> [(String, Maybe String)]
progInvokeEnv = [(String, Maybe String)]
envOverrides,
progInvokePathEnv :: ProgramInvocation -> [String]
progInvokePathEnv = [String]
extraPath,
progInvokeCwd :: ProgramInvocation -> Maybe String
progInvokeCwd = Maybe String
mcwd,
progInvokeInput :: ProgramInvocation -> Maybe IOData
progInvokeInput = Just IOData
inputStr,
progInvokeInputEncoding :: ProgramInvocation -> IOEncoding
progInvokeInputEncoding = IOEncoding
encoding
} = do
[(String, Maybe String)]
pathOverride <- [(String, Maybe String)] -> [String] -> IO [(String, Maybe String)]
getExtraPathEnv [(String, Maybe String)]
envOverrides [String]
extraPath
Maybe [(String, String)]
menv <- [(String, Maybe String)] -> IO (Maybe [(String, String)])
getEffectiveEnvironment ([(String, Maybe String)]
envOverrides forall a. [a] -> [a] -> [a]
++ [(String, Maybe String)]
pathOverride)
(ByteString
_, String
errors, ExitCode
exitCode) <- forall mode.
KnownIODataMode mode =>
Verbosity
-> String
-> [String]
-> Maybe String
-> Maybe [(String, String)]
-> Maybe IOData
-> IODataMode mode
-> IO (mode, String, ExitCode)
rawSystemStdInOut Verbosity
verbosity
String
path [String]
args
Maybe String
mcwd Maybe [(String, String)]
menv
(forall a. a -> Maybe a
Just IOData
input) IODataMode ByteString
IODataModeBinary
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ExitCode
exitCode forall a. Eq a => a -> a -> Bool
/= ExitCode
ExitSuccess) forall a b. (a -> b) -> a -> b
$
forall a. Verbosity -> String -> IO a
die' Verbosity
verbosity forall a b. (a -> b) -> a -> b
$ String
"'" forall a. [a] -> [a] -> [a]
++ String
path forall a. [a] -> [a] -> [a]
++ String
"' exited with an error:\n" forall a. [a] -> [a] -> [a]
++ String
errors
where
input :: IOData
input = IOEncoding -> IOData -> IOData
encodeToIOData IOEncoding
encoding IOData
inputStr
getProgramInvocationOutput :: Verbosity -> ProgramInvocation -> IO String
getProgramInvocationOutput :: Verbosity -> ProgramInvocation -> IO String
getProgramInvocationOutput Verbosity
verbosity ProgramInvocation
inv = do
(String
output, String
errors, ExitCode
exitCode) <- Verbosity -> ProgramInvocation -> IO (String, String, ExitCode)
getProgramInvocationOutputAndErrors Verbosity
verbosity ProgramInvocation
inv
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ExitCode
exitCode forall a. Eq a => a -> a -> Bool
/= ExitCode
ExitSuccess) forall a b. (a -> b) -> a -> b
$
forall a. Verbosity -> String -> IO a
die' Verbosity
verbosity forall a b. (a -> b) -> a -> b
$ String
"'" forall a. [a] -> [a] -> [a]
++ ProgramInvocation -> String
progInvokePath ProgramInvocation
inv forall a. [a] -> [a] -> [a]
++ String
"' exited with an error:\n" forall a. [a] -> [a] -> [a]
++ String
errors
forall (m :: * -> *) a. Monad m => a -> m a
return String
output
getProgramInvocationLBS :: Verbosity -> ProgramInvocation -> IO LBS.ByteString
getProgramInvocationLBS :: Verbosity -> ProgramInvocation -> IO ByteString
getProgramInvocationLBS Verbosity
verbosity ProgramInvocation
inv = do
(ByteString
output, String
errors, ExitCode
exitCode) <- forall mode.
KnownIODataMode mode =>
Verbosity
-> ProgramInvocation
-> IODataMode mode
-> IO (mode, String, ExitCode)
getProgramInvocationIODataAndErrors Verbosity
verbosity ProgramInvocation
inv IODataMode ByteString
IODataModeBinary
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ExitCode
exitCode forall a. Eq a => a -> a -> Bool
/= ExitCode
ExitSuccess) forall a b. (a -> b) -> a -> b
$
forall a. Verbosity -> String -> IO a
die' Verbosity
verbosity forall a b. (a -> b) -> a -> b
$ String
"'" forall a. [a] -> [a] -> [a]
++ ProgramInvocation -> String
progInvokePath ProgramInvocation
inv forall a. [a] -> [a] -> [a]
++ String
"' exited with an error:\n" forall a. [a] -> [a] -> [a]
++ String
errors
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
output
getProgramInvocationOutputAndErrors :: Verbosity -> ProgramInvocation
-> IO (String, String, ExitCode)
getProgramInvocationOutputAndErrors :: Verbosity -> ProgramInvocation -> IO (String, String, ExitCode)
getProgramInvocationOutputAndErrors Verbosity
verbosity ProgramInvocation
inv = case ProgramInvocation -> IOEncoding
progInvokeOutputEncoding ProgramInvocation
inv of
IOEncoding
IOEncodingText -> do
(String
output, String
errors, ExitCode
exitCode) <- forall mode.
KnownIODataMode mode =>
Verbosity
-> ProgramInvocation
-> IODataMode mode
-> IO (mode, String, ExitCode)
getProgramInvocationIODataAndErrors Verbosity
verbosity ProgramInvocation
inv IODataMode String
IODataModeText
forall (m :: * -> *) a. Monad m => a -> m a
return (String
output, String
errors, ExitCode
exitCode)
IOEncoding
IOEncodingUTF8 -> do
(ByteString
output', String
errors, ExitCode
exitCode) <- forall mode.
KnownIODataMode mode =>
Verbosity
-> ProgramInvocation
-> IODataMode mode
-> IO (mode, String, ExitCode)
getProgramInvocationIODataAndErrors Verbosity
verbosity ProgramInvocation
inv IODataMode ByteString
IODataModeBinary
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> String
normaliseLineEndings (ByteString -> String
fromUTF8LBS ByteString
output'), String
errors, ExitCode
exitCode)
getProgramInvocationIODataAndErrors
:: KnownIODataMode mode => Verbosity -> ProgramInvocation -> IODataMode mode
-> IO (mode, String, ExitCode)
getProgramInvocationIODataAndErrors :: forall mode.
KnownIODataMode mode =>
Verbosity
-> ProgramInvocation
-> IODataMode mode
-> IO (mode, String, ExitCode)
getProgramInvocationIODataAndErrors
Verbosity
verbosity
ProgramInvocation
{ progInvokePath :: ProgramInvocation -> String
progInvokePath = String
path
, progInvokeArgs :: ProgramInvocation -> [String]
progInvokeArgs = [String]
args
, progInvokeEnv :: ProgramInvocation -> [(String, Maybe String)]
progInvokeEnv = [(String, Maybe String)]
envOverrides
, progInvokePathEnv :: ProgramInvocation -> [String]
progInvokePathEnv = [String]
extraPath
, progInvokeCwd :: ProgramInvocation -> Maybe String
progInvokeCwd = Maybe String
mcwd
, progInvokeInput :: ProgramInvocation -> Maybe IOData
progInvokeInput = Maybe IOData
minputStr
, progInvokeInputEncoding :: ProgramInvocation -> IOEncoding
progInvokeInputEncoding = IOEncoding
encoding
}
IODataMode mode
mode = do
[(String, Maybe String)]
pathOverride <- [(String, Maybe String)] -> [String] -> IO [(String, Maybe String)]
getExtraPathEnv [(String, Maybe String)]
envOverrides [String]
extraPath
Maybe [(String, String)]
menv <- [(String, Maybe String)] -> IO (Maybe [(String, String)])
getEffectiveEnvironment ([(String, Maybe String)]
envOverrides forall a. [a] -> [a] -> [a]
++ [(String, Maybe String)]
pathOverride)
forall mode.
KnownIODataMode mode =>
Verbosity
-> String
-> [String]
-> Maybe String
-> Maybe [(String, String)]
-> Maybe IOData
-> IODataMode mode
-> IO (mode, String, ExitCode)
rawSystemStdInOut Verbosity
verbosity String
path [String]
args Maybe String
mcwd Maybe [(String, String)]
menv Maybe IOData
input IODataMode mode
mode
where
input :: Maybe IOData
input = IOEncoding -> IOData -> IOData
encodeToIOData IOEncoding
encoding forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe IOData
minputStr
getExtraPathEnv :: [(String, Maybe String)] -> [FilePath] -> IO [(String, Maybe String)]
[(String, Maybe String)]
_ [] = forall (m :: * -> *) a. Monad m => a -> m a
return []
getExtraPathEnv [(String, Maybe String)]
env [String]
extras = do
Maybe String
mb_path <- case forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"PATH" [(String, Maybe String)]
env of
Just Maybe String
x -> forall (m :: * -> *) a. Monad m => a -> m a
return Maybe String
x
Maybe (Maybe String)
Nothing -> String -> IO (Maybe String)
lookupEnv String
"PATH"
let extra :: String
extra = forall a. [a] -> [[a]] -> [a]
intercalate [Char
searchPathSeparator] [String]
extras
path' :: String
path' = case Maybe String
mb_path of
Maybe String
Nothing -> String
extra
Just String
path -> String
extra forall a. [a] -> [a] -> [a]
++ Char
searchPathSeparator forall a. a -> [a] -> [a]
: String
path
forall (m :: * -> *) a. Monad m => a -> m a
return [(String
"PATH", forall a. a -> Maybe a
Just String
path')]
getEffectiveEnvironment :: [(String, Maybe String)]
-> IO (Maybe [(String, String)])
getEffectiveEnvironment :: [(String, Maybe String)] -> IO (Maybe [(String, String)])
getEffectiveEnvironment [] = forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
getEffectiveEnvironment [(String, Maybe String)]
overrides =
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Map k a -> [(k, a)]
Map.toList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {t :: * -> *} {k} {a}.
(Foldable t, Ord k) =>
t (k, Maybe a) -> Map k a -> Map k a
apply [(String, Maybe String)]
overrides forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList) IO [(String, String)]
getEnvironment
where
apply :: t (k, Maybe a) -> Map k a -> Map k a
apply t (k, Maybe a)
os Map k a
env = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall {k} {a}. Ord k => (k, Maybe a) -> Map k a -> Map k a
update) Map k a
env t (k, Maybe a)
os
update :: (k, Maybe a) -> Map k a -> Map k a
update (k
var, Maybe a
Nothing) = forall k a. Ord k => k -> Map k a -> Map k a
Map.delete k
var
update (k
var, Just a
val) = forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert k
var a
val
multiStageProgramInvocation
:: ProgramInvocation
-> (ProgramInvocation, ProgramInvocation, ProgramInvocation)
-> [String]
-> [ProgramInvocation]
multiStageProgramInvocation :: ProgramInvocation
-> (ProgramInvocation, ProgramInvocation, ProgramInvocation)
-> [String]
-> [ProgramInvocation]
multiStageProgramInvocation ProgramInvocation
simple (ProgramInvocation
initial, ProgramInvocation
middle, ProgramInvocation
final) [String]
args =
let argSize :: ProgramInvocation -> Int
argSize ProgramInvocation
inv = forall (t :: * -> *) a. Foldable t => t a -> Int
length (ProgramInvocation -> String
progInvokePath ProgramInvocation
inv)
forall a. Num a => a -> a -> a
+ forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Int
s String
a -> forall (t :: * -> *) a. Foldable t => t a -> Int
length String
a forall a. Num a => a -> a -> a
+ Int
1 forall a. Num a => a -> a -> a
+ Int
s) Int
1 (ProgramInvocation -> [String]
progInvokeArgs ProgramInvocation
inv)
fixedArgSize :: Int
fixedArgSize = forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (forall a b. (a -> b) -> [a] -> [b]
map ProgramInvocation -> Int
argSize [ProgramInvocation
simple, ProgramInvocation
initial, ProgramInvocation
middle, ProgramInvocation
final])
chunkSize :: Int
chunkSize = Int
maxCommandLineSize forall a. Num a => a -> a -> a
- Int
fixedArgSize
in case forall a. Int -> [[a]] -> [[[a]]]
splitChunks Int
chunkSize [String]
args of
[] -> [ ProgramInvocation
simple ]
[[String]
c] -> [ ProgramInvocation
simple ProgramInvocation -> [String] -> ProgramInvocation
`appendArgs` [String]
c ]
([String]
c:[String]
c2:[[String]]
cs) | ([[String]]
xs, [String]
x) <- forall a. NonEmpty a -> ([a], a)
unsnocNE ([String]
c2forall a. a -> [a] -> NonEmpty a
:|[[String]]
cs) ->
[ ProgramInvocation
initial ProgramInvocation -> [String] -> ProgramInvocation
`appendArgs` [String]
c ]
forall a. [a] -> [a] -> [a]
++ [ ProgramInvocation
middle ProgramInvocation -> [String] -> ProgramInvocation
`appendArgs` [String]
c'| [String]
c' <- [[String]]
xs ]
forall a. [a] -> [a] -> [a]
++ [ ProgramInvocation
final ProgramInvocation -> [String] -> ProgramInvocation
`appendArgs` [String]
x ]
where
appendArgs :: ProgramInvocation -> [String] -> ProgramInvocation
ProgramInvocation
inv appendArgs :: ProgramInvocation -> [String] -> ProgramInvocation
`appendArgs` [String]
as = ProgramInvocation
inv { progInvokeArgs :: [String]
progInvokeArgs = ProgramInvocation -> [String]
progInvokeArgs ProgramInvocation
inv forall a. [a] -> [a] -> [a]
++ [String]
as }
splitChunks :: Int -> [[a]] -> [[[a]]]
splitChunks :: forall a. Int -> [[a]] -> [[[a]]]
splitChunks Int
len = forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr forall a b. (a -> b) -> a -> b
$ \[[a]]
s ->
if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[a]]
s then forall a. Maybe a
Nothing
else forall a. a -> Maybe a
Just (forall a. Int -> [[a]] -> ([[a]], [[a]])
chunk Int
len [[a]]
s)
chunk :: Int -> [[a]] -> ([[a]], [[a]])
chunk :: forall a. Int -> [[a]] -> ([[a]], [[a]])
chunk Int
len ([a]
s:[[a]]
_) | forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
s forall a. Ord a => a -> a -> Bool
>= Int
len = forall a. HasCallStack => String -> a
error String
toolong
chunk Int
len [[a]]
ss = forall a. [[a]] -> Int -> [[a]] -> ([[a]], [[a]])
chunk' [] Int
len [[a]]
ss
chunk' :: [[a]] -> Int -> [[a]] -> ([[a]], [[a]])
chunk' :: forall a. [[a]] -> Int -> [[a]] -> ([[a]], [[a]])
chunk' [[a]]
acc Int
len ([a]
s:[[a]]
ss)
| Int
len' forall a. Ord a => a -> a -> Bool
< Int
len = forall a. [[a]] -> Int -> [[a]] -> ([[a]], [[a]])
chunk' ([a]
sforall a. a -> [a] -> [a]
:[[a]]
acc) (Int
lenforall a. Num a => a -> a -> a
-Int
len'forall a. Num a => a -> a -> a
-Int
1) [[a]]
ss
where len' :: Int
len' = forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
s
chunk' [[a]]
acc Int
_ [[a]]
ss = (forall a. [a] -> [a]
reverse [[a]]
acc, [[a]]
ss)
toolong :: String
toolong = String
"multiStageProgramInvocation: a single program arg is larger "
forall a. [a] -> [a] -> [a]
++ String
"than the maximum command line length!"
maxCommandLineSize :: Int
maxCommandLineSize :: Int
maxCommandLineSize = Int
30 forall a. Num a => a -> a -> a
* Int
1024