Get building GHC itself with Cabal more-or-less working
[ghc-hetmet.git] / compiler / main / SysTools.lhs
index 91c0e7f..9d53b81 100644 (file)
@@ -7,12 +7,8 @@
 -----------------------------------------------------------------------------
 
 \begin{code}
-{-# OPTIONS -w #-}
--- The above warning supression flag is a temporary kludge.
--- While working on this module you are encouraged to remove it and fix
--- any warnings in the module. See
---     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
--- for details
+{-# OPTIONS -fno-cse #-}
+-- -fno-cse is needed for GLOBAL_VAR's to behave properly
 
 module SysTools (
         -- Initialisation
@@ -59,7 +55,7 @@ import System.Exit
 import System.Environment
 import System.FilePath
 import System.IO
-import SYSTEM_IO_ERROR as IO
+import System.IO.Error as IO
 import System.Directory
 import Data.Char
 import Data.Maybe
@@ -73,7 +69,7 @@ import CString          ( CString, peekCString )
 #endif
 
 import System.Process   ( runInteractiveProcess, getProcessExitCode )
-import Control.Concurrent( forkIO, newChan, readChan, writeChan )
+import Control.Concurrent
 import FastString
 import SrcLoc           ( SrcLoc, mkSrcLoc, noSrcSpan, mkSrcSpan )
 \end{code}
@@ -156,7 +152,7 @@ initSysTools :: Maybe String    -- Maybe TopDir path (without the '-B' prefix)
                                 --      (c) the GHC usage message
 
 
-initSysTools mbMinusB dflags
+initSysTools mbMinusB dflags0
   = do  { (am_installed, top_dir) <- findTopDir mbMinusB
                 -- top_dir
                 --      for "installed" this is the root of GHC's support files
@@ -165,9 +161,14 @@ initSysTools mbMinusB dflags
                 -- format, '/' separated
 
         ; let installed, installed_bin :: FilePath -> FilePath
-              installed_bin pgm   =  top_dir </> pgm
-              installed     file  =  top_dir </> file
-              inplace dir   pgm   =  top_dir </> dir </> pgm
+              installed_bin pgm  = top_dir </> pgm
+              installed     file = top_dir </> file
+              inplace dir   pgm  = let real_top_dir = foldr (</>) ""
+                                                    $ reverse
+                                                    $ drop 4
+                                                    $ reverse
+                                                    $ splitDirectories top_dir
+                                   in real_top_dir </> dir </> pgm
 
         ; let pkgconfig_path
                 | am_installed = installed "package.conf"
@@ -200,8 +201,6 @@ initSysTools mbMinusB dflags
                 | am_installed = installed_bin "bin/windres"
                 | otherwise    = "windres"
 
-        ; let dflags0 = defaultDynFlags
-
         ; tmpdir <- getTemporaryDirectory
         ; let dflags1 = setTmpDir tmpdir dflags0
 
@@ -211,45 +210,57 @@ initSysTools mbMinusB dflags
              throwDyn (InstallationError
                          ("Can't find package.conf as " ++ pkgconfig_path))
 
-#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
-        -- When "in-place" we look wherever the build-time configure
-        --      script found them
-        -- When "install" we tell gcc where its specs file + exes are (-B)
-        --      and also some places to pick up include files.  We need
-        --      to be careful to put all necessary exes in the -B place
-        --      (as, ld, cc1, etc) since if they don't get found there, gcc
-        --      then tries to run unadorned "as", "ld", etc, and will
-        --      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_b_arg = Option ("-B" ++ installed "gcc-lib/")
+        -- When "in-place", or when not on Windows, we look wherever
+        --      the build-time configure script found them
+        ; let
+              -- 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_args are in NATIVE format,
+              -- gcc can cope
+              --      (see comments with declarations of global variables)
+              gcc_b_arg = Option ("-B" ++ installed "gcc-lib/")
               (gcc_prog,gcc_args)
-                | am_installed = (installed_bin "gcc", [gcc_b_arg])
-                | 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_args are in NATIVE format,
-                -- gcc can cope
-                --      (see comments with declarations of global variables)
-
-              perl_path | am_installed = installed_bin cGHC_PERL
-                        | otherwise    = cGHC_PERL
-
-        -- 'touch' is a GHC util for Windows, and similarly unlit, mangle
-        ; let touch_path  | am_installed = installed_bin cGHC_TOUCHY_PGM
-                          | otherwise    = inplace cGHC_TOUCHY_DIR_REL cGHC_TOUCHY_PGM
-
-        -- 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_prog,  split_args)  = (perl_path, [Option split_script])
-              (mangle_prog, mangle_args) = (perl_path, [Option mangle_script])
-
-        ; let (mkdll_prog, mkdll_args)
+                | isWindowsHost && am_installed
+                    -- We tell gcc where its specs file + exes are (-B)
+                    -- and also some places to pick up include files.  We need
+                    -- to be careful to put all necessary exes in the -B place
+                    -- (as, ld, cc1, etc) since if they don't get found there,
+                    -- gcc then tries to run unadorned "as", "ld", etc, and
+                    -- will 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.
+                    = (installed_bin "gcc", [gcc_b_arg])
+                | otherwise = (cGCC, [])
+              perl_path
+                | isWindowsHost && am_installed = installed_bin cGHC_PERL
+                | otherwise = cGHC_PERL
+              -- 'touch' is a GHC util for Windows
+              touch_path
+                | isWindowsHost
+                    = if am_installed
+                      then installed_bin cGHC_TOUCHY_PGM
+                      else inplace cGHC_TOUCHY_DIR_REL cGHC_TOUCHY_PGM
+                | otherwise = "touch"
+              -- 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.
+              -- On Unix, scripts are invoked using the '#!' method.  Binary
+              -- installations of GHC on Unix place the correct line on the
+              -- front of the script at installation time, so we don't want
+              -- to wire-in our knowledge of $(PERL) on the host system here.
+              (split_prog,  split_args)
+                | isWindowsHost = (perl_path,    [Option split_script])
+                | otherwise     = (split_script, [])
+              (mangle_prog, mangle_args)
+                | isWindowsHost = (perl_path,   [Option mangle_script])
+                | otherwise     = (mangle_script, [])
+              (mkdll_prog, mkdll_args)
+                | not isWindowsHost
+                    = panic "Can't build DLLs on a non-Win32 system"
                 | am_installed =
                     (installed "gcc-lib/" </> cMKDLL,
                      [ Option "--dlltool-name",
@@ -257,24 +268,6 @@ initSysTools mbMinusB dflags
                        Option "--driver-name",
                        Option gcc_prog, gcc_b_arg ])
                 | otherwise    = (cMKDLL, [])
-#else
-        --              UNIX-SPECIFIC STUFF
-        -- On Unix, the "standard" tools are assumed to be
-        -- in the same place whether we are running "in-place" or "installed"
-        -- That place is wherever the build-time configure script found them.
-        ; let   gcc_prog   = cGCC
-                gcc_args   = []
-                touch_path = "touch"
-                mkdll_prog = panic "Can't build DLLs on a non-Win32 system"
-                mkdll_args = []
-
-        -- On Unix, scripts are invoked using the '#!' method.  Binary
-        -- installations of GHC on Unix place the correct line on the front
-        -- of the script at installation time, so we don't want to wire-in
-        -- our knowledge of $(PERL) on the host system here.
-        ; let (split_prog,  split_args)  = (split_script,  [])
-              (mangle_prog, mangle_args) = (mangle_script, [])
-#endif
 
         -- cpp is derived from gcc on all platforms
         -- HACK, see setPgmP below. We keep 'words' here to remember to fix
@@ -282,10 +275,6 @@ initSysTools mbMinusB dflags
         ; let cpp_path  = (gcc_prog, gcc_args ++
                            (Option "-E"):(map Option (words cRAWCPP_FLAGS)))
 
-        -- For all systems, copy and remove are provided by the host
-        -- system; architecture-specific stuff is done when building Config.hs
-        ; let   cp_path = cGHC_CP
-
         -- Other things being equal, as and ld are simply gcc
         ; let   (as_prog,as_args)  = (gcc_prog,gcc_args)
                 (ld_prog,ld_args)  = (gcc_prog,gcc_args)
@@ -447,9 +436,6 @@ xs `isContainedIn` ys = any (xs `isPrefixOf`) (tails ys)
 -- binaries (see bug #1110).
 getGccEnv :: [Option] -> IO (Maybe [(String,String)])
 getGccEnv opts =
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 603
-  return Nothing
-#else
   if null b_dirs
      then return Nothing
      else do env <- getEnvironment
@@ -463,7 +449,6 @@ getGccEnv opts =
   mangle_path (path,paths) | map toUpper path == "PATH"
         = (path, '\"' : head b_dirs ++ "\";" ++ paths)
   mangle_path other = other
-#endif
 
 runMangle :: DynFlags -> [Option] -> IO ()
 runMangle dflags args = do
@@ -700,11 +685,6 @@ runSomethingFiltered dflags filter_fn phase_name pgm args mb_env = do
                 -- to test for this in general.)
               (\ err ->
                 if IO.isDoesNotExistError err
-#if defined(mingw32_HOST_OS) && __GLASGOW_HASKELL__ < 604
-                -- the 'compat' version of rawSystem under mingw32 always
-                -- maps 'errno' to EINVAL to failure.
-                   || case (ioeGetErrorType err ) of { InvalidArgument{} -> True ; _ -> False}
-#endif
                  then return (ExitFailure 1, True)
                  else IO.ioError err)
   case (doesn'tExist, exit_code) of
@@ -712,12 +692,9 @@ runSomethingFiltered dflags filter_fn phase_name pgm args mb_env = do
      (_, ExitSuccess) -> return ()
      _                -> throwDyn (PhaseFailed phase_name exit_code)
 
-
-
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 603
-builderMainLoop dflags filter_fn pgm real_args mb_env = do
-  rawSystem pgm real_args
-#else
+builderMainLoop :: DynFlags -> (String -> String) -> FilePath
+                -> [String] -> Maybe [(String, String)]
+                -> IO ExitCode
 builderMainLoop dflags filter_fn pgm real_args mb_env = do
   chan <- newChan
   (hStdIn, hStdOut, hStdErr, hProcess) <- runInteractiveProcess pgm real_args Nothing mb_env
@@ -742,7 +719,7 @@ builderMainLoop dflags filter_fn pgm real_args mb_env = do
     -- for all of these to happen (status==3).
     -- ToDo: we should really have a contingency plan in case any of
     -- the threads dies, such as a timeout.
-    loop chan hProcess 0 0 exitcode = return exitcode
+    loop _    _        0 0 exitcode = return exitcode
     loop chan hProcess t p exitcode = do
       mb_code <- if p > 0
                    then getProcessExitCode hProcess
@@ -763,6 +740,7 @@ builderMainLoop dflags filter_fn pgm real_args mb_env = do
                   loop chan hProcess (t-1) p exitcode
           | otherwise -> loop chan hProcess t p exitcode
 
+readerProc :: Chan BuildMessage -> Handle -> (String -> String) -> IO ()
 readerProc chan hdl filter_fn =
     (do str <- hGetContents hdl
         loop (linesPlatform (filter_fn str)) Nothing)
@@ -784,6 +762,7 @@ readerProc chan hdl filter_fn =
                         checkError l ls
                   Nothing -> do
                         checkError l ls
+                  _ -> panic "readerProc/loop"
 
         checkError l ls
            = case parseError l of
@@ -826,8 +805,8 @@ data BuildMessage
   = BuildMsg   !SDoc
   | BuildError !SrcLoc !SDoc
   | EOF
-#endif
 
+showOpt :: Option -> String
 showOpt (FileOption pre f) = pre ++ f
 showOpt (Option s)  = s
 
@@ -847,9 +826,9 @@ traceCmd dflags phase_name cmd_line action
         ; action `IO.catch` handle_exn verb
         }}
   where
-    handle_exn verb exn = do { debugTraceMsg dflags 2 (char '\n')
-                             ; debugTraceMsg dflags 2 (ptext (sLit "Failed:") <+> text cmd_line <+> text (show exn))
-                             ; throwDyn (PhaseFailed phase_name (ExitFailure 1)) }
+    handle_exn _verb exn = do { debugTraceMsg dflags 2 (char '\n')
+                              ; debugTraceMsg dflags 2 (ptext (sLit "Failed:") <+> text cmd_line <+> text (show exn))
+                              ; throwDyn (PhaseFailed phase_name (ExitFailure 1)) }
 \end{code}
 
 %************************************************************************