#!/usr/bin/perl
use strict;
use warnings;
use Config;
use File::Spec;
use lib 'lib';
use inc::Module::Install;

my $pugs = "pugs$Config{_exe}";
my $version_h = "src/Pugs/pugs_version.h";
my $config_h = "src/Pugs/pugs_config.h";
my @srcdirs  = grep {-d} glob("src"), glob("src/*"), glob("src/*/*"), glob("src/*/*/*");
my @hsfiles  = map {glob "$_/*.hs"} @srcdirs;
push @hsfiles, "src/Pugs/Config.hs";
my @hppfiles = map {my $x=$_; $x=~s/\.hs$/.hpp/; $x} @hsfiles;

warn_cygwin     ();

name            ('Perl6-Pugs');
version_from    ('lib/Perl6/Pugs.pm');
abstract_from   ('lib/Perl6/Pugs.pm');
author          ('Autrijus Tang <autrijus@autrijus.org>');
license         ('perl');
install_script  ($pugs);
install_script  (glob('script/*'));
recommends      ('Perl6::Bible');
build_requires  ('ExtUtils::MakeMaker' => 6.15);
include         ('Module::Install::Makefile::Name');
include         ('Module::Install::Makefile::Version');
build_subdirs   (map fixpaths($_), grep {
                   -f "$_/Makefile.PL" && not -l "$_/Makefile.PL"
                 } glob("ext/*")
                );

my $version = version();
$version =~ s{6\.(\d{3})(\d{3})?}{join '.', 6, int($1), int($2||0)}e;
version($version);

makemaker_args  (
    test => { TESTS => join ' ', "t/*/*.t", "t/*/*/*.t" },
    MAN1PODS => {},
);
clean_files     (map fixpaths($_),
    "pugs*", "src/Pugs/pugs_config.h", $version_h, $config_h,
    'src/Pugs/Config.hs', 'blib6',
    'test.log',
    map {("$_/*.hpp", "$_/*.hi", "$_/*.o*")} @srcdirs
);

set_postamble   ();
no_index        (directory => 'inc', 'examples');
sign            (1);
WritePugs       (5);

