[project @ 2003-10-21 11:42:30 by simonmar]
authorsimonmar <unknown>
Tue, 21 Oct 2003 11:42:30 +0000 (11:42 +0000)
committersimonmar <unknown>
Tue, 21 Oct 2003 11:42:30 +0000 (11:42 +0000)
Change the filename policies (again).  Now the interface file and
object file always follow the source file unless the -odir or -hidir
options are specified.

ghc/compiler/main/Finder.lhs
ghc/docs/users_guide/separate_compilation.sgml

index adc33c7..3137fa2 100644 (file)
@@ -230,16 +230,17 @@ mkPackageModLocation hisuf mod_name path basename _ext = do
   return result
 
 hiOnlyModLocation path basename hisuf 
- = do { obj_fn <- mkObjPath path basename ;
-        return (ModLocation{ ml_hspp_file = Nothing,
+ = do let full_basename = path++'/':basename
+      obj_fn <- mkObjPath full_basename basename
+      return ModLocation{ ml_hspp_file = Nothing,
                             ml_hs_file   = Nothing,
-                            ml_hi_file   = path ++ '/':basename ++ '.':hisuf,
+                            ml_hi_file   = full_basename ++ '.':hisuf,
                                -- Remove the .hi-boot suffix from
                                -- hi_file, if it had one.  We always
                                -- want the name of the real .hi file
                                -- in the ml_hi_file field.
                             ml_obj_file  = obj_fn
-                 })}
+                  }
 
 -- -----------------------------------------------------------------------------
 -- Constructing a home module location
@@ -275,59 +276,57 @@ hiOnlyModLocation path basename hisuf
 --     The filename extension of the source file (usually "hs" or "lhs").
 
 mkHomeModLocation mod_name src_filename = do
-   let mod_basename = dots_to_slashes (moduleNameUserString mod_name)
-       (basename,extension) = splitFilename src_filename
-
-   case maybePrefixMatch (reverse mod_basename) (reverse basename) of
-       Just ""   ->
-          mkHomeModLocationSearched mod_name "."  mod_basename extension
-       Just rest@(r:_) | isPathSeparator r -> do
-          let path = reverse (dropWhile (=='/') rest)
-          mkHomeModLocationSearched mod_name path mod_basename extension
-       _ -> do
-         -- hPutStrLn stderr ("Warning: " ++ src_filename ++
-         --                     ": filename and module name do not match")
-         let (dir,basename,ext) = splitFilename3 src_filename
-         mkHomeModLocationSearched mod_name dir basename ext
-
-mkHomeModLocationSearched mod_name path src_basename ext = do
-   hisuf  <- readIORef v_Hi_suf
-   hidir  <- readIORef v_Hi_dir
-
-   let mod_basename = dots_to_slashes (moduleNameUserString mod_name)
-
-   obj_fn <- mkObjPath path mod_basename
+   let (basename,extension) = splitFilename src_filename
+   mkHomeModLocation' mod_name basename extension
 
-   let  -- hi filename, always follows the module name
-       hi_path | Just d <- hidir = d
-              | otherwise       = path
+mkHomeModLocationSearched mod_name path basename ext =
+   mkHomeModLocation' mod_name (path ++ '/':basename) ext
 
-       hi_fn = hi_path ++ '/':mod_basename ++ '.':hisuf
+mkHomeModLocation' mod_name src_basename ext = do
+   let mod_basename = dots_to_slashes (moduleNameUserString mod_name)
 
-       -- source filename
-       source_fn = path ++ '/':src_basename ++ '.':ext
+   obj_fn <- mkObjPath src_basename mod_basename
+   hi_fn  <- mkHiPath  src_basename mod_basename
 
