+-- MoveBinary sort-of-phase
+-- After having produced a binary, move it somewhere else and generate a
+-- wrapper script calling the binary. Currently, we need this only in
+-- a parallel way (i.e. in GUM), because PVM expects the binary in a
+-- central directory.
+-- This is called from doLink below, after linking. I haven't made it
+-- a separate phase to minimise interfering with other modules, and
+-- we don't need the generality of a phase (MoveBinary is always
+-- done after linking and makes only sense in a parallel setup) -- HWL
+
+run_phase_MoveBinary input_fn
+ = do
+ top_dir <- readIORef v_TopDir
+ pvm_root <- getEnv "PVM_ROOT"
+ pvm_arch <- getEnv "PVM_ARCH"
+ let
+ pvm_executable_base = "=" ++ input_fn
+ pvm_executable = pvm_root ++ "/bin/" ++ pvm_arch ++ "/" ++ pvm_executable_base
+ sysMan = top_dir ++ "/ghc/rts/parallel/SysMan";
+ -- nuke old binary; maybe use configur'ed names for cp and rm?
+ system ("rm -f " ++ pvm_executable)
+ -- move the newly created binary into PVM land
+ system ("cp -p " ++ input_fn ++ " " ++ pvm_executable)
+ -- generate a wrapper script for running a parallel prg under PVM
+ writeFile input_fn (mk_pvm_wrapper_script pvm_executable pvm_executable_base sysMan)
+ return True
+
+-- generates a Perl skript starting a parallel prg under PVM
+mk_pvm_wrapper_script :: String -> String -> String -> String
+mk_pvm_wrapper_script pvm_executable pvm_executable_base sysMan = unlines $
+ [
+ "eval 'exec perl -S $0 ${1+\"$@\"}'",
+ " if $running_under_some_shell;",
+ "# =!=!=!=!=!=!=!=!=!=!=!",
+ "# This script is automatically generated: DO NOT EDIT!!!",
+ "# Generated by Glasgow Haskell Compiler",
+ "# ngoqvam choHbogh vaj' vIHoHnISbej !!!!",
+ "#",
+ "$pvm_executable = '" ++ pvm_executable ++ "';",
+ "$pvm_executable_base = '" ++ pvm_executable_base ++ "';",
+ "$SysMan = '" ++ sysMan ++ "';",
+ "",
+ {- ToDo: add the magical shortcuts again iff we actually use them -- HWL
+ "# first, some magical shortcuts to run "commands" on the binary",
+ "# (which is hidden)",
+ "if ($#ARGV == 1 && $ARGV[0] eq '+RTS' && $ARGV[1] =~ /^--((size|file|strip|rm|nm).*)/ ) {",
+ " local($cmd) = $1;",
+ " system("$cmd $pvm_executable");",
+ " exit(0); # all done",
+ "}", -}
+ "",
+ "# Now, run the real binary; process the args first",
+ "$ENV{'PE'} = $pvm_executable_base;", -- ++ pvm_executable_base,
+ "$debug = '';",
+ "$nprocessors = 0; # the default: as many PEs as machines in PVM config",
+ "@nonPVM_args = ();",
+ "$in_RTS_args = 0;",
+ "",
+ "args: while ($a = shift(@ARGV)) {",
+ " if ( $a eq '+RTS' ) {",
+ " $in_RTS_args = 1;",
+ " } elsif ( $a eq '-RTS' ) {",
+ " $in_RTS_args = 0;",
+ " }",
+ " if ( $a eq '-d' && $in_RTS_args ) {",
+ " $debug = '-';",
+ " } elsif ( $a =~ /^-qN(\\d+)/ && $in_RTS_args ) {",
+ " $nprocessors = $1;",
+ " } elsif ( $a =~ /^-qp(\\d+)/ && $in_RTS_args ) {",
+ " $nprocessors = $1;",
+ " } else {",
+ " push(@nonPVM_args, $a);",
+ " }",
+ "}",
+ "",
+ "local($return_val) = 0;",
+ "# Start the parallel execution by calling SysMan",
+ "system(\"$SysMan $debug $pvm_executable $nprocessors @nonPVM_args\");",
+ "$return_val = $?;",
+ "# ToDo: fix race condition moving files and flushing them!!",
+ "system(\"cp $ENV{'HOME'}/$pvm_executable_base.???.gr .\") if -f \"$ENV{'HOME'}/$pvm_executable_base.002.gr\";",
+ "exit($return_val);"
+ ]
+
+-----------------------------------------------------------------------------
+-- Complain about non-dynamic flags in OPTIONS pragmas
+
+checkProcessArgsResult flags basename suff
+ = do when (not (null flags)) (throwDyn (OtherError (
+ basename ++ "." ++ suff
+ ++ ": static flags are not allowed in {-# OPTIONS #-} pragmas:\n\t"
+ ++ unwords flags)) (ExitFailure 1))
+
+-----------------------------------------------------------------------------