module SysTools (
-- Initialisation
initSysTools,
- setPgm, -- String -> IO ()
+
+ setPgmP, -- String -> IO ()
+ setPgmF,
+ setPgmc,
+ setPgmm,
+ setPgms,
+ setPgma,
+ setPgml,
+#ifdef ILX
+ setPgmI,
+ setPgmi,
+#endif
-- Command-line override
setDryRun,
) where
+#include "HsVersions.h"
+
import DriverUtil
import Config
import Outputable
import Panic ( progName, GhcException(..) )
-import Util ( global, dropList )
+import Util ( global, notNull )
import CmdLineOpts ( dynFlag, verbosity )
-import Exception ( throwDyn )
+import EXCEPTION ( throwDyn )
#if __GLASGOW_HASKELL__ > 408
-import qualified Exception ( catch )
+import qualified EXCEPTION as Exception ( catch )
#else
-import Exception ( catchAllIO )
+import EXCEPTION ( catchAllIO )
#endif
-import IO
-import Directory ( doesFileExist, removeFile )
-import IOExts ( IORef, readIORef, writeIORef )
+
+import CString ( CString, peekCString )
+import DATA_IOREF ( IORef, readIORef, writeIORef )
+import DATA_INT
+
import Monad ( when, unless )
import System ( ExitCode(..), exitWith, getEnv, system )
-import CString
-import Int
-import Addr
-
+import IO
+import Directory ( doesFileExist, removeFile )
+
#include "../includes/config.h"
-#ifndef mingw32_TARGET_OS
+-- GHC <= 4.08 didn't have rawSystem, and runs into problems with long command
+-- lines on mingw32, so we disallow it now.
+#if defined(mingw32_HOST_OS) && (__GLASGOW_HASKELL__ <= 408)
+#error GHC <= 4.08 is not supported for bootstrapping GHC on i386-unknown-mingw32
+#endif
+
+#ifndef mingw32_HOST_OS
+#if __GLASGOW_HASKELL__ > 504
+import qualified GHC.Posix
+#else
import qualified Posix
+#endif
#else
import List ( isPrefixOf )
-import MarshalArray
+import Util ( dropList )
+-- import Foreign.Marshal.Array
import Foreign
+-- import CString
#endif
-#if __GLASGOW_HASKELL__ > 408
-# if __GLASGOW_HASKELL__ >= 503
-import GHC.IOBase
-# else
-# endif
-# ifdef mingw32_TARGET_OS
+#ifdef mingw32_HOST_OS
+#if __GLASGOW_HASKELL__ > 504
+import System.Cmd ( rawSystem )
+#else
import SystemExts ( rawSystem )
-# endif
+#endif
#else
import System ( system )
#endif
-
-#include "HsVersions.h"
-
-- Make catch work on older GHCs
#if __GLASGOW_HASKELL__ > 408
myCatch = Exception.catch
| am_installed = installed_bin cGHC_MANGLER_PGM
| otherwise = inplace cGHC_MANGLER_DIR_REL cGHC_MANGLER_PGM
-#ifndef mingw32_TARGET_OS
+#ifndef mingw32_HOST_OS
-- check whether TMPDIR is set in the environment
; IO.try (do dir <- getEnv "TMPDIR" -- fails if not set
setTmpDir dir
throwDyn (InstallationError
("Can't find package.conf as " ++ pkgconfig_path))
-#if defined(mingw32_TARGET_OS)
+#if defined(mingw32_HOST_OS)
-- WINDOWS-SPECIFIC STUFF
-- On Windows, gcc and friends are distributed with GHC,
-- so when "installed" we look in TopDir/bin
; let split_path = perl_path ++ " \"" ++ split_script ++ "\""
mangle_path = perl_path ++ " \"" ++ mangle_script ++ "\""
- ; let mkdll_path = cMKDLL
+ ; let mkdll_path
+ | am_installed = pgmPath (installed "gcc-lib/") cMKDLL ++
+ " --dlltool-name " ++ pgmPath (installed "gcc-lib/") "dlltool" ++
+ " --driver-name " ++ gcc_path
+ | otherwise = cMKDLL
#else
-- UNIX-SPECIFIC STUFF
-- On Unix, the "standard" tools are assumed to be
; return ()
}
-#if defined(mingw32_TARGET_OS)
+#if defined(mingw32_HOST_OS)
foreign import stdcall "GetTempPathA" unsafe getTempPath :: Int -> CString -> IO Int32
#endif
\end{code}
-setPgm is called when a command-line option like
+The various setPgm functions are called when a command-line option
+like
+
-pgmLld
+
is used to override a particular program with a new one
\begin{code}
-setPgm :: String -> IO ()
--- The string is the flag, minus the '-pgm' prefix
--- So the first character says which program to override
-
-setPgm ('P' : pgm) = writeIORef v_Pgm_P pgm
-setPgm ('F' : pgm) = writeIORef v_Pgm_F pgm
-setPgm ('c' : pgm) = writeIORef v_Pgm_c pgm
-setPgm ('m' : pgm) = writeIORef v_Pgm_m pgm
-setPgm ('s' : pgm) = writeIORef v_Pgm_s pgm
-setPgm ('a' : pgm) = writeIORef v_Pgm_a pgm
-setPgm ('l' : pgm) = writeIORef v_Pgm_l pgm
+setPgmP = writeIORef v_Pgm_P
+setPgmF = writeIORef v_Pgm_F
+setPgmc = writeIORef v_Pgm_c
+setPgmm = writeIORef v_Pgm_m
+setPgms = writeIORef v_Pgm_s
+setPgma = writeIORef v_Pgm_a
+setPgml = writeIORef v_Pgm_l
#ifdef ILX
-setPgm ('I' : pgm) = writeIORef v_Pgm_I pgm
-setPgm ('i' : pgm) = writeIORef v_Pgm_i pgm
+setPgmI = writeIORef v_Pgm_I
+setPgmi = writeIORef v_Pgm_i
#endif
-setPgm pgm = unknownFlagErr ("-pgm" ++ pgm)
\end{code}
}
where
-- get_proto returns a Unix-format path (relying on getExecDir to do so too)
- get_proto | not (null minusbs)
+ get_proto | notNull minusbs
= return (unDosifyPath (drop 2 (last minusbs))) -- 2 for "-B"
| otherwise
= do { maybe_exec_dir <- getExecDir -- Get directory of executable
showOpt (FileOption pre f) = pre ++ dosifyPath f
showOpt (Option s) = s
-#if defined(mingw32_TARGET_OS)
- quote "" = ""
- quote s = "\"" ++ s ++ "\""
-#else
- quote = id
-#endif
-
\end{code}
runSomething phase_name pgm args
= traceCmd phase_name cmd_line $
do {
-#ifndef mingw32_TARGET_OS
+#ifndef mingw32_HOST_OS
exit_code <- system cmd_line
#else
exit_code <- rawSystem cmd_line
else return ()
}
where
- cmd_line = pgm ++ ' ':showOptions args -- unwords (pgm : dosifyPaths (map quote args))
-- The pgm is already in native format (appropriate dir separators)
-#if defined(mingw32_TARGET_OS)
- quote "" = ""
- quote s = "\"" ++ s ++ "\""
-#else
- quote = id
-#endif
+ cmd_line = pgm ++ ' ':showOptions args
+ -- unwords (pgm : dosifyPaths (map quote args))
traceCmd :: String -> String -> IO () -> IO ()
-- a) trace the command (at two levels of verbosity)
-#if defined(mingw32_TARGET_OS)
+#if defined(mingw32_HOST_OS)
--------------------- Windows version ------------------
dosifyPaths xs = map dosifyPath xs
-----------------------------------------------------------------------------
-- Define getExecDir :: IO (Maybe String)
-#if defined(mingw32_TARGET_OS)
+#if defined(mingw32_HOST_OS)
getExecDir :: IO (Maybe String)
getExecDir = do let len = (2048::Int) -- plenty, PATH_MAX is 512 under Win32.
buf <- mallocArray len
- ret <- getModuleFileName nullAddr buf len
+ ret <- getModuleFileName nullPtr buf len
if ret == 0 then free buf >> return Nothing
else do s <- peekCString buf
free buf
return (Just (reverse (dropList "/bin/ghc.exe" (reverse (unDosifyPath s)))))
-foreign import stdcall "GetModuleFileNameA" unsafe getModuleFileName :: Addr -> CString -> Int -> IO Int32
+foreign import stdcall "GetModuleFileNameA" unsafe
+ getModuleFileName :: Ptr () -> CString -> Int -> IO Int32
#else
getExecDir :: IO (Maybe String) = do return Nothing
#endif
-#ifdef mingw32_TARGET_OS
+#ifdef mingw32_HOST_OS
foreign import "_getpid" unsafe getProcessID :: IO Int -- relies on Int == Int32 on Windows
+#elif __GLASGOW_HASKELL__ > 504
+getProcessID :: IO Int
+getProcessID = GHC.Posix.c_getpid >>= return . fromIntegral
#else
getProcessID :: IO Int
getProcessID = Posix.getProcessID
#endif
-#if defined(mingw32_TARGET_OS) && (__GLASGOW_HASKELL__ <= 408)
-rawSystem :: String -> IO ExitCode
-rawSystem cmd = system cmd
- -- mingw only: if you try to build a stage2 compiler with a stage1
- -- that has been bootstrapped with 4.08 (or earlier), this will run
- -- into problems with limits on command-line lengths with the std.
- -- Win32 command interpreters. So don't this - use 5.00 or later
- -- to compile up the GHC sources.
+quote :: String -> String
+#if defined(mingw32_HOST_OS)
+quote "" = ""
+quote s = "\"" ++ s ++ "\""
+#else
+quote s = s
#endif
-
\end{code}