[project @ 2003-06-23 10:35:15 by simonpj]
[ghc-hetmet.git] / ghc / compiler / main / DriverState.hs
index 1b4a06b..93ac6b7 100644 (file)
@@ -1,5 +1,5 @@
 -----------------------------------------------------------------------------
--- $Id: DriverState.hs,v 1.80 2002/06/12 22:04:26 wolfgang Exp $
+-- $Id: DriverState.hs,v 1.92 2003/06/23 10:35:17 simonpj Exp $
 --
 -- Settings for the driver
 --
@@ -12,23 +12,25 @@ module DriverState where
 #include "../includes/config.h"
 #include "HsVersions.h"
 
-import SysTools                ( getTopDir )
 import ParsePkgConf    ( loadPackageConfig )
-import Packages                ( PackageConfig(..), mungePackagePaths )
+import SysTools                ( getTopDir )
+import Packages
 import CmdLineOpts
 import DriverPhases
 import DriverUtil
+import UniqFM          ( eltsUFM )
 import Util
 import Config
-import Exception
-import IOExts
 import Panic
 
+import DATA_IOREF      ( IORef, readIORef, writeIORef )
+import EXCEPTION
+
 import List
 import Char  
 import Monad
-import Maybe     ( fromJust, isJust )
-import Directory ( doesDirectoryExist )
+import Maybe           ( fromJust, isJust )
+import Directory       ( doesDirectoryExist )
 
 -----------------------------------------------------------------------------
 -- non-configured things
@@ -91,7 +93,10 @@ GLOBAL_VAR(v_Keep_ilx_files,         False,          Bool)
 -- Misc
 GLOBAL_VAR(v_Scale_sizes_by,           1.0,            Double)
 GLOBAL_VAR(v_Static,                   True,           Bool)
+GLOBAL_VAR(v_NoLink,                   False,          Bool)
 GLOBAL_VAR(v_NoHsMain,                         False,          Bool)
+GLOBAL_VAR(v_MainModIs,                        Nothing,        Maybe String)
+GLOBAL_VAR(v_MainFunIs,                        Nothing,        Maybe String)
 GLOBAL_VAR(v_Recomp,                   True,           Bool)
 GLOBAL_VAR(v_Collect_ghc_timing,       False,          Bool)
 GLOBAL_VAR(v_Do_asm_mangling,          True,           Bool)
@@ -156,7 +161,7 @@ verifyOutputFiles = do
                              show dir ++ " does not exist (used with " ++ 
                             show flg ++ " option.)"))
 
-GLOBAL_VAR(v_Object_suf,  Nothing, Maybe String)
+GLOBAL_VAR(v_Object_suf,  phaseInputExt Ln, String)
 GLOBAL_VAR(v_HC_suf,     Nothing, Maybe String)
 GLOBAL_VAR(v_Hi_dir,      Nothing, Maybe String)
 GLOBAL_VAR(v_Hi_suf,      "hi",           String)
@@ -168,14 +173,12 @@ odir_ify f = do
   odir_opt <- readIORef v_Output_dir
   case odir_opt of
        Nothing -> return f
-       Just d  -> return (newdir d f)
+       Just d  -> return (replaceFilenameDirectory f d)
 
 osuf_ify :: String -> IO String
 osuf_ify f = do
-  osuf_opt <- readIORef v_Object_suf
-  case osuf_opt of
-       Nothing -> return f
-       Just s  -> return (newsuf s f)
+  osuf <- readIORef v_Object_suf
+  return (replaceFilenameSuffix f osuf)
 
 -----------------------------------------------------------------------------
 -- Compiler optimisation options
@@ -190,7 +193,6 @@ setOptLevel n = do
 GLOBAL_VAR(v_minus_o2_for_C,            False, Bool)
 GLOBAL_VAR(v_MaxSimplifierIterations,   4,     Int)
 GLOBAL_VAR(v_StgStats,                  False, Bool)
