X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Fmain%2FSysTools.lhs;h=adc8e0cd391c5566dcba940e7f9a09c3f1bde9e7;hb=215dad7be238d00c90b3b11b5278ffd4659425d2;hp=33ac91c562383fa80ac06ad81427f2d24d129ae9;hpb=d65574ab3852a0d5b66358f71ae1e34dfcc606c9;p=ghc-hetmet.git diff --git a/ghc/compiler/main/SysTools.lhs b/ghc/compiler/main/SysTools.lhs index 33ac91c..adc8e0c 100644 --- a/ghc/compiler/main/SysTools.lhs +++ b/ghc/compiler/main/SysTools.lhs @@ -17,13 +17,14 @@ module SysTools ( -- Where package.conf is -- Interface to system tools - runUnlit, runCpp, runCc, -- [String] -> IO () - runMangle, runSplit, -- [String] -> IO () - runAs, runLink, -- [String] -> IO () + runUnlit, runCpp, runCc, -- [Option] -> IO () + runMangle, runSplit, -- [Option] -> IO () + runAs, runLink, -- [Option] -> IO () runMkDLL, touch, -- String -> String -> IO () copy, -- String -> String -> String -> IO () + unDosifyPath, -- String -> String -- Temporary-file management setTmpDir, @@ -33,13 +34,14 @@ module SysTools ( -- System interface getProcessID, -- IO Int - system, -- String -> IO Int + system, -- String -> IO ExitCode -- Misc showGhcUsage, -- IO () Shows usage message and exits getSysMan, -- IO String Parallel system only + + Option(..) - runSomething -- ToDo: make private ) where import DriverUtil @@ -54,31 +56,23 @@ import IO import Directory ( doesFileExist, removeFile ) import IOExts ( IORef, readIORef, writeIORef ) import Monad ( when, unless ) -import System ( system, ExitCode(..), exitWith ) +import System ( ExitCode(..), exitWith, getEnv, system ) import CString import Int - -#if __GLASGOW_HASKELL__ < 500 -import Storable -#else -import MarshalArray -#endif - +import Addr + #include "../includes/config.h" -#if !defined(mingw32_TARGET_OS) +#ifndef mingw32_TARGET_OS import qualified Posix #else -import Addr import List ( isPrefixOf ) +import MarshalArray +import SystemExts ( rawSystem ) #endif -import List ( isSuffixOf ) - #include "HsVersions.h" -{-# DEPRECATED runSomething "runSomething should be private to SysTools" #-} - \end{code} @@ -225,6 +219,14 @@ initSysTools minusB_args | am_installed = installed_bin cGHC_MANGLER | otherwise = inplace cGHC_MANGLER_DIR cGHC_MANGLER +#ifndef mingw32_TARGET_OS + -- check whether TMPDIR is set in the environment + ; IO.try (do dir <- getEnv "TMPDIR" -- fails if not set + setTmpDir dir + return () + ) +#endif + -- Check that the package config exists ; config_exists <- doesFileExist pkgconfig_path ; when (not config_exists) $ @@ -245,10 +247,17 @@ initSysTools minusB_args -- pick up whatever happens to be lying around in the path, -- possibly including those from a cygwin install on the target, -- which is exactly what we're trying to avoid. - ; let gcc_path | am_installed = installed_bin ("gcc -B" ++ installed "lib/gcc-lib/" - ++ " -I" ++ installed "include/w32api:" - ++ installed "include/mingw") + ; let gcc_path | am_installed = installed_bin ("gcc -B\"" ++ installed "gcc-lib/\"") | otherwise = cGCC + -- The trailing "/" is absolutely essential; gcc seems + -- to construct file names simply by concatenating to this + -- -B path with no extra slash + -- We use "/" rather than "\\" because otherwise "\\\" is mangled + -- later on; although gcc_path is in NATIVE format, gcc can cope + -- (see comments with declarations of global variables) + -- + -- The quotes round the -B argument are in case TopDir has spaces in it + perl_path | am_installed = installed_bin cGHC_PERL | otherwise = cGHC_PERL @@ -258,8 +267,8 @@ initSysTools minusB_args -- On Win32 we don't want to rely on #!/bin/perl, so we prepend -- a call to Perl to get the invocation of split and mangle - ; let split_path = perl_path ++ " " ++ split_script - mangle_path = perl_path ++ " " ++ mangle_script + ; let split_path = perl_path ++ " \"" ++ split_script ++ "\"" + mangle_path = perl_path ++ " \"" ++ mangle_script ++ "\"" ; let mkdll_path = cMKDLL #else @@ -366,7 +375,7 @@ getTopDir minusbs ; return (am_installed, top_dir) } where - -- get_proto returns a Unix-format path + -- get_proto returns a Unix-format path (relying on getExecDir to do so too) get_proto | not (null minusbs) = return (unDosifyPath (drop 2 (last minusbs))) -- 2 for "-B" | otherwise @@ -374,23 +383,43 @@ getTopDir minusbs ; case maybe_exec_dir of -- (only works on Windows; -- returns Nothing on Unix) Nothing -> throwDyn (InstallationError "missing -B option") - Just dir -> return (remove_suffix (unDosifyPath dir)) + Just dir -> return dir } +\end{code} + + +%************************************************************************ +%* * +\subsection{Command-line options} +n%* * +%************************************************************************ + +When invoking external tools as part of the compilation pipeline, we +pass these a sequence of options on the command-line. Rather than +just using a list of Strings, we use a type that allows us to distinguish +between filepaths and 'other stuff'. [The reason being, of course, that +this type gives us a handle on transforming filenames, and filenames only, +to whatever format they're expected to be on a particular platform.] + + +\begin{code} +data Option + = FileOption String + | Option String + +showOptions :: [Option] -> String +showOptions ls = unwords (map (quote.showOpt) ls) + where + showOpt (FileOption f) = dosifyPath f + showOpt (Option s) = s + +#if defined(mingw32_TARGET_OS) + quote "" = "" + quote s = "\"" ++ s ++ "\"" +#else + quote = id +#endif - -- In an installed tree, the ghc binary lives in $libexecdir, which - -- is normally $libdir/bin. So we strip off a /bin suffix here. - -- In a build tree, the ghc binary lives in $fptools/ghc/compiler, - -- so we strip off the /ghc/compiler suffix here too, leaving a - -- standard TOPDIR. - remove_suffix ghc_bin_dir -- ghc_bin_dir is in standard Unix format - | "/ghc/compiler" `isSuffixOf` ghc_bin_dir = back_two - | "/bin" `isSuffixOf` ghc_bin_dir = back_one - | otherwise = ghc_bin_dir - where - p1 = dropWhile (not . isSlash) (reverse ghc_bin_dir) - p2 = dropWhile (not . isSlash) (tail p1) -- head is '/' - back_two = reverse (tail p2) -- head is '/' - back_one = reverse (tail p1) \end{code} @@ -402,41 +431,41 @@ n%* * \begin{code} -runUnlit :: [String] -> IO () +runUnlit :: [Option] -> IO () runUnlit args = do p <- readIORef v_Pgm_L runSomething "Literate pre-processor" p args -runCpp :: [String] -> IO () +runCpp :: [Option] -> IO () runCpp args = do p <- readIORef v_Pgm_P runSomething "C pre-processor" p args -runCc :: [String] -> IO () +runCc :: [Option] -> IO () runCc args = do p <- readIORef v_Pgm_c runSomething "C Compiler" p args -runMangle :: [String] -> IO () +runMangle :: [Option] -> IO () runMangle args = do p <- readIORef v_Pgm_m runSomething "Mangler" p args -runSplit :: [String] -> IO () +runSplit :: [Option] -> IO () runSplit args = do p <- readIORef v_Pgm_s runSomething "Splitter" p args -runAs :: [String] -> IO () +runAs :: [Option] -> IO () runAs args = do p <- readIORef v_Pgm_a runSomething "Assembler" p args -runLink :: [String] -> IO () +runLink :: [Option] -> IO () runLink args = do p <- readIORef v_Pgm_l runSomething "Linker" p args -runMkDLL :: [String] -> IO () +runMkDLL :: [Option] -> IO () runMkDLL args = do p <- readIORef v_Pgm_MkDLL runSomething "Make DLL" p args touch :: String -> String -> IO () touch purpose arg = do p <- readIORef v_Pgm_T - runSomething purpose p [arg] + runSomething purpose p [FileOption arg] copy :: String -> String -> String -> IO () copy purpose from to = do @@ -556,20 +585,31 @@ setDryRun = writeIORef v_Dry_run True runSomething :: String -- For -v message -> String -- Command name (possibly a full path) -- assumed already dos-ified - -> [String] -- Arguments + -> [Option] -- Arguments -- runSomething will dos-ify them -> IO () runSomething phase_name pgm args = traceCmd phase_name cmd_line $ - do { exit_code <- system cmd_line + do { +#ifndef mingw32_TARGET_OS + exit_code <- system cmd_line +#else + exit_code <- rawSystem cmd_line +#endif ; if exit_code /= ExitSuccess then throwDyn (PhaseFailed phase_name exit_code) else return () } where - cmd_line = unwords (pgm : dosifyPaths args) + 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 traceCmd :: String -> String -> IO () -> IO () -- a) trace the command (at two levels of verbosity) @@ -631,10 +671,10 @@ pgmPath :: String -- Directory string in Unix format #if defined(mingw32_TARGET_OS) --------------------- Windows version ------------------ -unDosifyPath xs = xs - dosifyPaths xs = map dosifyPath xs +unDosifyPath xs = subst '\\' '/' xs + pgmPath dir pgm = dosifyPath dir ++ '\\' : pgm dosifyPath stuff @@ -651,9 +691,10 @@ dosifyPath stuff #else --------------------- Unix version --------------------- -dosifyPaths ps = ps -unDosifyPath xs = subst '\\' '/' xs -pgmPath dir pgm = dir ++ '/' : pgm +dosifyPaths ps = ps +unDosifyPath xs = xs +pgmPath dir pgm = dir ++ '/' : pgm +dosifyPath stuff = stuff -------------------------------------------------------- #endif @@ -688,37 +729,28 @@ slash s1 s2 = s1 ++ ('/' : s2) \begin{code} ----------------------------------------------------------------------------- --- Define myGetProcessId :: IO Int --- getExecDir :: IO (Maybe String) +-- Define getExecDir :: IO (Maybe String) -#ifdef mingw32_TARGET_OS -foreign import "_getpid" getProcessID :: IO Int -- relies on Int == Int32 on Windows - -#if __GLASGOW_HASKELL__ >= 500 -foreign import stdcall "GetCurrentDirectoryA" getCurrentDirectory :: Int32 -> CString -> IO Int32 -foreign import stdcall "GetCurrentDirectoryA" getCurrentDirectoryLen :: Int32 -> Addr -> IO Int32 +#if defined(mingw32_TARGET_OS) getExecDir :: IO (Maybe String) -getExecDir = do len <- getCurrentDirectoryLen 0 nullAddr +getExecDir = do let len = 2048 -- plenty, PATH_MAX is 512 under Win32. buf <- mallocArray (fromIntegral len) - ret <- getCurrentDirectory len buf + ret <- getModuleFileName nullAddr buf len if ret == 0 then return Nothing else do s <- peekCString buf destructArray (fromIntegral len) buf - return (Just s) + return (Just (reverse (drop (length "/bin/ghc.exe") (reverse (unDosifyPath s))))) + + +foreign import stdcall "GetModuleFileNameA" getModuleFileName :: Addr -> CString -> Int32 -> IO Int32 #else -foreign import stdcall "GetCurrentDirectoryA" getCurrentDirectory :: Int32 -> Addr -> IO Int32 -getExecDir :: IO (Maybe String) -getExecDir = do len <- getCurrentDirectory 0 nullAddr - buf <- malloc (fromIntegral len) - ret <- getCurrentDirectory len buf - if ret == 0 then return Nothing - else do s <- unpackCStringIO buf - free buf - return (Just s) +getExecDir :: IO (Maybe String) = do return Nothing #endif + +#ifdef mingw32_TARGET_OS +foreign import "_getpid" getProcessID :: IO Int -- relies on Int == Int32 on Windows #else getProcessID :: IO Int getProcessID = Posix.getProcessID -getExecDir :: IO (Maybe String) = do return Nothing #endif \end{code}