2 % (c) The University of Glasgow, 2000
4 \section[Finder]{Module Finder}
8 initFinder, -- :: [PackageConfig] -> IO (),
9 flushFinderCache, -- :: IO ()
11 findModule, -- :: ModuleName -> IO (Maybe (Module, ModLocation))
12 findPackageModule, -- :: ModuleName -> IO (Maybe (Module, ModLocation))
14 mkHomeModLocation, -- :: ModuleName -> String -> FilePath
17 findLinkable, -- :: ModuleName -> ModLocation -> IO (Maybe Linkable)
19 hiBootExt, -- :: String
20 hiBootVerExt, -- :: String
24 #include "HsVersions.h"
27 import UniqFM ( filterUFM )
28 import Packages ( PackageConfig(..) )
29 import HscTypes ( Linkable(..), Unlinked(..) )
31 import DriverUtil ( split_longest_prefix, splitFilename3 )
36 import DATA_IOREF ( IORef, writeIORef, readIORef )
43 -- -----------------------------------------------------------------------------
46 -- The Finder provides a thin filesystem abstraction to the rest of the
47 -- compiler. For a given module, it knows (a) whether the module lives
48 -- in the home package or in another package, so it can make a Module
49 -- from a ModuleName, and (b) where the source, interface, and object
50 -- files for a module live.
52 -- It does *not* know which particular package a module lives in, because
53 -- that information is only contained in the interface file.
55 initFinder :: [PackageConfig] -> IO ()
56 initFinder pkgs = return ()
58 -- -----------------------------------------------------------------------------
61 GLOBAL_VAR(finder_cache, emptyModuleEnv, ModuleEnv (Module,ModLocation))
63 -- remove all the home modules from the cache; package modules are
64 -- assumed to not move around during a session.
65 flushFinderCache :: IO ()
67 fm <- readIORef finder_cache
68 writeIORef finder_cache (filterUFM (not . isHomeModule . fst) fm)
70 addToFinderCache :: ModuleName -> (Module,ModLocation) -> IO ()
71 addToFinderCache mod_name stuff = do
72 fm <- readIORef finder_cache
73 writeIORef finder_cache (extendModuleEnvByName fm mod_name stuff)
75 lookupFinderCache :: ModuleName -> IO (Maybe (Module,ModLocation))
76 lookupFinderCache mod_name = do
77 fm <- readIORef finder_cache
78 return $! lookupModuleEnvByName fm mod_name
80 -- -----------------------------------------------------------------------------
83 -- This is the main interface to the finder, which maps ModuleNames to
84 -- Modules and ModLocations.
86 -- The Module contains one crucial bit of information about a module:
87 -- whether it lives in the current ("home") package or not (see Module
90 -- The ModLocation contains the names of all the files associated with
91 -- that module: its source file, .hi file, object file, etc.
93 findModule :: ModuleName -> IO (Maybe (Module, ModLocation))
95 r <- lookupFinderCache name
97 Just result -> return (Just result)
99 j <- maybeHomeModule name
101 Just home_module -> return (Just home_module)
102 Nothing -> findPackageMod name
104 findPackageModule :: ModuleName -> IO (Maybe (Module, ModLocation))
105 findPackageModule name = do
106 r <- lookupFinderCache name
108 Just result -> return (Just result)
109 Nothing -> findPackageMod name
111 hiBootExt = "hi-boot"
112 hiBootVerExt = "hi-boot-" ++ cHscIfaceFileVersion
114 maybeHomeModule :: ModuleName -> IO (Maybe (Module, ModLocation))
115 maybeHomeModule mod_name = do
116 home_path <- readIORef v_Import_paths
117 hisuf <- readIORef v_Hi_suf
118 mode <- readIORef v_GhcMode
122 [ ("hs", mkHomeModLocation mod_name False)
123 , ("lhs", mkHomeModLocation mod_name False)
126 hi_exts = [ (hisuf, mkHiOnlyModLocation hisuf mod_name) ]
129 [ (hiBootVerExt, mkHiOnlyModLocation hisuf mod_name)
130 , (hiBootExt, mkHiOnlyModLocation hisuf mod_name)
133 -- In compilation manager modes, we look for source files in the home
134 -- package because we can compile these automatically. In one-shot
135 -- compilation mode we look for .hi and .hi-boot files only.
137 -- When generating dependencies, we're interested in either category.
140 | mode == DoMkDependHS = hi_exts ++ source_exts ++ boot_exts
141 | isCompManagerMode mode = source_exts
142 | otherwise {-one-shot-} = hi_exts ++ boot_exts
144 searchPathExts home_path mod_name exts
146 -- -----------------------------------------------------------------------------
147 -- Looking for a package module
149 findPackageMod :: ModuleName -> IO (Maybe (Module, ModLocation))
150 findPackageMod mod_name = do
151 mode <- readIORef v_GhcMode
152 imp_dirs <- getPackageImportPath -- including the 'auto' ones
154 -- hi-suffix for packages depends on the build tag.
156 do tag <- readIORef v_Build_tag
159 else return (tag ++ "_hi")
163 [ (package_hisuf, mkPackageModLocation package_hisuf mod_name) ]
166 [ ("hs", mkPackageModLocation package_hisuf mod_name)
167 , ("lhs", mkPackageModLocation package_hisuf mod_name)
170 -- mkdependHS needs to look for source files in packages too, so
171 -- that we can make dependencies between package before they have
174 | mode == DoMkDependHS = hi_exts ++ source_exts
175 | otherwise = hi_exts
177 -- we never look for a .hi-boot file in an external package;
178 -- .hi-boot files only make sense for the home package.
179 searchPathExts imp_dirs mod_name exts
181 -- -----------------------------------------------------------------------------
182 -- General path searching
185 :: [FilePath] -- paths to search
186 -> ModuleName -- module name
189 String -> String -> String -> IO (Module, ModLocation) -- action
192 -> IO (Maybe (Module, ModLocation))
194 searchPathExts path mod_name exts = search path
196 mod_str = moduleNameUserString mod_name
197 basename = map (\c -> if c == '.' then '/' else c) mod_str
199 search [] = return Nothing
200 search (p:ps) = loop exts
202 base | p == "." = basename
203 | otherwise = p ++ '/':basename
206 loop ((ext,fn):exts) = do
207 let file = base ++ '.':ext
208 b <- doesFileExist file
209 if b then Just `liftM` fn p basename ext
212 -- -----------------------------------------------------------------------------
213 -- Building ModLocations
215 mkHiOnlyModLocation hisuf mod_name path basename extension = do
216 addToFinderCache mod_name result
219 result = ( mkHomeModule mod_name, hiOnlyModLocation path basename hisuf )
221 mkPackageModLocation hisuf mod_name path basename _extension = do
222 addToFinderCache mod_name result
225 result = ( mkPackageModule mod_name, hiOnlyModLocation path basename hisuf )
227 hiOnlyModLocation path basename hisuf =
228 ModLocation{ ml_hspp_file = Nothing,
229 ml_hs_file = Nothing,
230 -- remove the .hi-boot suffix from hi_file, if it
231 -- had one. We always want the name of the real
232 -- .hi file in the ml_hi_file field.
233 ml_hi_file = path ++ '/':basename ++ '.':hisuf,
234 ml_obj_file = Nothing
237 -- -----------------------------------------------------------------------------
238 -- Constructing a home module location
240 -- The .hi file always follows the module name, whereas the object
241 -- file may follow the name of the source file in the case where the
242 -- two differ (see summariseFile in compMan/CompManager.lhs).
244 -- The source filename is specified in three components. For example,
245 -- if we have a module "A.B.C" which was found along the patch "/P/Q/R"
246 -- with extension ".hs", then the full filename is "/P/Q/R/A/B/C.hs". The
247 -- components passed to mkHomeModLocation are
253 -- the object file and interface file are constructed by possibly
254 -- replacing the path component with the values of the -odir or the
255 -- -hidr options respectively, and the extension with the values of
256 -- the -osuf and -hisuf options respectively. That is, the basename
257 -- always remains intact.
259 -- mkHomeModLocation is called directly by the compilation manager to
260 -- construct the information for a root module. For a "root" module,
261 -- the rules are slightly different. The filename is allowed to
262 -- diverge from the module name, but we have to name the interface
263 -- file after the module name. For example, a root module
264 -- "/P/Q/R/foo.hs" will have components
270 -- and we set the flag is_root to True, to indicate that the basename
271 -- portion for the .hi file should be replaced by the last component
272 -- of the module name. eg. if the module name is "A.B.C" then basename
273 -- will be replaced by "C" for the .hi file only, resulting in an
274 -- .hi file like "/P/Q/R/C.hi" (subject to -hidir and -hisuf as usual).
276 mkHomeModLocation mod_name is_root path basename extension = do
278 hisuf <- readIORef v_Hi_suf
279 hidir <- readIORef v_Hi_dir
280 odir <- readIORef v_Output_dir
281 osuf <- readIORef v_Object_suf
284 mod_str = moduleNameUserString mod_name
285 (_,mod_suf) = split_longest_prefix mod_str (=='.')
289 | otherwise = basename
291 hi_path | Just d <- hidir = d
293 hi_fn = hi_path ++ '/':hi_basename ++ '.':hisuf
295 -- source filename (extension is always .hs or .lhs)
297 | path == "." = basename ++ '.':extension
298 | otherwise = path ++ '/':basename ++ '.':extension
300 -- the object filename
301 obj_path | Just d <- odir = d
303 obj_fn = obj_path ++ '/':basename ++ '.':osuf
306 result = ( mkHomeModule mod_name,
307 ModLocation{ ml_hspp_file = Nothing,
308 ml_hs_file = Just source_fn,
310 ml_obj_file = Just obj_fn,
313 addToFinderCache mod_name result
317 -- -----------------------------------------------------------------------------
318 -- findLinkable isn't related to the other stuff in here,
319 -- but there' no other obvious place for it
322 findLinkable :: ModuleName -> ModLocation -> IO (Maybe Linkable)
323 findLinkable mod locn
324 | Just obj_fn <- ml_obj_file locn
325 = do obj_exist <- doesFileExist obj_fn
329 do let stub_fn = case splitFilename3 obj_fn of
330 (dir, base, ext) -> dir ++ "/" ++ base ++ ".stub_o"
331 stub_exist <- doesFileExist stub_fn
332 obj_time <- getModificationTime obj_fn
334 then return (Just (LM obj_time mod [DotO obj_fn, DotO stub_fn]))
335 else return (Just (LM obj_time mod [DotO obj_fn]))