#!/usr/bin/perl -w

eval 'exec perl -S $0 ${1+"$@"}'
    if 0;

# This script will create the Makefile to build and install CLC-INTERCAL

# This file is part of CLC-INTERCAL

# Copyright (c) 2008, 2023-2024 Claudio Calvelli, all rights reserved.

# CLC-INTERCAL is copyrighted software. However, permission to use, modify,
# and distribute it is granted provided that the conditions set out in the
# licence agreement are met. See files README and COPYING in the distribution.

use vars qw($VERSION $PERVERSION);
($VERSION) = ($PERVERSION = "CLC-INTERCAL Makefile.PL 1.00") =~ /\s(\S+)$/;

use strict;
use File::Spec::Functions qw(curdir catfile);
use ExtUtils::MakeMaker;

$| = 1;

# find out what packages are included in this
my $base = undef;
my $docs = undef;
my @extras = ();
open(MANIFEST, '-|', $^X, catfile(curdir(), 'build', 'check-manifest'), '-lv')
    or die "check-manifest: $!\n";
print "Checking if your kit is complete...\n";
while (<MANIFEST>) {
    chomp;
    s|/Makefile.PL$|| or next;
    if (/-Base$/) {
	$base = $_;
    } elsif (/-Docs$/) {
	$docs = $_;
    } else {
	push @extras, $_;
    }
}
close MANIFEST or do {
    $? == -1 and die "check-manifest: $!\n";
    $? & 0x7f and die "check-manifest terminated with signal " . ($? & 0x7f) . "\n";
    die "check-manifest exited with statue " . ($? >> 8) . "\n";
};
defined $base or die "Something is wrong... Base package was not included\n";
defined $docs and push @extras, $docs; # Docs must be built last
print "Looks good\n";

# Check for --avoid-xs and remove it from @ARGV - in case it confuses some
# later version of ExtUtils::MakeMaker; note that we ask for it to be
# typed exactly, apart from the letter case
my %avoid_xs;
{
    my @av = grep { /^--avoid-xs(?:=|$)/ } @ARGV;
    if (@av) {
	@ARGV = grep { ! /^--avoid-xs(?:=|$)/ } @ARGV;
	for my $av (@av) {
	    if ($av =~ s/^--avoid-xs=//) {
		$avoid_xs{lc $_} = $_ for split(/,/, $av);
	    } else {
		$avoid_xs{''} = '';
	    }
	}
    }
}

# prevent the "Checking if your kit is complete" by their Makefile.PL
# since we've already done that here
open(MF, '>>', 'Makefile') and close MF;

# pretend to write a Makefile. so that we get all the constants
my $constants = '';
my $remake = '';
ExtUtils::MakeMaker::WriteEmptyMakefile(
    NORECURS => 1,
    NAME => 'Language::INTERCAL',
    VERSION => $VERSION,
);

# remove empty Makefile.old
-f "Makefile.old" && ! -s _ and unlink('Makefile.old');

# run Makefile.PL for base package
my $run_submakefile = catfile(curdir(), qw(build run_makefile_pl));
run_makefile_pl($base);

# run Makefile.PL for other packages
unshift @ARGV, "--in-bundle=$base";
for my $extra (@extras) {
    run_makefile_pl($extra);
}

# create a simple Makefile
my @targets = qw(all clean realclean install);
my %afterpath = (
    clean => [
	'$(RM_F) Makefile.old',
	'$(MV) Makefile Makefile.old',
    ],
    realclean => [
	'$(RM_F) Makefile Makefile.old',
	"\$(RM_RF) dist/CLC-INTERCAL-$VERSION",
    ],
);