-GLOBAL_VAR(v_UsageSPInf,               False, Bool)  -- Off by default
 GLOBAL_VAR(v_Strictness,               True,  Bool)
 GLOBAL_VAR(v_CSE,                      True,  Bool)
 GLOBAL_VAR(v_RuleCheck,                Nothing,  Maybe String)
@@ -229,7 +231,6 @@ buildCoreToDo :: IO [CoreToDo]
 buildCoreToDo = do
    opt_level  <- readIORef v_OptLevel
    max_iter   <- readIORef v_MaxSimplifierIterations
-   usageSP    <- readIORef v_UsageSPInf
    strictness <- readIORef v_Strictness
    cse        <- readIORef v_CSE
    rule_check <- readIORef v_RuleCheck
@@ -277,10 +278,6 @@ buildCoreToDo = do
        ],
        case rule_check of { Just pat -> CoreDoRuleCheck 2 pat; Nothing -> CoreDoNothing },
 
-       -- infer usage information here in case we need it later.
-        -- (add more of these where you need them --KSW 1999-04)
-        if usageSP then CoreDoUSPInf else CoreDoNothing,
-
        CoreDoSimplify (SimplPhase 1) [
                -- Need inline-phase2 here so that build/augment get 
                -- inlined.  I found that spectral/hartel/genfft lost some useful
@@ -377,8 +374,6 @@ GLOBAL_VAR(v_Import_paths,  ["."], [String])
 GLOBAL_VAR(v_Include_paths, ["."], [String])
 GLOBAL_VAR(v_Library_paths, [],         [String])
 
-GLOBAL_VAR(v_Cmdline_libraries,   [], [String])
-
 #ifdef darwin_TARGET_OS
 GLOBAL_VAR(v_Framework_paths, [], [String])
 GLOBAL_VAR(v_Cmdline_frameworks, [], [String])
@@ -450,69 +445,117 @@ addToDirList ref path
     splitUp xs = return (split split_marker xs)
 #endif
 
-GLOBAL_VAR(v_HCHeader, "", String)
-
------------------------------------------------------------------------------
--- Packages
-
--- package list is maintained in dependency order
-GLOBAL_VAR(v_Packages, ("haskell98":"base":"rts":[]), [String])
+-- ----------------------------------------------------------------------------
+-- Loading the package config file
 
 readPackageConf :: String -> IO ()
 readPackageConf conf_file = do
-  proto_pkg_details <- loadPackageConfig conf_file
-  top_dir <- getTopDir
-  let pkg_details    = mungePackagePaths top_dir proto_pkg_details
-  old_pkg_details <- readIORef v_Package_details
+  proto_pkg_configs <- loadPackageConfig conf_file
+  top_dir          <- getTopDir
+  let pkg_configs = mungePackagePaths top_dir proto_pkg_configs
+  extendPackageConfigMap pkg_configs
+
+mungePackagePaths :: String -> [PackageConfig] -> [PackageConfig]
+-- Replace the string "$libdir" at the beginning of a path
+-- with the current libdir (obtained from the -B option).
+mungePackagePaths top_dir ps = map munge_pkg ps
+ where 
+  munge_pkg p = p{ import_dirs  = munge_paths (import_dirs p),
+                  include_dirs = munge_paths (include_dirs p),
+                  library_dirs = munge_paths (library_dirs p),
+                  framework_dirs = munge_paths (framework_dirs p) }
 
-  let -- new package override old ones
-      new_pkg_names = map name pkg_details
-      filtered_old_pkg_details = 
-        filter (\p -> name p `notElem` new_pkg_names) old_pkg_details
+  munge_paths = map munge_path
 
-  writeIORef v_Package_details (pkg_details ++ filtered_old_pkg_details)
+  munge_path p 
+         | Just p' <- my_prefix_match "$libdir" p = top_dir ++ p'
+         | otherwise                              = p
 
+
+-- -----------------------------------------------------------------------------
+-- The list of packages requested on the command line
+
+-- The package list reflects what packages were given as command-line options,
+-- plus their dependent packages.  It is maintained in dependency order;
+-- earlier packages may depend on later ones, but not vice versa
+GLOBAL_VAR(v_ExplicitPackages, initPackageList, [PackageName])
+
+initPackageList = [basePackage, rtsPackage]
+       -- basePackage is part of this list entirely because of 
+       -- wired-in names in GHCi.  See the notes on wired-in names in
+       -- Linker.linkExpr.  By putting the base backage in initPackageList
+       -- we make sure that it'll always by linked.
+
+
+-- add a package requested from the command-line
 addPackage :: String -> IO ()
-addPackage package
-  = do pkg_details <- readIORef v_Package_details
-       case lookupPkg package pkg_details of
-         Nothing -> throwDyn (CmdLineError ("unknown package name: " ++ package))
-         Just details -> do
-           ps <- readIORef v_Packages
-           unless (package `elem` ps) $ do
-               mapM_ addPackage (package_deps details)
-               ps <- readIORef v_Packages
-               writeIORef v_Packages (package:ps)
-
-getPackageImportPath   :: IO [String]
+addPackage package = do
+  pkg_details <- getPackageConfigMap
+  ps  <- readIORef v_ExplicitPackages
+  ps' <- add_package pkg_details ps (mkPackageName package)
+               -- Throws an exception if it fails
+  writeIORef v_ExplicitPackages ps'
+
+-- internal helper
+add_package :: PackageConfigMap -> [PackageName]
+           -> PackageName -> IO [PackageName]
+add_package pkg_details ps p   
+  | p `elem` ps        -- Check if we've already added this package
+  = return ps
+  | Just details <- lookupPkg pkg_details p
+  -- Add the package's dependents also
+  = do ps' <- foldM (add_package pkg_details) ps (packageDependents details)
+       return (p : ps')
+  | otherwise
+  = throwDyn (CmdLineError ("unknown package name: " ++ packageNameString p))
+
+
+-- -----------------------------------------------------------------------------
+-- Extracting information from the packages in scope
+
+-- Many of these functions take a list of packages: in those cases,
+-- the list is expected to contain the "dependent packages",
+-- i.e. those packages that were found to be depended on by the
+-- current module/program.  These can be auto or non-auto packages, it
+-- doesn't really matter.  The list is always combined with the list
+-- of explicit (command-line) packages to determine which packages to
+-- use.
+
+getPackageImportPath :: IO [String]
 getPackageImportPath = do
-  ps <- getPackageInfo
+  ps <- getExplicitAndAutoPackageConfigs
+                 -- import dirs are always derived from the 'auto' 
+                 -- packages as well as the explicit ones
   return (nub (filter notNull (concatMap import_dirs ps)))
 
-getPackageIncludePath   :: IO [String]
-getPackageIncludePath = do
-  ps <- getPackageInfo
+getPackageIncludePath :: [PackageName] -> IO [String]
+getPackageIncludePath pkgs = do
+  ps <- getExplicitPackagesAnd pkgs
   return (nub (filter notNull (concatMap include_dirs ps)))
 
        -- includes are in reverse dependency order (i.e. rts first)
-getPackageCIncludes   :: IO [String]
-getPackageCIncludes = do
-  ps <- getPackageInfo
-  return (reverse (nub (filter notNull (concatMap c_includes ps))))
-
-getPackageLibraryPath  :: IO [String]
-getPackageLibraryPath = do
-  ps <- getPackageInfo
+getPackageCIncludes :: [PackageConfig] -> IO [String]
+getPackageCIncludes pkg_configs = do
+  return (reverse (nub (filter notNull (concatMap c_includes pkg_configs))))
+
+getPackageLibraryPath :: [PackageName] -> IO [String]
+getPackageLibraryPath pkgs = do 
+  ps <- getExplicitPackagesAnd pkgs
   return (nub (filter notNull (concatMap library_dirs ps)))
 
-getPackageLibraries    :: IO [String]
-getPackageLibraries = do
-  ps <- getPackageInfo
+getPackageLinkOpts :: [PackageName] -> IO [String]
+getPackageLinkOpts pkgs = do
+  ps <- getExplicitPackagesAnd pkgs
   tag <- readIORef v_Build_tag
-  let suffix = if null tag then "" else '_':tag
-  return (concat (
-       map (\p -> map (++suffix) (hACK (hs_libraries p)) ++ extra_libraries p) ps
-     ))
+  static <- readIORef v_Static
+  let 
+       imp        = if static then "" else "_imp"
+       suffix     = if null tag then "" else '_':tag
+       libs p     = map (++suffix) (hACK (hs_libraries p)) ++ extra_libraries p
+       imp_libs p = map (++imp) (libs p)
+       all_opts p = map ("-l" ++) (imp_libs p) ++ extra_ld_opts p
+
+  return (concat (map all_opts ps))
   where
      -- This is a totally horrible (temporary) hack, for Win32.  Problem is
      -- that package.conf for Win32 says that the main prelude lib is 
@@ -546,48 +589,42 @@ getPackageLibraries = do
 
 getPackageExtraGhcOpts :: IO [String]
 getPackageExtraGhcOpts = do
-  ps <- getPackageInfo
+  ps <- getExplicitAndAutoPackageConfigs
   return (concatMap extra_ghc_opts ps)
 
-getPackageExtraCcOpts  :: IO [String]
-getPackageExtraCcOpts = do
-  ps <- getPackageInfo
+getPackageExtraCcOpts :: [PackageName] -> IO [String]
+getPackageExtraCcOpts pkgs = do
+  ps <- getExplicitPackagesAnd pkgs
   return (concatMap extra_cc_opts ps)
 
-getPackageExtraLdOpts  :: IO [String]
-getPackageExtraLdOpts = do
-  ps <- getPackageInfo
-  return (concatMap extra_ld_opts ps)
-
 #ifdef darwin_TARGET_OS
-getPackageFrameworkPath  :: IO [String]
-getPackageFrameworkPath = do
-  ps <- getPackageInfo
+getPackageFrameworkPath  :: [PackageName] -> IO [String]
+getPackageFrameworkPath pkgs = do
+  ps <- getExplicitPackagesAnd pkgs
   return (nub (filter notNull (concatMap framework_dirs ps)))
 
-getPackageFrameworks  :: IO [String]
-getPackageFrameworks = do
-  ps <- getPackageInfo
+getPackageFrameworks  :: [PackageName] -> IO [String]
+getPackageFrameworks pkgs = do
+  ps <- getExplicitPackagesAnd pkgs
   return (concatMap extra_frameworks ps)
 #endif
 
-getPackageInfo :: IO [PackageConfig]
-getPackageInfo = do
-  ps <- readIORef v_Packages
-  getPackageDetails ps
-
-getPackageDetails :: [String] -> IO [PackageConfig]
-getPackageDetails ps = do
-  pkg_details <- readIORef v_Package_details
-  return [ pkg | p <- ps, Just pkg <- [ lookupPkg p pkg_details ] ]
-
-GLOBAL_VAR(v_Package_details, [], [PackageConfig])
-
-lookupPkg :: String -> [PackageConfig] -> Maybe PackageConfig
-lookupPkg nm ps
-   = case [p | p <- ps, name p == nm] of
-        []    -> Nothing
-        (p:_) -> Just p
+-- -----------------------------------------------------------------------------
+-- Package Utils
+
+getExplicitPackagesAnd :: [PackageName] -> IO [PackageConfig]
+getExplicitPackagesAnd pkg_names = do
+  pkg_map <- getPackageConfigMap
+  expl <- readIORef v_ExplicitPackages
+  all_pkgs <- foldM (add_package pkg_map) expl pkg_names
+  getPackageDetails all_pkgs
+
+-- return all packages, including both the auto packages and the explicit ones
+getExplicitAndAutoPackageConfigs :: IO [PackageConfig]
+getExplicitAndAutoPackageConfigs = do
+  pkg_map <- getPackageConfigMap
+  let auto_packages = [ mkPackageName (name p) | p <- eltsUFM pkg_map, auto p ]
+  getExplicitPackagesAnd auto_packages
 
 -----------------------------------------------------------------------------
 -- Ways