-       result = ( mkHomeModule mod_name,
-                 ModLocation{ ml_hspp_file = Nothing,
-                              ml_hs_file   = Just source_fn,
-                              ml_hi_file   = hi_fn,
-                              ml_obj_file  = obj_fn,
+   let result = ( mkHomeModule mod_name,
+                  ModLocation{ ml_hspp_file = Nothing,
+                               ml_hs_file   = Just (src_basename ++ '.':ext),
+                               ml_hi_file   = hi_fn,
+                               ml_obj_file  = obj_fn
                       })
 
    addToFinderCache mod_name result
    return result
 
-mkObjPath :: FilePath -> String -> IO FilePath
--- Construct the filename of a .o file.
--- Does *not* check whether the .o file exists
-mkObjPath path basename
+-- | Constructs the filename of a .o file for a given source file.
+-- Does /not/ check whether the .o file exists
+mkObjPath
+  :: FilePath          -- the filename of the source file, minus the extension
+  -> String            -- the module name with dots replaced by slashes
+  -> IO FilePath
+mkObjPath basename mod_basename
   = do  odir   <- readIORef v_Output_dir
        osuf   <- readIORef v_Object_suf
 
-       let obj_path | Just d <- odir = d
-                    | otherwise      = path
+       let obj_basename | Just dir <- odir = dir ++ '/':mod_basename
+                        | otherwise        = basename
+
+        return (obj_basename ++ '.':osuf)
+
+-- | Constructs the filename of a .hi file for a given source file.
+-- Does /not/ check whether the .hi file exists
+mkHiPath
+  :: FilePath          -- the filename of the source file, minus the extension
+  -> String            -- the module name with dots replaced by slashes
+  -> IO FilePath
+mkHiPath basename mod_basename
+  = do  hidir   <- readIORef v_Hi_dir
+       hisuf   <- readIORef v_Hi_suf
+
+       let hi_basename | Just dir <- hidir = dir ++ '/':mod_basename
+                       | otherwise         = basename
 
-        return (obj_path ++ '/':basename ++ '.':osuf)
+        return (hi_basename ++ '.':hisuf)
 
 -- -----------------------------------------------------------------------------
 -- findLinkable isn't related to the other stuff in here, 
index f9a06bf..fe51108 100644 (file)
 
       <para>Every module has a <emphasis>module name</emphasis>
       defined in its source code (<literal>module A.B.C where
-      ...</literal>).  Unless overridden with the
-      <literal>-o</literal> and <literal>-ohi</literal> flags
-      respectively, GHC always puts the object file for module
-      <literal>A.B.C</literal> in
-      <replaceable>odir</replaceable><literal>/A/B/C.</literal><replaceable>osuf</replaceable>,
-      and the interface file in the file
-      <replaceable>hidir</replaceable><literal>/A/B/C.</literal><replaceable>hisuf</replaceable>,
-      where <replaceable>hidir</replaceable>,
-      <replaceable>hisuf</replaceable>,
-      <replaceable>odir</replaceable>, and
-      <replaceable>osuf</replaceable>, defined as follows:
+      ...</literal>).</para>
 
-      <variablelist>
-       <varlistentry>
-         <term><replaceable>hidir</replaceable></term>
-         <listitem>
-           <para>is the value of the <option>-hidir</option> option if
-           one was given (<xref linkend="options-output">), or
-           <replaceable>root-path</replaceable> otherwise.</para>
-         </listitem>
-       </varlistentry>
-       <varlistentry>
-         <term><replaceable>hisuf</replaceable></term>
-         <listitem>
-           <para>is the value of the <option>-hisuf</option> option if
-           one was given (<xref linkend="options-output">), or <literal>hi</literal>
-           otherwise.</para>
-         </listitem>
-       </varlistentry>
-
-       <varlistentry>
-         <term><replaceable>odir</replaceable></term>
-         <listitem>
-           <para>is the value of the <option>-odir</option> option if
-           one was given (<xref linkend="options-output">), or
-           <replaceable>root-path</replaceable> otherwise.</para>
-         </listitem>
-       </varlistentry>
-       <varlistentry>
-         <term><replaceable>osuf</replaceable></term>
-         <listitem>
-           <para>is the value of the <option>-osuf</option> option if
-           one was given (<xref linkend="options-output">), or <literal>o</literal>
-           otherwise (<literal>obj</literal> on Windows).</para>
-         </listitem>
-       </varlistentry>
-      </variablelist>
-
-      The <replaceable>root-path</replaceable>, used in the above definitions, is derived from the
-      location of the source file, <replaceable>source-filename</replaceable>, as follows:
+      <para>The name of the object file generated by GHC is derived
+      according to the following rules, where
+      <replaceable>osuf</replaceable> is the object-file suffix (this
+      can be changed with the <option>-osuf</option> option).</para>
 
-  <variablelist>
-  <varlistentry>
-  <term>Rule 1</term>
-  <listitem>
-  <para>GHC matches <replaceable>source-filename</replaceable> against the pattern:
-  
-  <screen><replaceable>root-path</replaceable>/<literal>A/B/C.</literal><replaceable>extension</replaceable></screen>
-
-      where:
+      <itemizedlist>
+       <listitem>
+         <para>If there is no <option>-odir</option> option (the
+         default), then the object filename is derived from the
+         source filename by replacing the suffix with
+         <replaceable>osuf</replaceable>.</para>
+       </listitem>
+       <listitem>
+         <para>If
+         <option>-odir</option>&nbsp;<replaceable>dir</replaceable>
+         has been specified, then the object filename is
+         <replaceable>dir</replaceable>/<replaceable>mod</replaceable>.<replaceable>osuf</replaceable>,
+         where <replaceable>mod</replaceable> is the module name with
+         dots replaced by slashes.</para>
+       </listitem>
+      </itemizedlist>
 
-      <variablelist>
-       <varlistentry>
-         <term><replaceable>extension</replaceable></term>
-         <listitem>
-           <para>is the source file extension (usually
-           <literal>.hs</literal> or <literal>.lhs</literal>).</para>
-         </listitem>
-       </varlistentry>
-       <varlistentry>
-         <term><replaceable>root-path</replaceable></term>
-         <listitem>
-           <para>is what is left after <literal>A/B/C.</literal><replaceable>extension</replaceable>
-           has been stripped off the end of <replaceable>source-file</replaceable>.</para>
-         </listitem>
-       </varlistentry>
-      </variablelist>
-  </para>
-  </listitem>
-  </varlistentry>
-  
-  <varlistentry>
-  <term>Rule 2</term>
-  <listitem>
-       <para>If <replaceable>source-filename</replaceable> does not match the pattern
-       above (presumably because it doesn't finish with <literal>A/B/C.hs</literal>
-       or <literal>A/B/C.lhs</literal>)
-       then <replaceable>root-path</replaceable> becomes the
-       whole of the directory portion of the filename.  </para>
-  </listitem>
-  </varlistentry>
-  </variablelist>
+      <para>The name of the interface file is derived using the same
+      rules, except that the suffix is
+      <replaceable>hisuf</replaceable> (<literal>.hi</literal> by
+      default) instead of <replaceable>osuf</replaceable>, and the
+      relevant options are <option>-hidir</option> and
+      <option>-hisuf</option> instead of <option>-odir</option> and
+      <option>-osuf</option> respectively.</para>
 
-      For example, if GHC compiles the module
+      <para>For example, if GHC compiles the module
       <literal>A.B.C</literal> in the file
-      <filename>src/A/B/C.hs</filename>, with no <literal>-odir</literal> or <literal>-hidir</literal> flags,
-      the interface file will be put in <literal>src/A/B/C.hi</literal> and the object file in 
-      <literal>src/A/B/C.o</literal> (using Rule 1).
-      If the same module <literal>A.B.C</literal> was in file 
-      <filename>src/ABC.hs</filename>, 
-      the interface file will still be put in <literal>src/A/B/C.hi</literal> and the object file in 
-      <literal>src/A/B/C.o</literal> (using Rule 2).
-      </para>
-      <para>A common use for Rule 2 is to have many modules all called <literal>Main</literal> held in 
-      files <literal>Test1.hs</literal> <literal>Test2.hs</literal>, etc.    Beware, though: when compiling
-      (say) <literal>Test2.hs</literal>, GHC will consult <literal>Main.hi</literal> for version information
-      from the last recompilation.  Currently (a bug, really) GHC is not clever enough to spot that the source file has changed,
-      and so there is a danger that the recompilation checker will declare that no recompilation is needed when in fact it is.
-      Solution: delete the interface file first.
-      </para>
-  <para>Notice that (unless overriden with <option>-o</option> or <option>-ohi</option>) the filenames
-  of the object and interface files are always based on the module name. The reason for this is so that
-  GHC can find the interface file for module <literal>A.B.C</literal> when compiling the declaration
-  "<literal>import A.B.C</literal>".
-  </para>
+      <filename>src/A/B/C.hs</filename>, with no
+      <literal>-odir</literal> or <literal>-hidir</literal> flags, the
+      interface file will be put in <literal>src/A/B/C.hi</literal>
+      and the object file in <literal>src/A/B/C.o</literal>.</para>
+
+      <para>Note that it is reasonable to have a module
+      <literal>Main</literal> in a file named
+      <filename>foo.hs</filename>, but this only works because GHC
+      never needs to search for the interface for module
+      <literal>Main</literal> (because it is never imported).  It is
+      therefore possible to have several <literal>Main</literal>
+      modules in separate source files in the same directory, and GHC
+      will not get confused.  For modules other than
+      <literal>Main</literal>, it is strongly recommended that you
+      name the source file after the module name, replacing dots with
+      slashes in hierarchical module names.</para>
+
+      <para>In batch compilation mode, the name of the object file can
+      also be overriden using the <option>-o</option> option, and the
+      name of the interface file can be specified directly using the
+      <option>-ohi</option> option.</para>
     </sect2>
 
     <sect2 id="search-path">