open(MAKEFILE, '>', 'Makefile') or die "Makefile: $!\n";
print MAKEFILE "# Tool paths from MakeMaker...\n\n" or die "Makefile: $!\n";
print MAKEFILE $constants or die "Makefile: $!\n";
print MAKEFILE "\n\n# Generated by CLC-INTERCAL...\n\n" or die "Makefile: $!\n";
print MAKEFILE "DISTRIBUTION = dist/CLC-INTERCAL-$VERSION\n\n" or die "Makefile: $!\n";
print MAKEFILE ".PHONY: @targets test dist check-manifest check-manifest-git\n\n" or die "Makefile: $!\n";
for my $target (@targets) {
    print MAKEFILE "$target :\n" or die "Makefile: $!\n";
    for my $path ($base, @extras) {
	print MAKEFILE "\t\$(MAKE) -C $path $target\n" or die "Makefile: $!\n";
    }
    if (exists $afterpath{$target}) {
	my $s = $afterpath{$target};
	for my $c (ref $s ? @$s : $s) {
	    print MAKEFILE "\t$c\n" or die "Makefile: $!\n";
	}
    }
    print MAKEFILE "\n" or die "Makefile: $!\n";
}
print MAKEFILE $remake or die "Makefile: $!\n";
print MAKEFILE "test : all\n" or die "Makefile: $!\n";
print MAKEFILE "\t\$(ABSPERLRUN) build/all_tests.pl\n" or die "Makefile: $!\n";
print MAKEFILE "\n" or die "Makefile: $!\n";
print MAKEFILE "check-manifest :\n" or die "Makefile: $!\n";
print MAKEFILE "\t\$(ABSPERLRUN) build/check-manifest\n" or die "Makefile: $!\n";
print MAKEFILE "\t\$(NOECHO)\$(ECHO) MANIFEST OK\n" or die "Makefile: $!\n";
print MAKEFILE "\n" or die "Makefile: $!\n";
print MAKEFILE "check-manifest-git :\n" or die "Makefile: $!\n";
print MAKEFILE "\t\$(ABSPERLRUN) build/check-manifest -g\n" or die "Makefile: $!\n";
print MAKEFILE "\t\$(NOECHO)\$(ECHO) MANIFEST OK\n" or die "Makefile: $!\n";
print MAKEFILE "\n" or die "Makefile: $!\n";
print MAKEFILE "dist :\n" or die "Makefile: $!\n";
print MAKEFILE "\t\$(MKPATH) '\$(DISTRIBUTION)'\n" or die "Makefile: $!\n";
for my $dist ('', $base, @extras) {
    my $csub = $dist eq '' ? '' : "s$dist";
    my $msub = $dist eq '' ? '-' : $dist;
    my $name = ($dist eq '' ? 'CLC-INTERCAL' : $dist) . "-$VERSION";
    for my $arc (qw(ddsh tar)) {
	print MAKEFILE "\t\$(ABSPERLRUN) build/check-manifest -lv$csub | \\\n" or die "Makefile: $!\n";
	print MAKEFILE "\t\t\$(ABSPERLRUN) build/make-dist $arc $name $msub '\$(SUFFIX)' | \\\n" or die "Makefile: $!\n";
	print MAKEFILE "\t\t\$(COMPRESS) > \$(DISTRIBUTION)/$name.$arc\$(SUFFIX)\n" or die "Makefile: $!\n";
    }
}
print MAKEFILE "\n" or die "Makefile: $!\n";
close MAKEFILE or die "Makefile: $!\n";

sub run_makefile_pl {
    my ($path) = @_;
    -d $path or die "$path: $!\n";
    my @xs;
    (my $name = $path) =~ s/^CLC-INTERCAL-//i;
    exists $avoid_xs{''} || exists $avoid_xs{lc $name}
	and @xs = ('--avoid-xs');
    print "Running Makefile.PL for $path\n";
    # prevent the "Checking if your kit is complete" by their Makefile.PL
    # since we've already done that here
    my $mf = catfile(curdir(), $path, 'Makefile');
    open(MF, '>>', $mf) and close MF;
    system($^X, $run_submakefile, $path, @xs, @ARGV) == 0
	or die "Makefile.PL failed\n";
    # Makefile.PL will have renamed the Makefile -> Makefile.old so if this
    # exists and is empty will just be the one we created and we delete it
    $mf = catfile(curdir(), $path, 'Makefile.old');
    stat $mf && (stat _)[7] == 0 and unlink $mf;
}

sub MY::constants {
    package MY;
    my $i = shift->SUPER::constants(@_);
    $constants .= $i;
    $i;
}

sub MY::makefile {
    package MY;
    my $i = shift->SUPER::makefile(@_);
    if (scalar(keys %avoid_xs)) {
	my $axs;
	if (exists $avoid_xs{''}) {
	    $axs = '--avoid-xs';
	} else {
	    my @axs = sort grep { $_ ne '' } values %avoid_xs;
	    $axs = '"--avoid-xs=' . join(',', @axs) . '"';
	}
	$i =~ s#^(\s*\$\(PERL.*\sMakefile\.PL\b)#$1 $axs#m;
    }
    $remake .= $i;
    $i;
}

sub MY::tools_other {
    package MY;
    my $i = shift->SUPER::tools_other(@_);
    $constants .= $i;
    $i;
}

sub MY::dist {
    package MY;
    my $i = shift->SUPER::dist(@_);
    $constants .= $i;
    $i;
}

1;
