+{-# OPTIONS -fno-cse #-}
+-- -fno-cse is needed for GLOBAL_VAR's to behave properly
+
-----------------------------------------------------------------------------
--
-- GHC Driver
import BasicTypes ( SuccessFlag(..) )
import Maybes ( expectJust )
import ParserCoreUtils ( getCoreModuleName )
-import SrcLoc ( unLoc )
-import SrcLoc ( Located(..) )
+import SrcLoc
import FastString
-import Control.Exception as Exception
+import Data.Either
+import Exception
import Data.IORef ( readIORef, writeIORef, IORef )
import GHC.Exts ( Int(..) )
import System.Directory
import System.FilePath
import System.IO
-import SYSTEM_IO_ERROR as IO
+import System.IO.Error as IO
import Control.Monad
import Data.List ( isSuffixOf )
import Data.Maybe
extCoreName = basename ++ ".hcr" }
let hsc_env' = hsc_env { hsc_dflags = dflags' }
- -- -no-recomp should also work with --make
+ -- -fforce-recomp should also work with --make
let force_recomp = dopt Opt_ForceRecomp dflags
source_unchanged = isJust maybe_old_linkable && not force_recomp
object_filename = ml_obj_file location
exe_file = exeFileName dflags
- -- if the modification time on the executable is later than the
- -- modification times on all of the objects, then omit linking
- -- (unless the -no-recomp flag was given).
- e_exe_time <- IO.try $ getModificationTime exe_file
- extra_ld_inputs <- readIORef v_Ld_inputs
- extra_times <- mapM (IO.try . getModificationTime) extra_ld_inputs
- let other_times = map linkableTime linkables
- ++ [ t' | Right t' <- extra_times ]
- linking_needed = case e_exe_time of
- Left _ -> True
- Right t -> any (t <) other_times
+ linking_needed <- linkingNeeded dflags linkables pkg_deps
if not (dopt Opt_ForceRecomp dflags) && not linking_needed
then do debugTraceMsg dflags 2 (text exe_file <+> ptext (sLit "is up to date, linking not required."))
panicBadLink :: GhcLink -> a
panicBadLink other = panic ("link: GHC not built to link this way: " ++
show other)
+
+
+linkingNeeded :: DynFlags -> [Linkable] -> [PackageId] -> IO Bool
+linkingNeeded dflags linkables pkg_deps = do
+ -- if the modification time on the executable is later than the
+ -- modification times on all of the objects and libraries, then omit
+ -- linking (unless the -fforce-recomp flag was given).
+ let exe_file = exeFileName dflags
+ e_exe_time <- IO.try $ getModificationTime exe_file
+ case e_exe_time of
+ Left _ -> return True
+ Right t -> do
+ -- first check object files and extra_ld_inputs
+ extra_ld_inputs <- readIORef v_Ld_inputs
+ e_extra_times <- mapM (IO.try . getModificationTime) extra_ld_inputs
+ let (errs,extra_times) = splitEithers e_extra_times
+ let obj_times = map linkableTime linkables ++ extra_times
+ if not (null errs) || any (t <) obj_times
+ then return True
+ else do
+
+ -- next, check libraries. XXX this only checks Haskell libraries,
+ -- not extra_libraries or -l things from the command line.
+ let pkg_map = pkgIdMap (pkgState dflags)
+ pkg_hslibs = [ (libraryDirs c, lib)
+ | Just c <- map (lookupPackage pkg_map) pkg_deps,
+ lib <- packageHsLibs dflags c ]
+
+ pkg_libfiles <- mapM (uncurry findHSLib) pkg_hslibs
+ if any isNothing pkg_libfiles then return True else do
+ e_lib_times <- mapM (IO.try . getModificationTime)
+ (catMaybes pkg_libfiles)
+ let (lib_errs,lib_times) = splitEithers e_lib_times
+ if not (null lib_errs) || any (t <) lib_times
+ then return True
+ else return False
+
+findHSLib :: [String] -> String -> IO (Maybe FilePath)
+findHSLib dirs lib = do
+ let batch_lib_file = "lib" ++ lib <.> "a"
+ found <- filterM doesFileExist (map (</> batch_lib_file) dirs)
+ case found of
+ [] -> return Nothing
+ (x:_) -> return (Just x)
+
-- -----------------------------------------------------------------------------
-- Compile files in one-shot mode.
compileFile hsc_env stop_phase (src, mb_phase) = do
exists <- doesFileExist src
when (not exists) $
- throwDyn (CmdLineError ("does not exist: " ++ src))
+ ghcError (CmdLineError ("does not exist: " ++ src))
let
dflags = hsc_dflags hsc_env
where
-- Always link in the haskell98 package for static linking. Other
-- packages have to be specified via the -package flag.
- link_pkgs = [haskell98PackageId]
+ link_pkgs
+ | dopt Opt_AutoLinkPackages dflags = [haskell98PackageId]
+ | otherwise = []
-- ---------------------------------------------------------------------------
-- before B in a normal compilation pipeline.
when (not (start_phase `happensBefore` stop_phase)) $
- throwDyn (UsageError
+ ghcError (UsageError
("cannot compile this file to desired target: "
++ input_fn))
-- Cpp phase : (a) gets OPTIONS out of file
-- (b) runs cpp if necessary
-runPhase (Cpp sf) _stop hsc_env basename suff input_fn get_output_fn maybe_loc
+runPhase (Cpp sf) _stop hsc_env _basename _suff input_fn get_output_fn maybe_loc
= do let dflags0 = hsc_dflags hsc_env
src_opts <- getOptionsFromFile dflags0 input_fn
- (dflags, unhandled_flags, warns) <- parseDynamicFlags dflags0 (map unLoc src_opts)
+ (dflags, unhandled_flags, warns) <- parseDynamicFlags dflags0 src_opts
handleFlagWarnings dflags warns
- checkProcessArgsResult unhandled_flags (basename <.> suff)
+ checkProcessArgsResult unhandled_flags
if not (dopt Opt_Cpp dflags) then
-- no need to preprocess CPP, just pass input file along
Nothing -- No "module i of n" progress info
case mbResult of
- Nothing -> throwDyn (PhaseFailed "hsc" (ExitFailure 1))
+ Nothing -> ghcError (PhaseFailed "hsc" (ExitFailure 1))
Just HscNoRecomp
-> do SysTools.touch dflags' "Touching object file" o_file
-- The .o file must have a later modification date
ok <- hscCmmFile hsc_env' input_fn
- when (not ok) $ throwDyn (PhaseFailed "cmm" (ExitFailure 1))
+ when (not ok) $ ghcError (PhaseFailed "cmm" (ExitFailure 1))
return (next_phase, dflags, maybe_loc, output_fn)
let verb = getVerbFlag dflags
- pkg_extra_cc_opts <- getPackageExtraCcOpts dflags pkgs
+ -- cc-options are not passed when compiling .hc files. Our
+ -- hc code doesn't not #include any header files anyway, so these
+ -- options aren't necessary.
+ pkg_extra_cc_opts <-
+ if cc_phase `eqPhase` HCc
+ then return []
+ else getPackageExtraCcOpts dflags pkgs
#ifdef darwin_TARGET_OS
pkg_framework_paths <- getPackageFrameworkPath dflags pkgs
pvm_executable_base = "=" ++ input_fn
pvm_executable = pvm_root ++ "/bin/" ++ pvm_arch ++ "/" ++ pvm_executable_base
-- nuke old binary; maybe use configur'ed names for cp and rm?
- Panic.try (removeFile pvm_executable)
+ tryIO (removeFile pvm_executable)
-- move the newly created binary into PVM land
copy dflags "copying PVM executable" input_fn pvm_executable
-- generate a wrapper script for running a parallel prg under PVM
-- parallel only: move binary to another dir -- HWL
success <- runPhase_MoveBinary dflags output_fn dep_packages
if success then return ()
- else throwDyn (InstallationError ("cannot move binary"))
+ else ghcError (InstallationError ("cannot move binary"))
exeFileName :: DynFlags -> FilePath
let verb = getVerbFlag dflags
let o_file = outputFile dflags
- pkg_lib_paths <- getPackageLibraryPath dflags dep_packages
+ -- We don't want to link our dynamic libs against the RTS package,
+ -- because the RTS lib comes in several flavours and we want to be
+ -- able to pick the flavour when a binary is linked.
+ pkgs <- getPreloadPackagesAnd dflags dep_packages
+ let pkgs_no_rts = filter ((/= rtsPackageId) . packageConfigId) pkgs
+
+ let pkg_lib_paths = collectLibraryPaths pkgs_no_rts
let pkg_lib_path_opts = map ("-L"++) pkg_lib_paths
let lib_paths = libraryPaths dflags
let lib_path_opts = map ("-L"++) lib_paths
- pkg_link_opts <- getPackageLinkOpts dflags dep_packages
+ let pkg_link_opts = collectLinkOpts dflags pkgs_no_rts
-- probably _stub.o files
extra_ld_inputs <- readIORef v_Ld_inputs