2 % (c) The University of Glasgow, 2000
4 \section[Finder]{Module Finder}
8 initFinder, -- :: [PackageConfig] -> IO (),
9 findModule, -- :: ModuleName -> IO (Maybe (Module, ModuleLocation))
10 findModuleDep, -- :: ModuleName -> Bool -> IO (Maybe (Module, ModuleLocation))
11 findPackageModule, -- :: ModuleName -> IO (Maybe (Module, ModuleLocation))
12 mkHomeModuleLocn, -- :: ModuleName -> String -> FilePath
13 -- -> IO ModuleLocation
14 emptyHomeDirCache, -- :: IO ()
15 flushPackageCache -- :: [PackageConfig] -> IO ()
18 #include "HsVersions.h"
20 import HscTypes ( ModuleLocation(..) )
21 import Packages ( PackageConfig(..) )
36 The Finder provides a thin filesystem abstraction to the rest of the
37 compiler. For a given module, it knows (a) which package the module
38 lives in, so it can make a Module from a ModuleName, and (b) where the
39 source, interface, and object files for a module live.
42 initFinder :: [PackageConfig] -> IO ()
43 initFinder pkgs = return ()
45 -- empty, and lazilly fill in the package cache
46 flushPackageCache :: [PackageConfig] -> IO ()
47 flushPackageCache pkgs = return ()
49 emptyHomeDirCache :: IO ()
50 emptyHomeDirCache = return ()
52 findModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
53 findModule name = findModuleDep name False
55 findModuleDep :: ModuleName -> Bool -> IO (Maybe (Module, ModuleLocation))
56 findModuleDep name is_source
57 = do { j <- maybeHomeModule name is_source
59 Just home_module -> return (Just home_module)
60 Nothing -> findPackageMod name False
63 maybeHomeModule :: ModuleName -> Bool -> IO (Maybe (Module, ModuleLocation))
64 maybeHomeModule mod_name is_source = do
65 home_path <- readIORef v_Import_paths
66 hisuf <- readIORef v_Hi_suf
67 mode <- readIORef v_GhcMode
69 let mod_str = moduleNameUserString mod_name
70 basename = map (\c -> if c == '.' then '/' else c) mod_str
72 -- In compilation manager modes, we look for source files in the home
73 -- package because we can compile these automatically. In one-shot
74 -- compilation mode we look for .hi files only.
76 -- When generating dependencies, we're interested in either category.
79 [ ("hs", \ _ fName path -> mkHomeModuleLocn mod_name path fName)
80 , ("lhs", \ _ fName path -> mkHomeModuleLocn mod_name path fName)
82 hi_exts = [ (hisuf, \ _ fName path -> mkHiOnlyModuleLocn mod_name fName) ]
85 | mode == DoMkDependHS = hi_exts ++ source_exts
86 | isCompManagerMode mode = source_exts
89 -- last chance: .hi-boot-<ver> and .hi-boot
90 hi_boot_ver = "hi-boot-" ++ cHscIfaceFileVersion
93 [ (hi_boot_ver, \ _ fName path -> mkHiOnlyModuleLocn mod_name fName)
94 , ("hi-boot", \ _ fName path -> mkHiOnlyModuleLocn mod_name fName)
98 (map ((,) undefined) home_path)
100 (if is_source then (boot_exts++std_exts) else std_exts ++ boot_exts)
101 -- for SOURCE imports, check the hi-boot extensions
102 -- before the source/iface ones, to avoid
103 -- creating circ Makefile deps.
105 mkHiOnlyModuleLocn mod_name hi_file =
107 ( mkHomeModule mod_name
108 , ModuleLocation{ ml_hspp_file = Nothing
109 , ml_hs_file = Nothing
110 , ml_hi_file = hi_file
111 , ml_obj_file = Nothing
115 -- The .hi file always follows the module name, whereas the object
116 -- file may follow the name of the source file in the case where the
117 -- two differ (see summariseFile in compMan/CompManager.lhs).
119 mkHomeModuleLocn mod_name
120 basename -- everything but the extension
121 source_fn -- full path to the source (required)
124 hisuf <- readIORef v_Hi_suf
125 hidir <- readIORef v_Hi_dir
127 -- take the *last* component of the module name (if a hierarchical name),
128 -- and append it to the directory to get the .hi file name.
129 let (_,mod_str) = split_longest_prefix (moduleNameUserString mod_name) (=='.')
130 hi_filename = mod_str ++ '.':hisuf
131 hi_path | Just d <- hidir = d
132 | otherwise = getdir basename
133 hi = hi_path ++ '/':hi_filename
135 -- figure out the .o file name. It also lives in the same dir
136 -- as the source, but can be overriden by a -odir flag.
137 o_file <- odir_ify (basename ++ '.':phaseInputExt Ln) >>= osuf_ify
139 return (mkHomeModule mod_name,
140 ModuleLocation{ ml_hspp_file = Nothing
141 , ml_hs_file = Just source_fn
143 , ml_obj_file = Just o_file
146 findPackageMod :: ModuleName
148 -> IO (Maybe (Module, ModuleLocation))
149 findPackageMod mod_name hiOnly = do
150 pkgs <- getPackageInfo
152 -- hi-suffix for packages depends on the build tag.
154 do tag <- readIORef v_Build_tag
157 else return (tag ++ "_hi")
158 let imp_dirs = concatMap (\ pkg -> map ((,) pkg) (import_dirs pkg)) pkgs
159 mod_str = moduleNameUserString mod_name
160 basename = map (\c -> if c == '.' then '/' else c) mod_str
162 mkPackageModule mod_name pkg mbFName path =
163 return ( mkModule mod_name (mkFastString (name pkg))
164 , ModuleLocation{ ml_hspp_file = Nothing
165 , ml_hs_file = mbFName
166 , ml_hi_file = path ++ '.':package_hisuf
167 , ml_obj_file = Nothing
172 ((package_hisuf,\ pkg fName path -> mkPackageModule mod_name pkg Nothing path) :
173 -- can packages contain hi-boots?
174 (if hiOnly then [] else
175 [ ("hs", \ pkg fName path -> mkPackageModule mod_name pkg (Just fName) path)
176 , ("lhs", \ pkg fName path -> mkPackageModule mod_name pkg (Just fName) path)
180 findPackageModule :: ModuleName -> IO (Maybe (Module, ModuleLocation))
181 findPackageModule mod_name = findPackageMod mod_name True
183 searchPathExts :: [(a, FilePath)]
185 -> [(String, a -> FilePath -> String -> IO (Module, ModuleLocation))]
186 -> IO (Maybe (Module, ModuleLocation))
187 searchPathExts path basename exts = search exts
189 search [] = return Nothing
190 search ((x,f):xs) = do
191 let fName = (basename ++ '.':x)
192 found <- findOnPath path fName
194 -- special case to avoid getting "./foo.<ext>" all the time
195 Just (v,".") -> fmap Just (f v fName basename)
196 Just (v,path) -> fmap Just (f v (path ++ '/':fName)
197 (path ++ '/':basename))
200 findOnPath :: [(a,String)] -> String -> IO (Maybe (a, FilePath))
201 findOnPath path s = loop path
203 loop [] = return Nothing
205 let file = d ++ '/':s
206 b <- doesFileExist file
207 if b then return (Just (a,d)) else loop ds