text " Main.main not exported; not linking.")
return Succeeded
-
-- -----------------------------------------------------------------------------
-- Compile files in one-shot mode.
]
| otherwise = []
+ rc_objs <- maybeCreateManifest dflags output_fn
+
let (md_c_flags, _) = machdepCCOpts dflags
SysTools.runLink dflags (
[ SysTools.Option verb
++ extra_ld_inputs
++ lib_path_opts
++ extra_ld_opts
+ ++ rc_objs
#ifdef darwin_TARGET_OS
++ framework_path_opts
++ framework_opts
"a.out"
#endif
+maybeCreateManifest
+ :: DynFlags
+ -> FilePath -- filename of executable
+ -> IO [FilePath] -- extra objects to embed, maybe
+maybeCreateManifest dflags exe_filename = do
+#ifndef mingw32_TARGET_OS
+ return []
+#else
+ if not (dopt Opt_GenManifest dflags) then return [] else do
+
+ let manifest_filename = exe_filename `joinFileExt` "manifest"
+
+ writeFile manifest_filename $
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"++
+ " <assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n"++
+ " <assemblyIdentity version=\"1.0.0.0\"\n"++
+ " processorArchitecture=\"X86\"\n"++
+ " name=\"" ++ basenameOf exe_filename ++ "\"\n"++
+ " type=\"win32\"/>\n\n"++
+ " <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n"++
+ " <security>\n"++
+ " <requestedPrivileges>\n"++
+ " <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\"/>\n"++
+ " </requestedPrivileges>\n"++
+ " </security>\n"++
+ " </trustInfo>\n"++
+ "</assembly>\n"
+
+ -- Windows will fine the manifest file if it is named foo.exe.manifest.
+ -- However, for extra robustness, and so that we can move the binary around,
+ -- we can embed the manifest in the binary itself using windres:
+ if not (dopt Opt_EmbedManifest dflags) then return [] else do
+
+ rc_filename <- newTempName dflags "rc"
+ rc_obj_filename <- newTempName dflags (objectSuf dflags)
+
+ writeFile rc_filename $
+ "1 24 MOVEABLE PURE \"" ++ manifest_filename ++ "\"\n"
+ -- magic numbers :-)
+
+ let wr_opts = getOpts dflags opt_windres
+ runWindres dflags $ map SysTools.Option $
+ ["--input="++rc_filename,
+ "--output="++rc_obj_filename,
+ "--output-format=coff"]
+ ++ wr_opts
+ -- no FileOptions here: windres doesn't like seeing
+ -- backslashes, apparently
+
+ return [rc_obj_filename]
+#endif
+
+
linkDynLib :: DynFlags -> [String] -> [PackageId] -> IO ()
linkDynLib dflags o_files dep_packages = do
let verb = getVerbFlag dflags
| Opt_Haddock
| Opt_Hpc_No_Auto
| Opt_BreakOnException
+ | Opt_GenManifest
+ | Opt_EmbedManifest
-- keeping stuff
| Opt_KeepHiDiffs
opt_a :: [String],
opt_l :: [String],
opt_dep :: [String],
+ opt_windres :: [String],
-- commands for particular phases
pgm_L :: String,
pgm_dll :: (String,[Option]),
pgm_T :: String,
pgm_sysman :: String,
+ pgm_windres :: String,
-- Package flags
extraPkgConfs :: [FilePath],
opt_m = [],
opt_l = [],
opt_dep = [],
+ opt_windres = [],
extraPkgConfs = [],
packageFlags = [],
Opt_DoAsmMangling,
+ Opt_GenManifest,
+ Opt_EmbedManifest,
+
-- on by default:
Opt_PrintBindResult ]
++ [f | (ns,f) <- optLevelFlags, 0 `elem` ns]
setPgma f d = d{ pgm_a = (f,[])}
setPgml f d = d{ pgm_l = (f,[])}
setPgmdll f d = d{ pgm_dll = (f,[])}
+setPgmwindres f d = d{ pgm_windres = f}
addOptL f d = d{ opt_L = f : opt_L d}
addOptP f d = d{ opt_P = f : opt_P d}
addOpta f d = d{ opt_a = f : opt_a d}
addOptl f d = d{ opt_l = f : opt_l d}
addOptdep f d = d{ opt_dep = f : opt_dep d}
+addOptwindres f d = d{ opt_windres = f : opt_windres d}
addCmdlineFramework f d = d{ cmdlineFrameworks = f : cmdlineFrameworks d}
, ( "pgma" , HasArg (upd . setPgma) )
, ( "pgml" , HasArg (upd . setPgml) )
, ( "pgmdll" , HasArg (upd . setPgmdll) )
+ , ( "pgmwindres" , HasArg (upd . setPgmwindres) )
, ( "optL" , HasArg (upd . addOptL) )
, ( "optP" , HasArg (upd . addOptP) )
, ( "opta" , HasArg (upd . addOpta) )
, ( "optl" , HasArg (upd . addOptl) )
, ( "optdep" , HasArg (upd . addOptdep) )
+ , ( "optwindres" , HasArg (upd . addOptwindres) )
, ( "split-objs" , NoArg (if can_split
then setDynFlag Opt_SplitObjs
-- Deprecated in favour of -XUndecidableInstances:
( "allow-undecidable-instances", Opt_UndecidableInstances ),
-- Deprecated in favour of -XIncoherentInstances:
- ( "allow-incoherent-instances", Opt_IncoherentInstances )
+ ( "allow-incoherent-instances", Opt_IncoherentInstances ),
+ ( "gen-manifest", Opt_GenManifest ),
+ ( "embed-manifest", Opt_EmbedManifest )
]
supportedLanguages :: [String]
runMangle, runSplit, -- [Option] -> IO ()
runAs, runLink, -- [Option] -> IO ()
runMkDLL,
+ runWindres,
touch, -- String -> String -> IO ()
copy,
| am_installed = installed_bin cGHC_MANGLER_PGM
| otherwise = inplace cGHC_MANGLER_DIR_REL cGHC_MANGLER_PGM
+ windres_path
+ | am_installed = installed_bin "windres"
+ | otherwise = "windres"
+
; let dflags0 = defaultDynFlags
#ifndef mingw32_HOST_OS
-- check whether TMPDIR is set in the environment
pgm_l = (ld_prog,ld_args),
pgm_dll = (mkdll_prog,mkdll_args),
pgm_T = touch_path,
- pgm_sysman = top_dir ++ "/ghc/rts/parallel/SysMan"
+ pgm_sysman = top_dir ++ "/ghc/rts/parallel/SysMan",
+ pgm_windres = windres_path
-- Hans: this isn't right in general, but you can
-- elaborate it in the same way as the others
}
mb_env <- getGccEnv (args0++args)
runSomethingFiltered dflags id "Make DLL" p args1 mb_env
+runWindres :: DynFlags -> [Option] -> IO ()
+runWindres dflags args = do
+ let (gcc,gcc_args) = pgm_c dflags
+ windres = pgm_windres dflags
+ runSomething dflags "Windres" windres
+ (Option ("--preprocessor=" ++ gcc ++ unwords (map showOpt gcc_args) ++
+ " -E -xc -DRC_INVOKED")
+ : args)
+ -- we must tell windres where to find gcc: it might not be on PATH
+
touch :: DynFlags -> String -> String -> IO ()
touch dflags purpose arg =
runSomething dflags purpose (pgm_T dflags) [FileOption "" arg]
cp $mingw_bin/as.exe gcc-lib/
cp $mingw_bin/ld.exe gcc-lib/
cp $mingw_bin/ar.exe bin/
+cp $mingw_bin/windres.exe bin/
# Note: later versions of dlltool.exe depend on a bfd helper DLL.
cp $mingw_bin/dllwrap.exe gcc-lib/
cp $mingw_bin/dlltool.exe gcc-lib/