X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Fmain%2FSysTools.lhs;h=e40312cd7e7326d274bdd904b5a4d12deca1b9fa;hp=8bbe22774deaa5d03db4920bac5227d343ebd194;hb=79f275092de54ba5f7e7336c13231ad5198befdf;hpb=6f9127b3a48638a1230935d94046084db567699e diff --git a/compiler/main/SysTools.lhs b/compiler/main/SysTools.lhs index 8bbe227..e40312c 100644 --- a/compiler/main/SysTools.lhs +++ b/compiler/main/SysTools.lhs @@ -21,6 +21,7 @@ module SysTools ( runWindres, runLlvmOpt, runLlvmLlc, + figureLlvmVersion, readElfSection, touch, -- String -> String -> IO () @@ -46,6 +47,7 @@ import ErrUtils import Panic import Util import DynFlags +import StaticFlags import Exception import Data.IORef @@ -158,6 +160,11 @@ initSysTools mbMinusB -- format, '/' separated ; let settingsFile = top_dir "settings" + installed :: FilePath -> FilePath + installed file = top_dir file + installed_mingw_bin file = top_dir ".." "mingw" "bin" file + installed_perl_bin file = top_dir ".." "perl" file + ; settingsStr <- readFile settingsFile ; mySettings <- case maybeReadFuzzy settingsStr of Just s -> @@ -169,11 +176,19 @@ initSysTools mbMinusB return xs Nothing -> pgmError ("No entry for " ++ show key ++ " in " ++ show settingsFile) ; myExtraGccViaCFlags <- getSetting "GCC extra via C opts" - - ; let installed :: FilePath -> FilePath - installed file = top_dir file - installed_mingw_bin file = top_dir ".." "mingw" "bin" file - installed_perl_bin file = top_dir ".." "perl" file + -- On Windows, mingw is distributed with GHC, + -- so we look in TopDir/../mingw/bin + -- It would perhaps be nice to be able to override this + -- with the settings file, but it would be a little fiddly + -- to make that possible, so for now you can't. + ; gcc_prog <- if isWindowsHost then return $ installed_mingw_bin "gcc" + else getSetting "C compiler command" + ; gcc_args_str <- if isWindowsHost then return [] + else getSetting "C compiler flags" + ; let gcc_args = map Option (words gcc_args_str) + ; perl_path <- if isWindowsHost + then return $ installed_perl_bin "perl" + else getSetting "perl command" ; let pkgconfig_path = installed "package.conf.d" ghc_usage_msg_path = installed "ghc-usage.txt" @@ -190,15 +205,7 @@ initSysTools mbMinusB ; tmpdir <- getTemporaryDirectory - -- On Windows, mingw is distributed with GHC, - -- so we look in TopDir/../mingw/bin ; let - gcc_prog - | isWindowsHost = installed_mingw_bin "gcc" - | otherwise = cGCC - perl_path - | isWindowsHost = installed_perl_bin cGHC_PERL - | otherwise = cGHC_PERL -- 'touch' is a GHC util for Windows touch_path | isWindowsHost = installed cGHC_TOUCHY_PGM @@ -221,14 +228,18 @@ initSysTools mbMinusB -- cpp is derived from gcc on all platforms -- HACK, see setPgmP below. We keep 'words' here to remember to fix -- Config.hs one day. - ; let cpp_path = (gcc_prog, - (Option "-E"):(map Option (words cRAWCPP_FLAGS))) + ; let cpp_prog = gcc_prog + cpp_args = Option "-E" + : map Option (words cRAWCPP_FLAGS) + ++ gcc_args -- Other things being equal, as and ld are simply gcc ; let as_prog = gcc_prog + as_args = gcc_args ld_prog = gcc_prog + ld_args = gcc_args - -- figure out llvm location. (TODO: Acutally implement). + -- We just assume on command line ; let lc_prog = "llc" lo_prog = "opt" @@ -241,20 +252,33 @@ initSysTools mbMinusB sExtraGccViaCFlags = words myExtraGccViaCFlags, sSystemPackageConfig = pkgconfig_path, sPgm_L = unlit_path, - sPgm_P = cpp_path, + sPgm_P = (cpp_prog, cpp_args), sPgm_F = "", - sPgm_c = (gcc_prog,[]), + sPgm_c = (gcc_prog, gcc_args), sPgm_s = (split_prog,split_args), - sPgm_a = (as_prog,[]), - sPgm_l = (ld_prog,[]), + sPgm_a = (as_prog, as_args), + sPgm_l = (ld_prog, ld_args), sPgm_dll = (mkdll_prog,mkdll_args), sPgm_T = touch_path, sPgm_sysman = top_dir ++ "/ghc/rts/parallel/SysMan", sPgm_windres = windres_path, sPgm_lo = (lo_prog,[]), - sPgm_lc = (lc_prog,[]) + sPgm_lc = (lc_prog,[]), -- Hans: this isn't right in general, but you can -- elaborate it in the same way as the others + sOpt_L = [], + sOpt_P = (if opt_PIC + then -- this list gets reversed + ["-D__PIC__", "-U __PIC__"] + else []), + sOpt_F = [], + sOpt_c = [], + sOpt_a = [], + sOpt_m = [], + sOpt_l = [], + sOpt_windres = [], + sOpt_lo = [], + sOpt_lc = [] } } \end{code} @@ -393,16 +417,54 @@ runAs dflags args = do mb_env <- getGccEnv args1 runSomethingFiltered dflags id "Assembler" p args1 mb_env +-- | Run the LLVM Optimiser runLlvmOpt :: DynFlags -> [Option] -> IO () runLlvmOpt dflags args = do let (p,args0) = pgm_lo dflags runSomething dflags "LLVM Optimiser" p (args0++args) +-- | Run the LLVM Compiler runLlvmLlc :: DynFlags -> [Option] -> IO () runLlvmLlc dflags args = do let (p,args0) = pgm_lc dflags runSomething dflags "LLVM Compiler" p (args0++args) +-- | Figure out which version of LLVM we are running this session +figureLlvmVersion :: DynFlags -> IO (Maybe Int) +figureLlvmVersion dflags = do + let (pgm,opts) = pgm_lc dflags + args = filter notNull (map showOpt opts) + -- we grab the args even though they should be useless just in + -- case the user is using a customised 'llc' that requires some + -- of the options they've specified. llc doesn't care what other + -- options are specified when '-version' is used. + args' = args ++ ["-version"] + ver <- catchIO (do + (pin, pout, perr, _) <- runInteractiveProcess pgm args' + Nothing Nothing + {- > llc -version + Low Level Virtual Machine (http://llvm.org/): + llvm version 2.8 (Ubuntu 2.8-0Ubuntu1) + ... + -} + hSetBinaryMode pout False + _ <- hGetLine pout + vline <- hGetLine pout + v <- case filter isDigit vline of + [] -> fail "no digits!" + [x] -> fail $ "only 1 digit! (" ++ show x ++ ")" + (x:y:_) -> return ((read [x,y]) :: Int) + hClose pin + hClose pout + hClose perr + return $ Just v + ) + (\err -> do + putMsg dflags $ text $ "Warning: " ++ show err + return Nothing) + return ver + + runLink :: DynFlags -> [Option] -> IO () runLink dflags args = do let (p,args0) = pgm_l dflags @@ -765,20 +827,16 @@ data BuildMessage | EOF traceCmd :: DynFlags -> String -> String -> IO () -> IO () --- a) trace the command (at two levels of verbosity) --- b) don't do it at all if dry-run is set +-- trace the command (at two levels of verbosity) traceCmd dflags phase_name cmd_line action = do { let verb = verbosity dflags ; showPass dflags phase_name ; debugTraceMsg dflags 3 (text cmd_line) ; hFlush stderr - -- Test for -n flag - ; unless (dopt Opt_DryRun dflags) $ do { - -- And run it! ; action `catchIO` 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)) @@ -799,14 +857,15 @@ getBaseDir :: IO (Maybe String) #if defined(mingw32_HOST_OS) -- Assuming we are running ghc, accessed by path $(stuff)/bin/ghc.exe, -- return the path $(stuff)/lib. -getBaseDir = do let len = (2048::Int) -- plenty, PATH_MAX is 512 under Win32. - buf <- mallocArray len - ret <- getModuleFileName nullPtr buf len - if ret == 0 then free buf >> return Nothing - else do s <- peekCString buf - free buf - return (Just (rootDir s)) +getBaseDir = try_size 2048 -- plenty, PATH_MAX is 512 under Win32. where + try_size size = allocaArray (fromIntegral size) $ \buf -> do + ret <- c_GetModuleFileName nullPtr buf size + case ret of + 0 -> return Nothing + _ | ret < size -> fmap (Just . rootDir) $ peekCWString buf + | otherwise -> try_size (size * 2) + rootDir s = case splitFileName $ normalise s of (d, ghc_exe) | lower ghc_exe `elem` ["ghc.exe", @@ -821,8 +880,8 @@ getBaseDir = do let len = (2048::Int) -- plenty, PATH_MAX is 512 under Win32. where fail = panic ("can't decompose ghc.exe path: " ++ show s) lower = map toLower -foreign import stdcall unsafe "GetModuleFileNameA" - getModuleFileName :: Ptr () -> CString -> Int -> IO Int32 +foreign import stdcall unsafe "windows.h GetModuleFileNameW" + c_GetModuleFileName :: Ptr () -> CWString -> Word32 -> IO Word32 #else getBaseDir = return Nothing #endif