+
+To add another system library, you'll need to augment the
+Supported_syslibs variable with name and info on your addition
+to the syslib family. The info bit consist of the following:
+
+ - interface file directory
+ see the misc or posix entry for how to distinguish
+ between using installed and build tree directories.
+
+ - directory location of archives
+
+ - location of (way-independent) C support libs.
+ not all libraries need this - if you don't, just
+ give the empty string.
+ - list of syslibs you depend on.
+
+ - additional ghc command line flags that should be used.
+ - additional C compiler command line flags that should be used.
+ - link
+
+
+\begin{code}
+
+# Hash to keep track of
+%Syslibs_added = ();
+
+sub add_syslib {
+ local($syslib) = @_;
+
+ # Lifting this out of this sub brings it out of scope - why??
+ %Supported_syslibs =
+ ( exts,
+ [ # where to slurp interface files from
+ ( $INSTALLING
+ ? "$InstLibDirGhc/imports/exts"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/exts"
+ )
+ , # where to find the archive to use when linking
+ ( $INSTALLING
+ ? "$InstLibDirGhc"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/exts"
+ )
+ , '' # no cbits
+ , '' # Syslib dependencies
+ , '' # extra ghc opts
+ , '' # extra cc opts
+ , '' # extra ld opts
+ ],
+
+ misc,
+ [ # where to slurp interface files from
+ ( $INSTALLING
+ ? "$InstLibDirGhc/imports/misc"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/misc"
+ )
+ , # where to find the archive to use when linking
+ ( $INSTALLING
+ ? "$InstLibDirGhc"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/misc"
+ )
+ , # where to find the cbits archive to use when linking
+ ( $INSTALLING
+ ? "$InstLibDirGhc"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/misc/cbits"
+ )
+ , 'exts' # Syslib dependencies
+ , '' # extra ghc opts
+ , '' # extra cc opts
+ , ( $TargetPlatform =~ /-solaris2$/ ? '-lnsl -lsocket' : '')
+ ],
+ hbc,
+ [ # where to slurp interface files from
+ ( $INSTALLING
+ ? "$InstLibDirGhc/imports/hbc"
+ : "$TopPwd/CONTRIB/libraries/hbc/src"
+ )
+ , # where to find the archive to use when linking
+ ( $INSTALLING
+ ? "$InstLibDirGhc"
+ : "$TopPwd/CONTRIB/libraries/src/hbc"
+ )
+ , # where to find the cbits archive to use when linking
+ ( $INSTALLING
+ ? "$InstLibDirGhc"
+ : "$TopPwd/CONTRIB/libraries/hbc/cbits"
+ )
+ , 'exts' # Syslib dependencies
+ , '' # extra ghc opts
+ , '' # extra cc opts
+ , ''
+ ],
+ posix,
+ [ # where to slurp interface files from
+ ( $INSTALLING
+ ? "$InstLibDirGhc/imports/posix"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/posix"
+ )
+ , # where to find the archive to use when linking
+ ( $INSTALLING
+ ? "$InstLibDirGhc"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/posix"
+ )
+ , # where to find the cbits archive to use when linking
+ ( $INSTALLING
+ ? "$InstLibDirGhc"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/posix/cbits"
+ )
+ , 'misc' # Syslib dependencies
+ , '' # extra ghc opts
+ , '' # extra cc opts
+ , '' # extra ld opts
+ ],
+ concurrent,
+ [ # where to slurp interface files from
+ ( $INSTALLING
+ ? "$InstLibDirGhc/imports/concurrent"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/concurrent"
+ )
+ , # where to find the archive to use when linking
+ ( $INSTALLING
+ ? "$InstLibDirGhc"
+ : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/concurrent"
+ )
+ , '' # where to find the cbits archive to use when linking
+ , '' # Syslib dependencies
+ , '' # extra ghc opts
+ , '' # extra cc opts
+ , '' # extra ld opts
+ ],
+ win32,
+ [ # where to slurp interface files from
+ ( $INSTALLING
+ ? "$InstLibDirGhc/imports/win32"
+ : "$TopPwd/hslibs/win32/src"
+ )
+ , # where to find the archive to use when linking
+ ( $INSTALLING
+ ? "$InstLibDirGhc"
+ : "$TopPwd/hslibs/win32/src"
+ )
+ , ''
+ , 'exts' # Syslib dependencies
+ , '' # extra ghc opts
+ , '' # extra cc opts
+ , '-luser32 -lgdi32' # extra ld opts
+ ]
+ );
+
+ # check if it's supported..
+
+ if ( !exists $Supported_syslibs{$syslib} ) {
+ print STDERR "$Pgm: no such system library (-syslib): $syslib\n";
+ $Status++;
+ return;
+ }
+
+ # This check is here to avoid syslib loops from
+ # spoiling the party. A side-effect of it is that
+ # it disallows multiple mentions of a syslib on a command-line,
+ # explicit *and* implicit ones (i.e., "-syslib exts -syslib misc"
+ # is not equal to "-syslib exts -syslib misc -syslib exts",
+ # which it needs to be)
+ #
+ # Since our current collection of syslibs don't have any
+ # loops, this test is disabled.
+ #
+ # ToDo: loop avoidance scheme when the need arises
+ #
+ #return if ( exists $Syslibs_added{$syslib} );
+
+ $Syslibs_added{$syslib} = 1;
+
+ local ($hi_dir, $lib_dir, $lib_cbits_dir,
+ $syslib_deps, $syslib_ghc_opts,
+ $syslib_cc_opts, $syslib_ld_opts) = @{ $Supported_syslibs{$syslib} };
+
+
+ unshift(@SysImport_dir, $hi_dir);
+ push(@SysLibrary_dir, $lib_dir);
+ push(@SysLibrary_dir, $lib_cbits_dir) if ( $lib_cbits_dir ne '');
+
+ push(@SysLibrary, "-lHS$syslib");
+ push(@SysLibrary, "-lHS${syslib}_cbits") if ( $lib_cbits_dir ne '');
+ push(@SysLibrary, $syslib_ld_opts) if ($syslib_ld_opts ne '');
+
+ # Add on any extra dependencies.
+ foreach $lib (split(' ',$syslib_deps)) {
+ &add_syslib($lib);
+ }
+}
+\end{code}
+
+Source files may have {-# OPTIONS ... #-} pragmas at the top, containing
+command line options we want to append to collection of commands specified
+directly. @check_for_source_options@ looks at the top of a de-lit'ified Haskell
+file for any such pragmas:
+
+\begin{code}
+sub check_for_source_options {
+ local($file,$ifile) = @_;
+ local($comment_start,$comment_end);
+
+ if ($ifile =~ /\.hc$/ ||
+ $ifile =~ /_hc$/ ||
+ $ifile =~ /\.s$/ ||
+ $ifile =~ /_s$/ ) { # `Real' C intermediate
+ $comment_start = "/\\*";
+ $comment_end = "\\*/";
+ } else { # Assume it is a file containing Haskell source
+ $comment_start = "{-#";
+ $comment_end = "#-}";
+ }
+
+ open(FILE,$file) || return(1); # No big loss
+
+ while (<FILE>) {
+ if ( /^${comment_start} OPTIONS (.*)${comment_end}$/ ) {
+ # add the options found at the back of the command line.
+ local(@entries) = split(/\s+/,$1);
+ print STDERR "Found OPTIONS " . join(' ',@entries) . " in $file\n" if $Verbose;
+ push(@File_options, @entries);
+ }
+ elsif ( /^$/ ) { # ignore empty lines
+ ;
+ }
+ elsif ( /^#line.+$/ ) { # ignore comment lines (unused..ToDo: rm )
+ ;
+ }
+ elsif ( /^{-# LINE.+$/ ) { # ignore line pragmas
+ ;
+ }
+ else { # stop looking, something non-empty / not
+ # ${comment_start} OPTIONS .. ${comment_end} encountered.
+ close(FILE);return(0);
+ }
+ }
+ close(FILE);
+ return(0);
+}
+\end{code}
+
+
+We split the initial argv up into three arrays:
+
+ - @Cmd_opts
+ - @Link_file
+ - @Input_file
+
+the reason for doing so is to be able to deal
+with {-# OPTIONS #-} pragma in source files properly.
+
+\begin{code}
+sub splitCmdLine {
+ local(@args) = @_;
+
+arg: while($_ = $args[0]) {
+ shift(@args);
+ # sigh, we have to deal with these -option arg specially here.
+ /^-(tmpdir|odir|ohi|o|isuf|osuf|hisuf|odump|syslib)$/ &&
+ do { push(@Cmd_opts, $_); push(@Cmd_opts,$args[0]); shift(@args); next arg; };
+ /^--?./ && do { push(@Cmd_opts, $_); next arg; };
+
+ if (/\.([^_]+_)?[oa]$/) {
+ push(@Link_file, $_);
+ } else {
+ push(@Input_file, $_);
+ }
+
+ # input files must exist:
+ if (! -f $_) {
+ print STDERR "$Pgm: input file doesn't exist: $_\n";
+ $Status++;
+ }
+ }
+}
+
+\end{code}
+
+When saving an intermediate file (.hc or .s) away, we
+have to prefix any OPTIONS found in the original source file.
+
+\begin{code}
+sub saveIntermediate {
+ local ($final,$suffix,$tmp)= @_ ;
+ local ($to_do);
+
+ # $final -- root of where to park ${final}.${suffix}
+ # $tmp -- temporary file where hsc put the intermediate file.
+
+ # Delete the old file
+ $to_do = "$Rm ${final}.${suffix}"; &run_something($to_do, "Removing old .${suffix} file");
+
+ if ( $#File_options >= 0 ) { # OPTIONS found in Haskell source unit
+ # Add OPTION comment to the top of the generated .${suffix} file
+ open(TEMP, "> ${final}.${suffix}") || &tidy_up_and_die(1,"Can't open ${final}.${suffix}\n");
+ print TEMP "/* OPTIONS " . join(' ',@File_options) . " */\n";
+ close(TEMP);
+ print STDERR "Prepending OPTIONS: " . join(' ',@File_options) . " to ${final}.${suffix}\n" if $Verbose;
+ }
+ $to_do = "$Cat $tmp >> ${final}.${suffix}";
+ &run_something($to_do, "Saving copy of .${suffix} file");
+
+}
+
+\end{code}
+
+
+Command-line processor
+
+\begin{code}
+sub processArgs {
+ local(@Args) = @_;
+
+# can't use getopt(s); what we want is too complicated
+
+arg: while($_ = $Args[0]) {
+ shift(@Args);
+
+ #---------- help -------------------------------------------------------
+ if (/^-\?$/ || /^--?help$/) { print $LongUsage; exit $Status; }
+
+ #-----------version ----------------------------------------------------
+ /^--version$/ && do { print STDERR "${ProjectName}, version ${ProjectVersion}, patchlevel ${ProjectPatchLevel}\n"; exit $Status; };
+
+ #---------- verbosity and such -----------------------------------------
+ /^-v$/ && do { $Verbose = '-v'; $Time = 'time'; next arg; };
+
+ #---------- what phases are to be run ----------------------------------
+ /^-(no-)?recomp/ && do { $Do_recomp_chkr = ($1 eq '') ? 1 : 0; next arg; };
+
+ /^-cpp$/ && do { $Cpp_flag_set = 1; next arg; };
+ # change the global default:
+ # we won't run cat; we'll run the real thing
+
+ /^-C$/ && do { $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0; $HscOut = '-C=';
+ next arg; };
+ # stop after generating C
+
+ /^-noC$/ && do { $HscOut = '-N='; $ProduceHi = '-nohifile=';
+ $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0;
+ next arg; };
+ # leave out actual C generation (debugging) [also turns off interface gen]
+
+
+ /^-hi$/ && do { $HiOnStdout = 1; $ProduceHi = '-hifile='; next arg; };
+ # _do_ generate an interface; usually used as: -noC -hi
+ /^-hi-with-(.*)$/ && do { $HiOnStdout = 1; $HiWith .= " $1" ; $ProduceHi = '-hifile='; next arg; };
+ # limit ourselves to outputting a particular section.
+
+ /^-nohi$/ && do { $ProduceHi = '-nohifile='; next arg; };
+ # don't generate an interface (even if generating C)
+
+ /^-hi-diffs$/ && do { $HiDiff_flag = 'normal'; next arg; };
+ /^-hi-diffs-with-usages$/ && do { $HiDiff_flag = 'usages'; next arg; };
+ /^-no-hi-diffs$/ && do { $HiDiff_flag = ''; next arg; };
+ /^-keep-hi-diffs$/ && do { $Keep_HiDiffs = 1; next arg; };
+
+ # show/disable diffs if the interface file changes
+
+ /^-E$/ && do { push(@CcBoth_flags, '-E');
+ $Only_preprocess_C = 1;
+ $Do_as = 0; $Do_lnkr = 0; next arg; };
+ # stop after preprocessing C
+ /^-M$/ && do { $Only_generate_deps = 1; $Do_as = 0; $Do_lnkr = 0; next arg; };
+ # only generate dependency information.
+ /^-S$/ && do { $Do_as = 0; $Do_lnkr = 0; next arg; };
+ # stop after generating assembler
+
+ /^-c$/ && do { $Do_lnkr = 0; next arg; };
+ # stop after generating .o files
+
+ /^-link-chk$/ && do { $LinkChk = 1; next arg; };
+ /^-no-link-chk$/ && do { $LinkChk = 0; next arg; };
+ # don't do consistency-checking after a link
+
+ /^-tmpdir$/ && do { $Tmp_prefix = &grab_arg_arg(*Args,'-tmpdir', '');
+ $Tmp_prefix = "$Tmp_prefix/ghc$$";
+ $ENV{'TMPDIR'} = $Tmp_prefix; # for those who use it...
+ next arg; };
+ # use an alternate directory for temp files
+
+ #---------- redirect output --------------------------------------------
+
+ # -o <file>; applies to the last phase, whatever it is
+ # "-o -" sends it to stdout
+ # if <file> has a directory component, that dir must already exist
+
+ /^-odir$/ && do { $Specific_output_dir = &grab_arg_arg(*Args,'-odir', '');
+ #
+ # Hack, of the worst sort: don't do validation of
+ # odir argument if you're using -M (dependency generation).
+ #
+ if ( ! $Only_generate_deps && ! -d $Specific_output_dir) {
+ print STDERR "$Pgm: -odir: no such directory: $Specific_output_dir\n";
+ $Status++;
+ }
+ next arg; };
+
+ /^-o$/ && do { $Specific_output_file = &grab_arg_arg(*Args,'-o', '');
+ if ($Specific_output_file ne '-'
+ && $Specific_output_file =~ /(.*)\/[^\/]*$/) {
+ local($dir_part) = $1;
+ if (! -d $dir_part) {
+ print STDERR "$Pgm: no such directory: $dir_part\n";
+ $Status++;
+ }
+ }
+ next arg; };
+
+ # NB: -isuf not documented yet (because it doesn't work yet)
+ /^-isuf$/ && do { $Isuffix = &grab_arg_arg(*Args,'-isuf', '');
+ if ($Isuffix =~ /\./ ) {
+ print STDERR "$Pgm: -isuf suffix shouldn't contain a .\n";
+ $Status++;
+ }
+ next arg; };
+
+ /^-osuf$/ && do { $Osuffix = &grab_arg_arg(*Args,'-osuf', '');
+ if ($Osuffix =~ /\./ ) {
+ print STDERR "$Pgm: -osuf suffix shouldn't contain a .\n";
+ $Status++;
+ }
+ next arg; };
+
+ # -ohi <file>; send the interface to <file>; "-ohi -" to send to stdout
+ /^-ohi$/ && do { $Specific_hi_file = &grab_arg_arg(*Args,'-ohi', '');
+ if ($Specific_hi_file ne '-'
+ && $Specific_hi_file =~ /(.*)\/[^\/]*$/) {
+ local($dir_part) = $1;
+ if (! -d $dir_part) {
+ print STDERR "$Pgm: no such directory: $dir_part\n";
+ $Status++;
+ }
+ }
+ next arg; };
+
+ # The suffix to use when looking for interface files
+ /^-hisuf$/ && do { $HiSuffix = &grab_arg_arg(*Args,'-hisuf', '');
+ if ($HiSuffix =~ /\./ ) {
+ print STDERR "$Pgm: -hisuf suffix shouldn't contain a .\n";
+ $Status++;
+ }
+ next arg; };
+ /^-odump$/ && do { $Specific_dump_file = &grab_arg_arg(*Args,'-odump', '');
+ if ($Specific_dump_file =~ /(.*)\/[^\/]*$/) {
+ local($dir_part) = $1;
+ if (! -d $dir_part) {
+ print STDERR "$Pgm: no such directory: $dir_part\n";
+ $Status++;
+ }
+ }
+ next arg; };
+
+ #-------------- scc & Profiling Stuff ----------------------------------
+
+ /^-prof$/ && do { $PROFing = 'p'; next arg; }; # profiling -- details later!
+
+ /^-auto/ && do {
+ # generate auto SCCs on top level bindings
+ # -auto-all = all top level bindings
+ # -auto = only top level exported bindings
+ $PROFauto = ( /-all/ )
+ ? '-fauto-sccs-on-all-toplevs'
+ : '-fauto-sccs-on-exported-toplevs';
+ next arg; };
+
+ /^-caf-all/ && do { # generate individual CAF SCC annotations
+ $PROFcaf = '-fauto-sccs-on-individual-cafs';
+ next arg; };
+
+ /^-ignore-scc$/ && do {
+ # forces ignore of scc annotations even if profiling
+ $PROFignore_scc = '-W';
+ next arg; };
+
+ /^-G(.*)$/ && do { push(@HsC_flags, "-G=$1"); # set group for cost centres
+ next arg; };
+
+ /^-unprof-scc-auto/ && do {
+ # generate auto SCCs on top level bindings when not profiling.
+ # Used to measure optimisation effects of presence of sccs.
+ $UNPROFscc_auto = ( /-all/ )
+ ? '-fauto-sccs-on-all-toplevs'
+ : '-fauto-sccs-on-exported-toplevs';
+ next arg; };
+
+ #--------- ticky/parallel ----------------------------------------------
+ # we sort out the details a bit later on
+
+ /^-gransim$/ && do { $GRANing = 'g'; &add_syslib('concurrent'); next arg; }; # GranSim
+ /^-ticky$/ && do { $TICKYing = 't'; next arg; }; # ticky-ticky
+ /^-parallel$/ && do { $PARing = 'p'; &add_syslib('concurrent'); next arg; }; # parallel Haskell
+
+ #-------------- "user ways" --------------------------------------------
+
+ (/^-user-setup-([a-oA-Z])$/ ) &&
+ do {
+ /^-user-setup-([a-oA-Z])$/ && do { $BuildTag = "_$1"; };
+
+ local($stuff) = $UserSetupOpts{$BuildTag};
+ local(@opts) = split(/\s+/, $stuff);
+
+ # feed relevant ops into the arg-processing loop (if any)
+ unshift(@Args, @opts) if $#opts >= 0;
+
+ next arg; };
+
+ #---------- set search paths for libraries and things ------------------
+
+ # we do -i just like HBC (-i clears the list; -i<colon-separated-items>
+ # prepends the items to the list); -I is for including C .h files.
+
+ /^-i$/ && do { @Import_dir = (); # import path cleared!
+ @SysImport_dir = ();
+ print STDERR "WARNING: import paths cleared by `-i'\n";
+ next arg; };
+
+ /^-i(.*)/ && do { local(@new_items)
+ = split( /:/, &grab_arg_arg(*Args,'-i', $1));
+ unshift(@Import_dir, @new_items);
+ next arg; };
+
+ /^-I(.*)/ && do { push(@Include_dir, &grab_arg_arg(*Args,'-I', $1)); next arg; };
+ /^-L(.*)/ && do { push(@UserLibrary_dir, &grab_arg_arg(*Args,'-L', $1)); next arg; };
+ /^-l(.*)/ && do { push(@UserLibrary,'-l'.&grab_arg_arg(*Args,'-l', $1)); next arg; };
+
+ /^-syslib(.*)/ && do { local($syslib) = &grab_arg_arg(*Args,'-syslib',$1);
+ &add_syslib($syslib);
+ next arg; };
+
+ #=======================================================================
+ # various flags that we can harmlessly send to one program or another
+ # (we will later "reclaim" some of the compiler ones now sent to gcc)
+ #=======================================================================
+
+ #---------- this driver itself (ghc) -----------------------------------
+ # these change what executable is run for each phase:
+ /^-pgmL(.*)$/ && do { $Unlit = $1; next arg; };
+ /^-pgmP(.*)$/ && do { $HsCpp = $1; next arg; };
+ /^-pgmC(.*)$/ && do { $HsC = $1; next arg; };
+ /^-pgmcO?(.*)$/ && do { $CcRegd = $1; next arg; }; # the O? for back compat
+ /^-pgma(.*)$/ && do { $As = $1; next arg; };
+ /^-pgml(.*)$/ && do { $Lnkr = $1; next arg; };
+ /^-pgmdep(.*)$/ && do { $MkDependHS = $1; next arg; };
+
+ #---------- the get-anything-through opts (all pgms) -------------------
+ # these allow arbitrary option-strings to go to any phase:
+ /^-optL(.*)$/ && do { push(@Unlit_flags, $1); next arg; };
+ /^-optP(.*)$/ && do { push(@HsCpp_flags, $1); next arg; };
+ /^-optCrts(.*)$/&& do { push(@HsC_rts_flags, $1); next arg; };
+ /^-optC(.*)$/ && do { push(@HsC_flags, $1); next arg; };
+ /^-optp(.*)$/ && do { push(@HsP_flags, $1); next arg; };
+ /^-optcpp(.*)$/ && do { push(@Cpp_define, $1); $Only_preprocess_hc = ($1 eq "-E"); next arg; };
+ /^-optc(.*)$/ && do { push(@CcBoth_flags, $1); next arg; };
+ /^-opta(.*)$/ && do { push(@As_flags, $1); next arg; };
+ /^-optl(.*)$/ && do { push(@Ld_flags, $1); next arg; };
+ /^-optdep(.*)$/ && do { push(@MkDependHS_flags, $1); next arg; };
+
+ #---------- Haskell C pre-processor (hscpp) ----------------------------
+ /^-D(.*)/ && do { push(@HsCpp_flags, "'-D".&grab_arg_arg(*Args,'-D',$1)."'"); next arg; };
+ /^-U(.*)/ && do { push(@HsCpp_flags, "'-U".&grab_arg_arg(*Args,'-U',$1)."'"); next arg; };
+
+ #---------- post-Haskell "assembler"------------------------------------
+ /^-ddump-raw-asm$/ && do { $Dump_raw_asm = 1; next arg; };
+ /^-ddump-asm-splitting-info$/ && do { $Dump_asm_splitting_info = 1; next arg; };
+
+ #---------- Haskell compiler (hsc) -------------------------------------
+
+ /^-keep-hc-files?-too$/ && do { $Keep_hc_file_too = 1; next arg; };
+ /^-keep-s-files?-too$/ && do { $Keep_s_file_too = 1; next arg; };
+
+ /^-fignore-interface-pragmas$/ && do { push(@HsC_flags, $_); next arg; };
+
+ /^-fno-implicit-prelude$/ && do { $NoImplicitPrelude= 1; push(@HsC_flags, $_); next arg; };
+
+ #
+ # have the compiler proper generate concurrent code,
+ # really only used when you want to configure your own
+ # special user compilation way.
+ #
+ # (ditto for -fgransim, fscc-profiling, -fparallel and -fticky-ticky)
+ #
+ /^-fscc-profiling$/ && do { push(@HsC_flags,$_); next arg; };
+ /^-fticky-ticky$/ && do { push(@HsC_flags,$_); next arg; };
+ /^-fgransim$/ && do { push(@HsC_flags,$_); next arg; };
+ /^-fparallel$/ && do { push(@HsC_flags,$_); next arg; };
+
+ /^-split-objs$/ && do {
+ if ( $TargetPlatform !~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|rs6000|sparc)-/ ) {
+ $SplitObjFiles = 0;
+ print STDERR "WARNING: don't know how to split objects on this platform: $TargetPlatform\n`-split-objs' option ignored\n";
+ } else {
+ $SplitObjFiles = 1;
+ $HscOut = '-C=';
+
+ push(@HsC_flags, "-fglobalise-toplev-names");
+ push(@CcBoth_flags, '-DUSE_SPLIT_MARKERS');
+
+ require('ghc-split.prl')
+ || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-split.prl!\n");
+ }
+ next arg; };
+
+ /^-fno-asm-mangling$/ && do { $DoAsmMangling = 0; next arg; };
+
+ /^-fallow-overlapping-instances$/ && do { push(@HsC_flags, $_); next arg; };
+ /^-fallow-undecidable-instances$/ && do { push(@HsC_flags, $_); next arg; };
+ /^-fglasgow-exts$/
+ && do { push(@HsC_flags, $_);
+ push(@HsP_flags, '-N');
+
+ # -fglasgow-exts implies -syslib exts
+ &add_syslib('exts');
+
+ next arg; };
+
+ /^-fspeciali[sz]e$/
+ && do { $Oopt_DoSpecialise = '-fspecialise'; next arg; };
+ /^-fno-speciali[sz]e$/
+ && do { $Oopt_DoSpecialise = ''; next arg; };
+
+
+# Now the foldr/build options, which are *on* by default (for -O).
+
+ /^-ffoldr-build$/
+ && do { $Oopt_FoldrBuild = 1;
+ $Oopt_FB_Support = '-fdo-arity-expand';
+ #print "Yes F/B\n";
+ next arg; };
+
+ /^-fno-foldr-build$/
+ && do { $Oopt_FoldrBuild = 0;
+ $Oopt_FB_Support = '';
+ next arg; };
+
+ /^-fno-foldr-build-rule$/
+ && do { $Oopt_FoldrBuild = 0;
+ next arg; };
+
+ /^-fno-enable-tech$/
+ && do { $Oopt_FB_Support = '';
+ next arg; };
+
+ /^-fno-snapback-to-append$/
+ && do { $Oopt_FoldrBuildInline .= ' -fdo-not-fold-back-append ';
+ next arg; };
+
+ # --------------- Renamer -------------
+
+
+ /^-fno-prune-tydecls$/ && do { push(@HsC_flags, $_); next arg; };
+ /^-fno-prune-instdecls$/ && do { push(@HsC_flags, $_); next arg; };
+
+ # ---------------
+
+ /^-fasm-(.*)$/ && do { $HscOut = '-S='; next arg; }; # force using nativeGen
+ /^-fvia-[cC]$/ && do { $HscOut = '-C='; next arg; }; # force using C compiler
+
+ # ---------------
+
+ /^-funfolding-.*$/
+ && do { push(@HsC_flags, $_); next arg };
+
+ /^-funfold-casms-in-hi-file$/
+ && do { push(@HsC_flags, $_); next arg };
+
+ /^(-fmax-simplifier-iterations)(.*)$/
+ && do { $Oopt_MaxSimplifierIterations = $1 . &grab_arg_arg(*Args,$1, $2);
+ next arg; };
+
+ /^-fno-pedantic-bottoms$/
+ && do { $Oopt_PedanticBottoms = ''; next arg; };
+
+ /^-fno-pre-inlining$/
+ && do { push(@HsC_flags, $_); next arg };
+
+ /^-fdo-monad-eta-expansion$/
+ && do { $Oopt_MonadEtaExpansion = $_; next arg; };
+
+ /^-fno-let-from-(case|app|strict-let)$/ # experimental, really (WDP 95/10)
+ && do { push(@HsC_flags, $_); next arg; };
+
+ # --------------- Warnings etc. ------
+
+ /^-fwarn-(.*)$/ && do { push(@HsC_flags, $_); next arg; };
+
+ /^-fno-(.*)$/ && do { push(@HsC_antiflags, "-f$1");
+ &squashHscFlag("-f$1");
+ next arg; };
+
+ /^-W$/ && do { push(@HsC_flags, @MinusWOpts); next arg; };
+ /^-Wall$/ && do { push(@HsC_flags, @MinusWallOpts); next arg; };
+ /^(-Wnot|w)$/ && do { foreach (@Hsc_flags) {
+ /^-fwarn-(.*)$/ && do { $_=''; };
+ };
+ push(@HsC_antiflags, @StandardWarnings);
+ next arg; };
+
+ # --------------- fun stuff ----------------
+
+ /^-freport-compile$/ && do { push(@HsC_flags, $_); next arg; };
+
+ # --------------- platform specific flags (for gcc mostly) ----------------
+
+ /^-mlong-calls$/ && do { # for GCC for HP-PA boxes,
+ # for 2.6.x..?, does not apply for 2.7.2
+ # any longer.
+ unshift(@CcBoth_flags, ( $_ ));
+ next arg; };
+
+ /^-m(v8|sparclite|cypress|supersparc|cpu=(cypress|supersparc))$/
+ && do { # for GCC for SPARCs
+ unshift(@CcBoth_flags, ( $_ ));
+ next arg; };
+
+ /^-monly-([432])-regs/ && do { # for iX86 boxes only; no effect otherwise
+ $StolenX86Regs = $1;
+ next arg; };
+
+ #*************** ... and lots of debugging ones (form: -d* )
+
+ # -d(no-)core-lint is done this way so it is turn-off-able.
+ /^-dcore-lint/ && do { $CoreLint = '-dcore-lint'; next arg; };
+ /^-dno-core-lint/ && do { $CoreLint = ''; next arg; };
+ # Ditto for STG lint
+ /^-dstg-lint/ && do { $StgLint = '-dstg-lint'; next arg; };
+ /^-dno-stg-lint/ && do { $StgLint = ''; next arg; };
+
+ /^-d(dump|ppr)-/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dverbose-(simpl|stg)/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dshow-passes/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dshow-rn-stats/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dshow-rn-trace/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dsource-stats/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dsimplifier-stats/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dstg-stats/ && do { $Oopt_StgStats = $_; next arg; };
+
+ #*************** ... and now all these -R* ones for its runtime system...
+
+ /^-Rscale-sizes?(.*)/ && do {
+ $Scale_sizes_by = &grab_arg_arg(*Args,'-Rscale-sizes', $1);
+ next arg; };
+
+ /^(-H|-Rmax-heapsize)(.*)/ && do {
+ local($heap_size) = &grab_arg_arg(*Args,$1, $2);
+ if ($heap_size =~ /(\d+)[Kk]$/) {
+ $heap_size = $1 * 1000;
+ } elsif ($heap_size =~ /(\d+)[Mm]$/) {
+ $heap_size = $1 * 1000 * 1000;
+ } elsif ($heap_size =~ /(\d+)[Gg]$/) {
+ $heap_size = $1 * 1000 * 1000 * 1000;
+ }
+ if ($heap_size <= 0) {
+ print STDERR "$Pgm: resetting heap-size to zero!!! $heap_size\n";
+ $Specific_heap_size = 0;
+
+ # if several heap sizes given, take the largest...
+ } elsif ($heap_size >= $Specific_heap_size) {
+ $Specific_heap_size = $heap_size;
+ } else {
+ print STDERR "$Pgm: ignoring heap-size-setting option ($_)...not the largest seen\n";
+ }
+ next arg; };
+
+ /^(-K|Rmax-(stk|stack)size)(.*)/ && do {
+ local($flag) = $1;
+ local($stk_size) = &grab_arg_arg(*Args,'-Rmax-stksize', $3);
+ if ($stk_size =~ /(\d+)[Kk]$/) {
+ $stk_size = $1 * 1000;
+ } elsif ($stk_size =~ /(\d+)[Mm]$/) {
+ $stk_size = $1 * 1000 * 1000;
+ } elsif ($stk_size =~ /(\d+)[Gg]$/) {
+ $stk_size = $1 * 1000 * 1000 * 1000;
+ }
+ if ($stk_size <= 0) {
+ print STDERR "$Pgm: resetting stack-size to zero!!! $stk_size\n";
+ $Specific_stk_size = 0;
+
+ # if several stack sizes given, take the largest...
+ } elsif ($stk_size >= $Specific_stk_size) {
+ $Specific_stk_size = $stk_size;
+ } else {
+ print STDERR "$Pgm: ignoring stack-size-setting option ($flag $stk_size)...not the largest seen\n";
+ }
+ next arg; };
+
+ /^-Rgc-stats$/ && do { $CollectingGCstats++;
+ # the two RTSs do this diff ways; we will try to compensate
+ next arg; };
+
+ /^-Rghc-timing/ && do { $CollectGhcTimings = 1; next arg; };
+
+ #---------- C high-level assembler (gcc) -------------------------------
+ /^-(Wall|ansi|pedantic)$/ && do { push(@CcBoth_flags, $_); next arg; };
+
+ # -dgcc-lint is a useful way of making GCC very fussy.
+ # From alan@spri.levels.unisa.edu.au (Alan Modra).
+ /^-dgcc-lint$/ && do { push(@CcBoth_flags, '-Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs'); next arg; };
+ # An alternate set, from mark@sgcs.com (Mark W. Snitily)
+ # -Wall -Wstrict-prototypes -Wmissing-prototypes -Wcast-align -Wshadow
+
+ # inject "#include <wurble>" into the compiler's C output!
+
+ /^-#include(.*)/ && do {
+ local($to_include) = &grab_arg_arg(*Args,'-#include', $1);
+ push(@CcInjects, "#include $to_include\n");
+ next arg; };
+
+ #---------- Linker (gcc, really) ---------------------------------------
+
+ /^-static$/ && do { push(@Ld_flags, $_); next arg; };
+ /^-no-hs-main$/ && do { $NoHaskellMain=1; next arg; };
+
+ #---------- mixed cc and linker magic ----------------------------------
+ # this optimisation stuff is finally sorted out later on...
+
+ /^-O2-for-C$/ && do { $MinusO2ForC = 1; next arg; };
+
+ /^-O[1-2]?$/ && do {
+ local($opt_lev) = ( /^-O2$/ ) ? 2 : 1; # max 'em
+ $OptLevel = ( $opt_lev > $OptLevel ) ? $opt_lev : $OptLevel;
+
+ $HscOut = '-C=' if $OptLevel == 2; # force use of C compiler
+ next arg; };
+
+ /^-Onot$/ && do { $OptLevel = 0; next arg; }; # # set it to <no opt>
+
+ /^-Ofile(.*)/ && do {
+ $OptLevel = 3;
+ local($ofile) = &grab_arg_arg(*Args,'-Ofile', $1);
+ @HsC_minusO3_flags = ();
+
+ open(OFILE, "< $ofile") || die "Can't open $ofile!\n";
+ while (<OFILE>) {
+ chop;
+ s/\#.*//; # death to comments
+ s/[ \t]+//g; # death to whitespace
+ next if /^$/; # ditto, blank lines
+ s/([()*{}])/\\$1/g; # protect shell metacharacters
+ if ( /^C:(.*)/ ) {
+ push(@CcBoth_flags, $1);
+ } else {
+ push(@HsC_minusO3_flags, $_);
+ }
+ }
+ close(OFILE);
+ next arg; };
+
+ /^-debug$/ && do { # all this does is mark a .hc/.o as "debugging"
+ # in the consistency info
+ $DEBUGging = 'd';
+ next arg; };
+
+ #---------- linking .a file --------------------------------------------
+
+ /^-Main(.*)/ && do {
+ # specifies main or mainPrimIO to be linked
+ $Ld_main = $1;
+ next arg; };
+
+ #---------- catch unrecognized flags -----------------------------------
+
+ /^-./ && do {
+ print STDERR "$Pgm: unrecognised option: $_\n";
+ $Status++;
+ next arg; };
+
+}
+
+} # end of processArgs
+
+\end{code}