-----------------------------------------------------------------------------
--- $Id: DriverPipeline.hs,v 1.42 2000/12/18 12:43:04 sewardj Exp $
+-- $Id: DriverPipeline.hs,v 1.47 2001/01/09 17:16:35 rrt Exp $
--
-- GHC Driver
--
--
-----------------------------------------------------------------------------
+#include "../includes/config.h"
+
module DriverPipeline (
-- interfaces for the batch-mode driver
GhcMode(..), getGhcMode, v_GhcMode,
- genPipeline, runPipeline,
+ genPipeline, runPipeline, pipeLoop,
-- interfaces for the compilation manager (interpreted/batch-mode)
preprocess, compile, CompResult(..),
-- batch-mode linking interface
- doLink
+ doLink,
+ -- DLL building
+ doMkDLL
) where
#include "HsVersions.h"
-import CmStaticInfo ( GhciMode(..) )
+import CmStaticInfo
import CmTypes
import GetImports
import DriverState
import Monad
import Maybe
+import PackedString
+import MatchPS
+
-----------------------------------------------------------------------------
-- GHC modes of operation
data GhcMode
= DoMkDependHS -- ghc -M
- | DoMkDLL -- ghc -mk-dll
+ | DoMkDLL -- ghc --mk-dll
| StopBefore Phase -- ghc -E | -C | -S | -c
| DoMake -- ghc --make
| DoInteractive -- ghc --interactive
modeFlag :: String -> Maybe GhcMode
modeFlag "-M" = Just $ DoMkDependHS
+modeFlag "--mk-dll" = Just $ DoMkDLL
modeFlag "-E" = Just $ StopBefore Hsc
modeFlag "-C" = Just $ StopBefore HCc
modeFlag "-S" = Just $ StopBefore As
([(flag,one)], rest) -> return (rest, one, flag)
(_ , _ ) ->
throwDyn (OtherError
- "only one of the flags -M, -E, -C, -S, -c, --make, --interactive is allowed")
+ "only one of the flags -M, -E, -C, -S, -c, --make, --interactive, -mk-dll is allowed")
-----------------------------------------------------------------------------
-- genPipeline
----------- ----- ---- --- -- -- - - -
(_basename, suffix) = splitFilename filename
- start_phase = startPhase suffix
+ start = startPhase suffix
+
+ -- special case for mkdependHS: .hspp files go through MkDependHS
+ start_phase | todo == DoMkDependHS && start == Hsc = MkDependHS
+ | otherwise = start
haskellish = haskellish_suffix suffix
cish = cish_suffix suffix
- -- for a .hc file we need to force lang to HscC
+ -- for a .hc file we need to force lang to HscC
real_lang | start_phase == HCc = HscC
| otherwise = lang
++ filename))
else do
- -- if we can't find the phase we're supposed to stop before,
- -- something has gone wrong.
- case todo of
- StopBefore phase ->
- when (phase /= Ln
- && phase `notElem` pipeline
- && not (phase == As && SplitAs `elem` pipeline)) $
- throwDyn (OtherError
- ("flag " ++ stop_flag
- ++ " is incompatible with source file `" ++ filename ++ "'"))
- _ -> return ()
-
let
----------- ----- ---- --- -- -- - - -
myPhaseInputExt Ln = case osuf of Nothing -> phaseInputExt Ln
-- the suffix on an output file is determined by the next phase
-- in the pipeline, so we add linking to the end of the pipeline
-- to force the output from the final phase to be a .o file.
- stop_phase = case todo of StopBefore phase -> phase
- DoMkDependHS -> Ln
- DoLink -> Ln
+ stop_phase = case todo of
+ StopBefore As | split -> SplitAs
+ StopBefore phase -> phase
+ DoMkDependHS -> Ln
+ DoLink -> Ln
annotated_pipeline = annotatePipeline (pipeline ++ [ Ln ]) stop_phase
phase_ne p (p1,_,_) = (p1 /= p)
----------- ----- ---- --- -- -- - - -
- return $
- dropWhile (phase_ne start_phase) .
- foldr (\p ps -> if phase_ne stop_phase p then p:ps else []) []
- $ annotated_pipeline
+ -- if we can't find the phase we're supposed to stop before,
+ -- something has gone wrong. This test carefully avoids the
+ -- case where we aren't supposed to do any compilation, because the file
+ -- is already in linkable form (for example).
+ if start_phase `elem` pipeline &&
+ (stop_phase /= Ln && stop_phase `notElem` pipeline)
+ then throwDyn (OtherError
+ ("flag " ++ stop_flag
+ ++ " is incompatible with source file `" ++ filename ++ "'"))
+ else do
+
+ return (
+ takeWhile (phase_ne stop_phase ) $
+ dropWhile (phase_ne start_phase) $
+ annotated_pipeline
+ )
runPipeline
#ifdef mingw32_TARGET_OS
let extra_os = if static || no_hs_main
then []
--- else [ head (lib_paths (head rts_pkg)) ++ "/Main.dll_o",
--- head (lib_paths (head std_pkg)) ++ "/PrelMain.dll_o" ]
- else []
+ else [ head (library_dirs (head rts_pkg)) ++ "/Main.dll_o",
+ head (library_dirs (head std_pkg)) ++ "/PrelMain.dll_o" ]
#endif
(md_c_flags, _) <- machdepCCOpts
runSomething "Linker"
)
-----------------------------------------------------------------------------
+-- Making a DLL
+
+-- only for Win32, but bits that are #ifdefed in doLn are still #ifdefed here
+-- in a vain attempt to aid future portability
+doMkDLL :: [String] -> IO ()
+doMkDLL o_files = do
+ ln <- readIORef v_Pgm_dll
+ verb <- getVerbFlag
+ static <- readIORef v_Static
+ let imp = if static then "" else "_imp"
+ no_hs_main <- readIORef v_NoHsMain
+
+ o_file <- readIORef v_Output_file
+ let output_fn = case o_file of { Just s -> s; Nothing -> "HSdll.dll"; }
+
+ pkg_lib_paths <- getPackageLibraryPath
+ let pkg_lib_path_opts = map ("-L"++) pkg_lib_paths
+
+ lib_paths <- readIORef v_Library_paths
+ let lib_path_opts = map ("-L"++) lib_paths
+
+ pkg_libs <- getPackageLibraries
+ let pkg_lib_opts = map (\lib -> "-l" ++ lib ++ imp) pkg_libs
+
+ libs <- readIORef v_Cmdline_libraries
+ let lib_opts = map ("-l"++) (reverse libs)
+ -- reverse because they're added in reverse order from the cmd line
+
+ pkg_extra_ld_opts <- getPackageExtraLdOpts
+
+ -- probably _stub.o files
+ extra_ld_inputs <- readIORef v_Ld_inputs
+
+ -- opts from -optdll-<blah>
+ extra_ld_opts <- getStaticOpts v_Opt_dll
+
+ rts_pkg <- getPackageDetails ["rts"]
+ std_pkg <- getPackageDetails ["std"]
+#ifdef mingw32_TARGET_OS
+ let extra_os = if static || no_hs_main
+ then []
+ else [ head (library_dirs (head rts_pkg)) ++ "/Main.dll_o",
+ head (library_dirs (head std_pkg)) ++ "/PrelMain.dll_o" ]
+#endif
+ (md_c_flags, _) <- machdepCCOpts
+ runSomething "DLL creator"
+ (unwords
+ ([ ln, verb, "-o", output_fn ]
+ ++ md_c_flags
+ ++ o_files
+#ifdef mingw32_TARGET_OS
+ ++ extra_os
+ ++ [ "--target=i386-mingw32" ]
+#endif
+ ++ extra_ld_inputs
+ ++ lib_path_opts
+ ++ lib_opts
+ ++ pkg_lib_path_opts
+ ++ pkg_lib_opts
+ ++ pkg_extra_ld_opts
+ ++ (case findPS (packString (concat extra_ld_opts)) (packString "--def") of
+ Nothing -> [ "--export-all" ]
+ Just _ -> [ "" ])
+ ++ extra_ld_opts
+ )
+ )
+
+-----------------------------------------------------------------------------
-- Just preprocess a file, put the result in a temp. file (used by the
-- compilation manager during the summary phase).