################################################################################
sub set_postamble {
    my @srcfiles = grep !/MainCC/, map glob("$_/*.*hs"), @srcdirs;
    push @srcfiles, grep !/MainCC/, map glob("$_/*.*hs-boot"), @srcdirs;

    my ($ghc, $ghc_version, $ghc_flags) = assert_ghc();
    # $ghc_flags .= ' -dcore-lint';
    $ghc_flags .= " -keep-tmp-files";
	if (!has_ghc_package('plugins')) {
	  warn << '.';
*** Inline Haskell support disabled.  If you want dynamic loading
    of haskell modules, please install the hs-plugins library,
	ftp://ftp.cse.unsw.edu.au/pub/users/dons/hs-plugins/snapshots/ ,
    dated 2005-04-10 or later -- remember to "make register" too!
.
	} else {
	  $ghc_flags .= ' -DPUGS_HAVE_HSPLUGINS=1';
	}

    if (has_ghc_package('readline') 
        and  try_compile("import System.Console.Readline;\n"
						."main :: IO ()\n"
                        .'main = readline "" >> return ()')) 
    {
      $ghc_flags .= ' -DPUGS_HAVE_READLINE=1 -package readline';
    } else {
      warn << '.';

*** Readline support disabled.  If you want readline support,
    please install the GNU readline library.

.
    }
        

    my $ghc_output = "-o pugs$Config{_exe} src/Main.hs";
    my $hasktags = $ENV{HASKTAGS} || 'hasktags';

    my $pcre = "src/pcre/pcre.o";
    my $pcre_c = "src/pcre/pcre.c";
    my $unicode = "src/UnicodeC.o";
    my $unicode_c = "src/UnicodeC.c";

    my @prereqs = ($config_h, $pcre, $unicode);
    $ghc_output .= " $pcre $unicode";

    my $config = get_pugs_config();
    my $is_win32 = ($^O =~ /MSWin|mingw|cygwin/i);
    my $threaded = (!$is_win32 and try_compile("main :: IO ()\nmain = return ()", "-threaded"))
        ? '-threaded' : '';

    # XXX - hsplugins doesn't build with profiles
    my $profiled_flags = $ghc_flags;
    $profiled_flags =~ s{-DPUGS_HAVE_HSPLUGINS=1}{};

    postamble(fixpaths(<< "."));
$config_h : lib/Perl6/Pugs.pm util/config_h.pl
	\$(PERL) util/config_h.pl "$ghc $ghc_flags"

$version_h : .svn/entries util/version_h.pl
	\$(PERL) util/version_h.pl $version_h

.svn/entries :
	\$(NOOP)

$pcre : $pcre_c
	$ghc $threaded -no-link -no-hs-main -O -o $pcre $pcre_c

$unicode : $unicode_c
	$ghc $threaded -no-link -no-hs-main -O -o $unicode $unicode_c

src/Pugs/Config.hs : util/PugsConfig.pm
	\$(PERL) -Iutil -MPugsConfig -e "PugsConfig->write_config_module" > src/Pugs/Config.hs

${() = '%.hpp : %.hs @prereqs $version_h
	$ghc $threaded $ghc_flags -DHADDOCK -E \$< -o \$@
	\$(PERL) util/munge_haddock.pl \$@'; \''}

.SUFFIXES: .hs .hpp

.hs.hpp :
	$ghc $threaded $ghc_flags -DHADDOCK -E \$< -o \$@
	\$(PERL) util/munge_haddock.pl \$@

haddock : $version_h $config_h @hppfiles docs/haddock
	haddock -h -o docs/haddock/ @hppfiles
	\@\$(PERL) -le "print q-*** API Documentation generated in @{[File::Spec->catdir('docs', 'haddock').File::Spec->catdir('')]}.-"

docs/haddock :
	\@\$(PERL) -e "mkdir q-docs/haddock-"

profiled :: src/Pugs/Config.hs @srcfiles $version_h @prereqs
	$ghc $threaded -O -auto-all -prof --make $profiled_flags $ghc_output

pugs.prof :: profiled
	find t -type f | grep -v D | grep -v R | grep -v pugsrun | ./pugs +RTS -p -RTS -e 'my sub exit {}; for =\$\$*IN -> \$\$t is copy { chomp \$\$t; require \$\$t }'

optimised :: optimized

optimized :: src/Pugs/Config.hs @srcfiles $version_h @prereqs
	$ghc $threaded -O --make $ghc_flags $ghc_output

unoptimised :: optimized

unoptimized :: src/Pugs/Config.hs @srcfiles $version_h @prereqs
	$ghc $threaded -O0 --make $ghc_flags $ghc_output

$pugs : src/Pugs/Config.hs @srcfiles $version_h @prereqs
	$ghc $threaded -O --make $ghc_flags $ghc_output

smoke : $pugs util/run-smoke.pl
	\$(PERL) util/run-smoke.pl . smoke.html

ghci ::
	$ghc --interactive $ghc_flags $ghc_output

tags : @srcfiles
	$hasktags -c @srcfiles
	sort tags > tags.tmp
	mv tags.tmp tags

INST6_ARCHLIB = blib6/arch
INST6_SCRIPT = blib6/script
INST6_BIN = blib6/bin
INST6_LIB = blib6/lib
INST6_MAN1DIR = blib6/man1
INST6_MAN3DIR = blib6/man3

pure_all ::
	\$(PERLRUN) util/src_to_blib.pl

pure_site_install ::
	\$(NOECHO) \$(MOD_INSTALL) \\
		\$(INST6_LIB) \$(DESTDIR)$config->{privlib} \\
		\$(INST6_ARCHLIB) \$(DESTDIR)$config->{archlib} \\
		\$(INST6_BIN) \$(DESTDIR)$config->{installbin} \\
		\$(INST6_SCRIPT) \$(DESTDIR)$config->{installscript} \\
		\$(INST6_MAN1DIR) \$(DESTINSTALLMAN1DIR) \\
		\$(INST6_MAN3DIR) \$(DESTINSTALLMAN3DIR)
.
}

sub try_compile {
    my $code = shift;
    my $temp = File::Spec->catfile(File::Spec->tmpdir, "pugs-tmp-$$");

    eval {
        open TMP, "> $temp.hs";
        print TMP $code;
        close TMP;
        system(
            ($ENV{GHC} || 'ghc'), @_,
            "--make", "-v0",
            -o => "$temp.exe",
            "$temp.hs"
        );

    };

    my $ok = -e "$temp.exe";
    unlink("$temp.exe");
    unlink("$temp.hs");
    unlink("$temp.hi");
    unlink("$temp.o");
    return $ok;
}
