package ExtUtils::MakeMaker;

# Authors: Andy Dougherty	<doughera@lafcol.lafayette.edu>
#	   Andreas Koenig	<k@franz.ww.TU-Berlin.DE>
#	   Tim Bunce		<Tim.Bunce@ig.co.uk>

# Last Revision: Sep 24, 1994

# This utility is designed to write a Makefile for an extension 
# module from a Makefile.PL. It is based on the excellent Makefile.SH
# model provided by Andy Dougherty and the perl5-porters. 

# It splits the task of generating the Makefile into several
# subroutines that can be individually overridden.
# Each subroutines returns the text it wishes to have written to
# the Makefile.

use Config;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(writeMakefile mkbootstrap $Verbose);
@EXPORT_OK = qw(%att @recognized_att_keys);

use strict qw(refs);

# Setup dummy package:
# MY exists for overriding methods to be defined within
unshift(@MY::ISA, qw(MM));

$Verbose = 0;
$Subdirs = 0;	# set to 1 to have this .PL run all below
$^W=1;


# For most extensions it will do to call
#
#   use ExtUtils::MakeMaker
#   &writeMakefile("potential_libs" => "-L/usr/alpha -lfoo -lbar");
#
# from Makefile.PL in the extension directory
# It is also handy to include some of the following attributes:
#
@recognized_att_keys=qw(
    TOP INC DISTNAME VERSION DEFINE OBJECT LDTARGET ARMAYBE
    BACKUP_LIBS  AUTOSPLITMAXLEN	
);
#
# TOP      is the directory above lib/ and ext/ (normally ../..)
#          (MakeMaker will normally work this out for itself)
# INC      is something like "-I/usr/local/Minerva/include"
# DISTNAME is a name of your choice for distributing the package
# VERSION  is your version number
# DEFINE   is something like "-DHAVE_UNISTD_H"
# OBJECT   defaults to '$(BASEEXT).o', but can be a long string containing 
#          all object files, e.g. "tkpBind.o tkpButton.o tkpCanvas.o"
# LDTARGET defaults to $(OBJECT) and is used in the ld command
#          (some machines need additional switches for bigger projects)
# ARMAYBE  defaults to ":", but can be used to run ar before ld
# BACKUP_LIBS is an anonymous array of libraries to be searched for
#          until we get at least some output from ext/util/extliblist
#          'potential_libs' => "-lgdbm",
#          'BACKUP_LIBS' => [ "-ldbm -lfoo", "-ldbm.nfs" ]
# AUTOSPLITMAXLEN defaults to 8 and is used when autosplit is done
#          (can be set higher on a case-by-case basis)

#
# `make distclean'  builds $(DISTNAME)-$(VERSION).tar.Z after a clean

# Be aware, that you can also pass attributes into the %att hash table
# by calling Makefile.PL with an argument of the form TOP=/some/where.

# If the Makefile generated by default does not fit your purpose,
# you may specify private subroutines in the Makefile.PL as there are:
#
# MY->initialize        =>   sub MY::initialize{ ... }
# MY->post_initialize   =>   sub MY::post_initialize{ ... }
# MY->constants         =>   etc
# MY->dynamic
# etc. (see function writeMakefile, for the current breakpoints)
#
# if you still need a different solution, try to develop another 
# subroutine, that fits your needs and submit the diffs to 
# perl5-porters or comp.lang.perl as appropriate.
#
# Each subroutines returns the text it wishes to have written to
# the Makefile. To override a section of the Makefile you can
# either say: 	sub MY::co { "new literal text" }
# or you can edit the default by saying something like:
#	sub MY::co { $_=MM->co; s/old text/new text/; $_ }

sub writeMakefile {
    %att = @_;
    local($\)="\n";

    foreach (@ARGV){
	$att{$1}=$2 if m/(.*)=(.*)/;
    }
    print STDOUT "MakeMaker" if $Verbose;
    print STDOUT '     %att=("', join('", "', %att), '")' if $Verbose && %att;

    MY->initialize();

    print STDOUT "Writing ext/$att{FULLEXT}/Makefile (with variable substitutions)";

    open MAKE, ">Makefile" or die "Unable to open Makefile: $!";

    MY->mkbootstrap(split(" ", $att{'dynaloadlibs'}));
    print MAKE MY->post_initialize;

    print MAKE MY->constants;
    print MAKE MY->post_constants;

    print MAKE MY->subdir if $Subdirs;
    print MAKE MY->dynamic;
    print MAKE MY->force;
    print MAKE MY->static;
    print MAKE MY->co;
    print MAKE MY->c;
    print MAKE MY->installpm;
    print MAKE MY->clean;
    print MAKE MY->realclean;
    print MAKE MY->test;
    print MAKE MY->install;
    print MAKE MY->perldepend;
    print MAKE MY->distclean;
    print MAKE MY->postamble;

    MY->finish;

    close MAKE;

}

sub mkbootstrap{
    MY->mkbootstrap(@_)
}

sub avoid_typo_warnings{
    local($t) = "$t
	$main::writeMakefile
	$main::mkbootstrap
	$main::Verbose
	$DynaLoader::dl_resolve_using
	$ExtUtils::MakeMaker::Config
	$DynaLoader::Config
";
}


# --- Supply the MakeMaker default methods ---

package MM;

use Config;
require Exporter;

Exporter::import('ExtUtils::MakeMaker',
	qw(%att @recognized_att_keys $Verbose)
);

sub initialize {
    # Find out directory name.  This is also the extension name.
    chop($pwd=`pwd`);

    unless ( $top = $att{TOP} ){
	foreach(qw(../.. ../../.. ../../../..)){
	    ($top=$_, last) if -f "$_/config.sh";
	}
	die "Can't find config.sh" unless -f "$top/config.sh";
    }
    chdir $top or die "Couldn't chdir $top";
    chop($abstop=`pwd`);
    chdir $pwd;

    # EXTMODNAME = The perl module name for this extension.
    # FULLEXT = Full pathname to extension directory.
    # BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT.
    # ROOTEXT = Directory part of FULLEXT. May be empty.
    my($p) = $pwd; $p =~ s:^\Q$abstop/ext/\E::;
    ($att{EXTMODNAME}=$p) =~ s#/#::#g ;		#eg. BSD::Foo::Socket
    ($att{FULLEXT}   =$p);			#eg. BSD/Foo/Socket
    ($att{BASEEXT}   =$p) =~ s:.*/:: ;		#eg. Socket
    ($att{ROOTEXT}   =$p) =~ s:/?\Q$att{BASEEXT}\E$:: ; #eg. BSD/Foo

    #determine, which perl called us
    if ($^X =~ m:^/:){
       $perl=$^X;
    } elsif ($^X =~ m:(.*/)(.*):){
       chdir $1;
       chop($perldir=`pwd`);
       $perl="$perldir/$2";
       chdir $pwd;
    } else {
       foreach $dir (split ":", $ENV{PATH}){
           last if (-x ($perl="$dir/$^X") and ! -d $perl);
       }
    }

    # For the test target we probably will need a different perl
    ($fullperl = $perl) =~ s/miniperl$/perl/ ;

    for $key (@recognized_att_keys, 
	      qw(extralibs dynaloadlibs statloadlibs 
		 potential_libs)){
	# avoid warnings for uninitialized vars
	$att{$key} = "" unless defined $att{$key};
    }

    # This extension might have its own typemap
    $exttypemap= (-f "typemap") ? "typemap" : "";

    $eunicefix = $Config{'eunicefix'};

    # compute extralibs, dynaloadlibs and statloadlibs from
    # $att{'potential_libs'}

    unless ( &run_extliblist($att{'potential_libs'}) ){
       foreach ( @{$att{'BACKUP_LIBS'} || []} ){
           #  Try again.  Maybe they have specified some other libraries
           last if  &run_extliblist($_);
       }
    }

    $att{BOOTSTRAP}="$att{BASEEXT}.bs";
}

sub run_extliblist {
    my($potential_libs)=@_;
    # Now run ext/util/extliblist to discover what *libs definitions
    # are required for the needs of $potential_libs
    $ENV{'potential_libs'} = $potential_libs;
    $_=`. $abstop/ext/util/extliblist;
	echo extralibs=\$extralibs
	echo dynaloadlibs=\$dynaloadlibs
	echo statloadlibs=\$statloadlibs
	echo bootdep=\$bootdep
	`;
    my(@w);
    foreach $line (split "\n", $_){
	chomp $line;
	if ($line =~ /(.*)\s*=\s*(.*)$/){
	    $att{$1} = $2;
	    print STDERR "	$1 = $2" if $Verbose;
	}else{
	    push(@w, $line);
	}
    }
    print STDERR "Messages from extliblist:\n", join("\n",@w,'')
       if @w ;
    join '', @att{qw(extralibs dynaloadlibs statloadlibs)};
}


sub post_initialize{
    "";
}
 

sub constants {
    my(@m);

    # This extension might need bootstrap support
    $att{BOOTDEP} = (-f "$att{BASEEXT}_BS")  ? "$att{BASEEXT}_BS" : "";

    $att{OBJECT} = '$(BASEEXT).o' unless  $att{OBJECT};
    $att{LDTARGET} = '$(OBJECT)' unless  $att{LDTARGET};
    $att{ARMAYBE} = ":" unless  $att{ARMAYBE};
    $att{AUTOSPLITMAXLEN} = 8 unless  $att{AUTOSPLITMAXLEN};

    push @m, "
#
# This Makefile is for the $att{FULLEXT} extension to perl.
# It was written by Makefile.PL, so don't edit it, edit
# Makefile.PL instead
# 

#shellflags seems not to be needed anywhere except unicos
shellflags = $Config{'shellflags'}
TOP = $top
ABSTOP = $abstop
PERL = $perl
FULLPERL = $fullperl
INC = $att{INC}
DEFINE = $att{DEFINE}
OBJECT = $att{OBJECT}
LDTARGET = $att{LDTARGET}
ARMAYBE = $att{ARMAYBE}
DISTNAME = $att{DISTNAME}
VERSION = $att{VERSION}
AUTOSPLITMAXLEN = $att{AUTOSPLITMAXLEN}
";

    push @m, "
LDFLAGS = $Config{'ldflags'}
CLDFLAGS = $Config{'ldflags'}
CC = $Config{'cc'}
LIBC = $Config{'libc'}
RANLIB = $Config{'ranlib'}
SMALL = $Config{'small'}
LARGE = $Config{'large'} $Config{'split'}
DLSRC = $Config{'dlsrc'}
# The following are used to build and install shared libraries for
# dynamic loading.
LDDLFLAGS = $Config{'lddlflags'}
CCDLFLAGS = $Config{'ccdlflags'}
CCCDLFLAGS = $Config{'cccdlflags'}
SO = $Config{'so'}
DLEXT = $Config{'dlext'}
";

    push @m, "
# EXTMODNAME = The perl module name for this extension.
# FULLEXT = Full pathname to extension directory.
# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT.
# ROOTEXT = Directory part of FULLEXT. May be empty.
EXTMODNAME = $att{EXTMODNAME}
FULLEXT = $att{FULLEXT}
BASEEXT = $att{BASEEXT}
ROOTEXT = $att{ROOTEXT}
# and for backward compatibility and for AIX support (due to change!)
EXT = $att{BASEEXT}

# $att{FULLEXT} might have its own typemap
EXTTYPEMAP = $exttypemap
# $att{FULLEXT} might have its own bootstrap support
BOOTSTRAP = $att{BOOTSTRAP}
BOOTDEP = $att{BOOTDEP}
";

    push @m, "
# $att{FULLEXT} might need to be linked with some extra libraries.
# EXTRALIBS =  full list of libraries needed for static linking.
#		Only those libraries that actually exist are included.
# DYNLOADLIBS = list of those libraries that are needed but can be
#		linked in dynamically on this platform.  On SunOS, for
#		example, this would be .so* libraries, but not archive
#		libraries.  The bootstrap file is installed only if
#		this list is not empty.
# STATLOADLIBS = list of those libraries which must be statically
#		linked into the shared library.  On SunOS 4.1.3, 
#		for example,  I have only an archive version of
#		-lm, and it must be linked in statically.
EXTRALIBS = $att{'extralibs'}
DYNALOADLIBS = $att{'dynaloadlibs'}
STATLOADLIBS = $att{'statloadlibs'}
";

    push @m, '
# Where to put things:
AUTO = $(TOP)/lib/auto
AUTOEXT = $(TOP)/lib/auto/$(FULLEXT)
INST_BOOT = $(AUTOEXT)/$(BASEEXT).bs
INST_DYNAMIC = $(AUTOEXT)/$(BASEEXT).$(DLEXT)
INST_STATIC = $(BASEEXT).a
INST_PM = $(TOP)/lib/$(FULLEXT).pm
'."
# These two are only used by install: targets
INSTALLPRIVLIB = $Config{'installprivlib'}
INSTALLARCHLIB = $Config{'installarchlib'}
";

    push @m, q{
# Tools
XSUBPP = $(TOP)/ext/xsubpp
CCCMD = `sh $(shellflags) $(ABSTOP)/cflags $@`
SHELL = /bin/sh
# the following is a portable way to say mkdir -p
MKPATH = $(PERL) -we '$$"="/"; foreach(split(/\//,$$ARGV[0])){ push(@p, $$_); next if -d "@p"; print "mkdir @p\n"; mkdir("@p",0777)||die "mkdir @p: $$!" } exit 0;'
AUTOSPLITLIB = cd $(TOP); \
	$(PERL) -Ilib -e 'use AutoSplit; $$AutoSplit::Verbose=1; $$AutoSplit::Maxlen=$(AUTOSPLITMAXLEN); autosplit_lib_modules(@ARGV) ;'
};

    push @m, '

all :: 

config :: Makefile
	@$(MKPATH) $(AUTOEXT)

install ::

';
    join('',@m);
}


sub post_constants{
    "";
}


sub subdir {
    my(@m);
    foreach $MakefilePL (<*/Makefile.PL>){
	($subdir=$MakefilePL) =~ s:/Makefile\.PL$:: ;
	push @m, "
config ::
	\@cd $subdir ; \\
	if test ! -f Makefile; then \\
	test -f Makefile.PL  && \$(PERL) -I\$(ABSTOP)/lib Makefile.PL TOP=\$(ABSTOP) ; \\
	fi

all ::
	cd $subdir ; \$(MAKE) config
	cd $subdir ; \$(MAKE) all
";

    }
    join('',@m);
}


sub co {
    '
.c.o:
	$(CCCMD) $(CCCDLFLAGS) $(DEFINE) -I$(TOP) $(INC) $*.c
';
}


sub force {
    '
# Phony target to force checking subdirectories.
FORCE:
';
}


sub dynamic {
    '
all::	dynamic

# Target for Dynamic Loading:
dynamic::	$(INST_DYNAMIC) $(INST_PM) $(INST_BOOT)

$(INST_DYNAMIC): $(OBJECT)
	@$(MKPATH) $(AUTOEXT)
	$(ARMAYBE) cr $(EXTMODNAME).a $(OBJECT) 
	ld $(LDDLFLAGS) -o $@ $(LDTARGET) $(STATLOADLIBS)

$(BOOTSTRAP): $(BOOTDEP)
	$(PERL) -I$(TOP)/lib -e \'use ExtUtils::MakeMaker; &mkbootstrap("$(DYNALOADLIBS)");\'
	touch $(BOOTSTRAP)

$(INST_BOOT): $(BOOTSTRAP)
	@test ! -s $(BOOTSTRAP) || cp $(BOOTSTRAP) $@
';
}


sub static {
    '
# Target for Static Loading:
static:: $(INST_STATIC) $(INST_PM)

$(INST_STATIC): $(OBJECT)
	ar cr $@ $(OBJECT)
	$(RANLIB) $@
	echo $(EXTRALIBS) >> $(TOP)/ext.libs
';
}


sub c {
    '
$(BASEEXT).c:	$(BASEEXT).xs $(XSUBPP) $(TOP)/ext/typemap $(EXTTYPEMAP) $(TOP)/cflags
	$(PERL) $(XSUBPP) $(BASEEXT).xs >tmp
	mv tmp $@
';
}


sub installpm {
    '
$(INST_PM):	$(BASEEXT).pm
	@$(MKPATH) $(TOP)/lib/$(ROOTEXT)
	rm -f $@
	cp $(BASEEXT).pm $@
	@$(AUTOSPLITLIB) $(EXTMODNAME)
';
}
#old AutoSplit:
# cd $(TOP); $(PERL) -Ilib
#	-e \'use AutoSplit; $$AutoSplit::Verbose='.$Verbose.';
#	autosplit_lib_modules("$(EXTMODNAME)") ;\'


sub clean {
    '
clean::
	rm -f *.o *.a mon.out core $(BASEEXT).c so_locations
	rm -f makefile Makefile $(BOOTSTRAP) $(BASEEXT).bso
';
}


sub realclean {
    '
realclean:: 	clean
	rm -f $(INST_DYNAMIC) $(INST_STATIC) $(INST_BOOT)
	rm -rf $(INST_PM) $(AUTOEXT)

purge:	realclean
';
}


sub test {
    '
test: all
	$(FULLPERL) -I$(TOP)/lib -e \'use Test::Harness; runtests @ARGV;\' t/*.t
';
}


sub install {
    '
# used if installperl will not be installing it for you
install:: all
	# not yet defined
';
}


sub distclean {
    '
distclean:     clean
	rm -f Makefile *~ t/*~
	cd ..; tar cvf "$(DISTNAME)-$(VERSION).tar" $(BASEEXT)
	cd ..; compress "$(DISTNAME)-$(VERSION).tar"
';
}


sub perldepend {
    '
$(OBJECT) : Makefile
$(OBJECT) : $(TOP)/EXTERN.h
$(OBJECT) : $(TOP)/INTERN.h
$(OBJECT) : $(TOP)/XSUB.h
$(OBJECT) : $(TOP)/av.h
$(OBJECT) : $(TOP)/cop.h
$(OBJECT) : $(TOP)/cv.h
$(OBJECT) : $(TOP)/dosish.h
$(OBJECT) : $(TOP)/embed.h
$(OBJECT) : $(TOP)/form.h
$(OBJECT) : $(TOP)/gv.h
$(OBJECT) : $(TOP)/handy.h
$(OBJECT) : $(TOP)/hv.h
$(OBJECT) : $(TOP)/keywords.h
$(OBJECT) : $(TOP)/mg.h
$(OBJECT) : $(TOP)/op.h
$(OBJECT) : $(TOP)/opcode.h
$(OBJECT) : $(TOP)/patchlevel.h
$(OBJECT) : $(TOP)/perl.h
$(OBJECT) : $(TOP)/perly.h
$(OBJECT) : $(TOP)/pp.h
$(OBJECT) : $(TOP)/proto.h
$(OBJECT) : $(TOP)/regcomp.h
$(OBJECT) : $(TOP)/regexp.h
$(OBJECT) : $(TOP)/scope.h
$(OBJECT) : $(TOP)/sv.h
$(OBJECT) : $(TOP)/unixish.h
$(OBJECT) : $(TOP)/util.h
$(TOP)/config.h:        $(TOP)/config.sh; cd $(TOP); /bin/sh config_h.SH
$(TOP)/embed.h: $(TOP)/config.sh; cd $(TOP); /bin/sh embed_h.SH
$(TOP)/cflags:  $(TOP)/config.sh; cd $(TOP); /bin/sh cflags.SH

Makefile:	Makefile.PL
	$(PERL) -I$(TOP)/lib Makefile.PL
';
}


sub postamble{
    "";
}


sub finish {
    chmod 0755, "Makefile";
    system("$eunicefix Makefile") unless $eunicefix eq ":";
}



sub mkbootstrap {
#
# mkbootstrap, by:
#
#	Andreas Koenig <k@otto.ww.TU-Berlin.DE>
#	Tim Bunce <Tim.Bunce@ig.co.uk>
#	Andy Dougherty <doughera@lafcol.lafayette.edu>
#
#  This perl script attempts to make a bootstrap file for use by this
#  system's DynaLoader. It typically gets called from an extension
#  Makefile.
#
# There is no .bs file supplied with the extension. Instead a _BS
# file which has code for the special cases, like posix for berkeley db
# on the NeXT.
# 
# This file will get parsed, and produce a maybe empty
# @DynaLoader::dl_resolve_using array for the current architecture.
# That will be extended by $dynaloadlibs, which was computed by Andy's
# extliblist script. If this array still is empty, we do nothing, else
# we write a .bs file with an @DynaLoader::dl_resolve_using array, but
# without any `if's, because there is no longer a need to deal with
# special cases.
# 
# The _BS file can put some code into the generated .bs file by placing
# it in $bscode. This is a handy 'escape' mechanism that may prove
# useful in complex situations.
# 
# If @DynaLoader::dl_resolve_using contains -L* or -l* entries then
# mkbootstrap will automatically add a dl_findfile() call to the
# generated .bs file.
#
    my($self, @dynaloadlibs)=@_;
    print STDERR "	dynaloadlibs=@dynaloadlibs" if $Verbose;
    require DynaLoader; # we need DynaLoader, if the *_BS gets interpreted
    import DynaLoader;  # we don't say `use', so if DynaLoader is not 
	          # yet built MakeMaker works nonetheless except here

    &initialize unless defined $att{BOOTSTRAP};

    rename "$att{BASEEXT}.bs", "$att{BASEEXT}.bso";

    if (-f "$att{BASEEXT}_BS"){
	$_ = "$att{BASEEXT}_BS";
	package DynaLoader; # execute code as if in DynaLoader
	local($osname, $dlsrc) = (); # avoid warnings
	($osname, $dlsrc) = @Config{qw(osname dlsrc)};
	$bscode = "";
	unshift @INC, ".";
	require $_;
    }

    if ($Config{'dlsrc'} =~ /^dl_dld/){
	package DynaLoader;
	push(@dl_resolve_using, dl_findfile('-lc'));
    }

    my(@all) = (@dynaloadlibs, @DynaLoader::dl_resolve_using);
    my($method) = '';
    if (@all){
	open BS, ">$att{BASEEXT}.bs"
		or die "Unable to open $att{BASEEXT}.bs: $!";
	print STDOUT "Writing $att{BASEEXT}.bs\n";
	print STDOUT "	containing: @all" if $Verbose;
	print BS "# $att{BASEEXT} DynaLoader bootstrap file for $Config{'osname'} architecture.\n";
	print BS "# Do not edit this file, changes will be lost.\n";
	print BS "# This file was automatically generated by the\n";
	print BS "# mkbootstrap routine in ExtUtils/MakeMaker.pm.\n";
	print BS "\@DynaLoader::dl_resolve_using = ";
	if (" @all" =~ m/ -[lL]/){
	    print BS "  dl_findfile(qw(\n  @all\n  ));\n";
	}else{
	    print BS "  qw(@all);\n";
	}
	# write extra code if *_BS says so
	print BS $DynaLoader::bscode if $DynaLoader::bscode;
	print BS "1;\n";
	close BS;
    }

    if ($Config{'dlsrc'} =~ /^dl_aix/){
       open AIX, ">$att{BASEEXT}.exp";
       print AIX "#!\nboot_$att{BASEEXT}";
       close AIX;
    }
}

# the following makes AutSplit happy (bug in perl5b3e)
package ExtUtils::MakeMaker;
1;

__END__
package ExtUtils::MakeMaker;

# Authors: Andy Dougherty	<doughera@lafcol.lafayette.edu>
#	   Andreas Koenig	<k@franz.ww.TU-Berlin.DE>
#	   Tim Bunce		<Tim.Bunce@ig.co.uk>

# Last Revision: Sep 19, 1994

# This utility is designed to write a Makefile for an extension 
# module from a Makefile.PL. It is based on the excellent Makefile.SH
# model provided by Andy Dougherty and the perl5-porters. 

# It splits the task of generating the Makefile into several
# subroutines that can be individually overridden.
# Each subroutines returns the text it wishes to have written to
# the Makefile.

use Config;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(writeMakefile mkbootstrap $Verbose);
@EXPORT_OK = qw(%att @recognized_att_keys);

use strict qw(refs);

# Setup dummy package:
#   MY exists for overriding methods to be defined within
unshift(@MY::ISA, qw(MM));

$Verbose = 0;
$Subdirs = 0;	# set to 1 to have this .PL run all below
$^W=1;
$\="\n";


# For most extensions it will do to call
#
#   use ExtUtils::MakeMaker
#   &writeMakefile("potential_libs" => "-L/usr/alpha -lfoo -lbar");
#
# from Makefile.PL in the extension directory
# It is also handy to include some of the following attributes:
#
@recognized_att_keys=qw(
    TOP INC DISTNAME VERSION
);
#
# TOP is the directory above lib/ and ext/ (normally ../..)
#     (MakeMaker will normally work this out for itself)
# INC is designed to look something like "-I/usr/local/Minerva/include"
# DISTNAME is a name of your choice for distributing the package
# VERSION is your version number
#
# `make distclean'  builds $(DISTNAME)-$(VERSION).tar.Z after a clean

# Be aware, that you can also pass attributes into the %att hash table
# by calling Makefile.PL with an argument of the form TOP=/some/where.

# If the Makefile generated by default does not fit your purpose,
# you may specify private subroutines in the Makefile.PL as there are:
#
# MY->initialize        =>   sub MY::initialize{ ... }
# MY->post_initialize   =>   sub MY::post_initialize{ ... }
# MY->constants         =>   etc
# MY->dynamic
# etc. (see function writeMakefile, for the current breakpoints)
#
# if you still need a different solution, try to develop another 
# subroutine, that fits your needs and submit the diffs to 
# perl5-porters or comp.lang.perl as appropriate.
#
# Each subroutines returns the text it wishes to have written to
# the Makefile. To override a section of the Makefile you can
# either say: 	sub MY::co { "new literal text" }
# or you can edit the default by saying something like:
#	sub MY::co { $_=MM->co; s/old text/new text/; $_ }


1; #to make require happy


sub writeMakefile {
    %att = @_;
    foreach (@ARGV){
	$att{$1}=$2 if m/(.*)=(.*)/;
    }
    print STDOUT "MakeMaker" if $Verbose;
    print STDOUT "	",%att if $Verbose && %att;

    MY->initialize();

    print STDOUT "Writing ext/$att{FULLEXT}/Makefile (with variable substitutions)";

    open MAKE, ">Makefile" or die "Unable to open Makefile: $!";

    MY->mkbootstrap(split(" ", $att{'dynaloadlibs'}));
    print MAKE MY->post_initialize;

    print MAKE MY->constants;
    print MAKE MY->post_constants;

    print MAKE MY->subdir if $Subdirs;
    print MAKE MY->dynamic;
    print MAKE MY->force;
    print MAKE MY->static;
    print MAKE MY->co;
    print MAKE MY->c;
    print MAKE MY->installpm;
    print MAKE MY->clean;
    print MAKE MY->realclean;
    print MAKE MY->test;
    print MAKE MY->install;
    print MAKE MY->perldepend;
    print MAKE MY->distclean;
    print MAKE MY->postamble;

    MY->finish;

    close MAKE;

}

sub mkbootstrap{
    MY->mkbootstrap(@_)
}

sub avoid_typo_warnings{
    local($t) = "$AutoLoader::carp
	@main::recognized_att_keys
	$main::mkbootstrap
	$main::Verbose
	$ExtUtils::MakeMaker::Config
	$AutoLoader::confess
	$DynaLoader::confess";
}


# --- Supply the MakeMaker default methods ---

package MM;

use Config;
use DynaLoader;	# for mkbootstrap
require Exporter;

Exporter::import('ExtUtils::MakeMaker',
	qw(%att @recognized_att_keys $Verbose)
);

sub initialize {
    # Find out directory name.  This is also the extension name.
    chop($pwd=`pwd`);

    unless ( $top = $att{TOP} ){
	foreach(qw(../.. ../../.. ../../../..)){
	    ($top=$_, last) if -f "$_/config.sh";
	}
	die "Can't find config.sh" unless -f "$top/config.sh";
    }
    chdir $top or die "Couldn't chdir $top";
    chop($abstop=`pwd`);
    chdir $pwd;

    # EXTMODNAME = The perl module name for this extension.
    # FULLEXT = Full pathname to extension directory.
    # BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT.
    # ROOTEXT = Directory part of FULLEXT. May be empty.
    my($p) = $pwd; $p =~ s:^$abstop/ext/::;
    ($att{EXTMODNAME}=$p) =~ s#/#::# ;		#eg. BSD::Foo::Socket
    ($att{FULLEXT}   =$p);			#eg. BSD/Foo/Socket
    ($att{BASEEXT}   =$p) =~ s:.*/:: ;		#eg. Socket
    ($att{ROOTEXT}   =$p) =~ s:/?$att{BASEEXT}$:: ; #eg. BSD/Foo

    #determine, which perl called us
    if ($^X =~ m:^/:){
       $perl=$^X;
    } elsif ($^X =~ m:(.*/)(.*):){
       chdir $1;
       chop($perldir=`pwd`);
       $perl="$perldir/$2";
       chdir $pwd;
    } else {
       foreach $dir (split ":", $ENV{PATH}){
           last if (-x ($perl="$dir/$^X"));
       }
    }

    for $key (@recognized_att_keys){
	# avoid warnings for uninitialized vars
	$att{$key} = "" unless defined $att{$key};
    }

    # This extension might have its own typemap
    $exttypemap= (-f "typemap") ? "typemap" : "";

    $make= $Config{'altmake'} || "make" ;

    $dlsrc = $Config{'dlsrc'};
    $eunicefix = $Config{'eunicefix'};

    # compute extralibs, dynaloadlibs and statloadlibs from
    # $att{'potential_libs'}

    foreach $key (qw(extralibs dynaloadlibs statloadlibs 
	    BOOTDEP potential_libs
	    INC DIST VERSION
	)){
	#avoid warnings for uninitialized variables
	$att{$key} = "" unless defined $att{$key};
    }

    # Now run ext/util/extliblist to discover what *libs definitions
    # are required for the needs of $potential_libs
    $ENV{'potential_libs'} = $att{'potential_libs'};
    $_=`. $abstop/ext/util/extliblist;
	echo extralibs=\$extralibs
	echo dynaloadlibs=\$dynaloadlibs
	echo statloadlibs=\$statloadlibs
	echo bootdep=\$bootdep
	`;
    #old:$_=`sh $abstop/ext/util/extlibprint $att{'potential_libs'}`;
    my(@w);
    foreach $line (split "\n", $_){
	chomp $line;
	if ($line =~ /(.*)\s*=\s*(.*)$/){
	    $att{$1} = $2;
	    print STDERR "	$1 = $2" if $Verbose;
	}else{
	    push(@w, $line);
	}
    }
    print STDERR "Messages from extliblist:\n", join("\n",@w,'')
	if @w;

    $att{BOOTSTRAP}="$att{BASEEXT}.bs";
    $installboot="\$(TOP)/lib/auto/$att{FULLEXT}.bs";
}


sub post_initialize{
    "";
}
 

sub constants {
    my(@m);

    # This extension might need bootstrap support
    $att{BOOTDEP} = (-f "$att{BASEEXT}_BS")  ? "$att{BASEEXT}_BS" : "";

    push @m, "
#
# This Makefile is for the $att{FULLEXT} extension to perl.
# It was written by Makefile.PL, so don't edit it, edit
# Makefile.PL instead
# 

TOP = $top
ABSTOP = $abstop

INC = $att{INC}
DISTNAME = $att{DISTNAME}
VERSION = $att{VERSION}
";

    push @m, "
LDFLAGS = $Config{'ldflags'}
CLDFLAGS = $Config{'ldflags'}
CC = $Config{'cc'}
LIBC = $Config{'libc'}
RANLIB = $Config{'ranlib'}
SMALL = $Config{'small'}
LARGE = $Config{'large'} $Config{'split'}
DLSRC = $Config{'dlsrc'}
";

    push @m, "
# EXTMODNAME = The perl module name for this extension.
# FULLEXT = Full pathname to extension directory.
# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT.
# ROOTEXT = Directory part of FULLEXT. May be empty.
EXTMODNAME = $att{EXTMODNAME}
FULLEXT = $att{FULLEXT}
BASEEXT = $att{BASEEXT}
ROOTEXT = $att{ROOTEXT}

# $att{FULLEXT} might have its own typemap
EXTTYPEMAP = $exttypemap
# $att{FULLEXT} might have its own bootstrap support
BOOTSTRAP = $att{BOOTSTRAP}
BOOTDEP = $att{BOOTDEP}
";

    push @m, "
# The following are used to build and install shared libraries for
# dynamic loading.
LDDLFLAGS = $Config{'lddlflags'}
CCDLFLAGS = $Config{'ccdlflags'}
CCCDLFLAGS = $Config{'cccdlflags'}
SO = $Config{'so'}
";

    push @m, "
# $att{FULLEXT} might need to be linked with some extra libraries.
# EXTRALIBS =  full list of libraries needed for static linking.
#		Only those libraries that actually exist are included.
# DYNLOADLIBS = list of those libraries that are needed but can be
#		linked in dynamically on this platform.  On SunOS, for
#		example, this would be .so* libraries, but not archive
#		libraries.  The bootstrap file is installed only if
#		this list is not empty.
# STATLOADLIBS = list of those libraries which must be statically
#		linked into the shared library.  On SunOS 4.1.3, 
#		for example,  I have only an archive version of
#		-lm, and it must be linked in statically.
EXTRALIBS = $att{'extralibs'}
DYNALOADLIBS  = $att{'dynaloadlibs'}
STATLOADLIBS = $att{'statloadlibs'}
PERL = $perl
";

    push @m, '
# Where to put things:
AUTO = $(TOP)/lib/auto
AUTOEXT = $(TOP)/lib/auto/$(FULLEXT)
INSTALLBOOT = $(AUTOEXT)/$(BASEEXT).bs
INSTALLDYNAMIC = $(AUTOEXT)/$(BASEEXT).$(SO)
INSTALLSTATIC = $(BASEEXT).a
INSTALLPM = $(TOP)/lib/$(FULLEXT).pm
XSUBPP = $(TOP)/ext/xsubpp
SHELL = /bin/sh
CCCMD = `sh $(shellflags) $(ABSTOP)/cflags $@`

all :: 

config :: Makefile
	@test -d $(AUTO) || mkdir $(AUTO)
	@test -d $(AUTOEXT) || mkdir $(AUTOEXT)

install ::

';
	join('',@m);
}


sub post_constants{
    "";
}


sub subdir {
    my(@m);
    foreach $MakefilePL (<*/Makefile.PL>){
	($subdir=$MakefilePL) =~ s:/Makefile\.PL$:: ;
	push @m, "
config ::
	\@cd $subdir ; \\
	if test ! -f Makefile; then \\
	test -f Makefile.PL  && \$(PERL) -I\$(ABSTOP)/ext/util -I\$(ABSTOP)/lib Makefile.PL TOP=\$(ABSTOP) ; \\
	fi

all ::
	cd $subdir ; \$(MAKE) config
	cd $subdir ; \$(MAKE) all
";

    }
    join('',@m);
}


sub co {
    '
.c.o:
	$(CCCMD) $(CCCDLFLAGS) -I$(TOP) $(INC) $*.c
';
}


sub force {
    '
# Phony target to force checking subdirectories.
FORCE:
';
}


sub dynamic {
    '
all::	dynamic
# Target for Dynamic Loading:
dynamic::	$(INSTALLDYNAMIC) $(INSTALLPM) $(INSTALLBOOT)

$(INSTALLDYNAMIC): $(BASEEXT).o
	@: for better portability we need a way to avoid using -p 
	@test -d $(AUTOEXT) || mkdir -p $(AUTOEXT)
	ld $(LDDLFLAGS) -o $@ $(BASEEXT).o $(STATLOADLIBS)

$(BOOTSTRAP): $(BOOTDEP)
	$(PERL) -I$(TOP)/ext/util -I$(TOP)/lib -e \'use ExtUtils::MakeMaker; &mkbootstrap("$(DYNALOADLIBS)");\'

$(INSTALLBOOT): $(BOOTSTRAP)
	@test ! -s $(BOOTSTRAP) || cp $(BOOTSTRAP) $@
';
}


sub static {
    '
# Target for Static Loading:
static:: $(INSTALLSTATIC) $(INSTALLPM)

$(INSTALLSTATIC): $(BASEEXT).o
	ar cr $@ $(BASEEXT).o
	$(RANLIB) $@
	echo $(EXTRALIBS) >> $(TOP)/ext.libs
';
}


sub c {
    '
$(BASEEXT).c:	$(BASEEXT).xs $(XSUBPP) $(TOP)/ext/typemap $(EXTTYPEMAP) $(TOP)/cflags
	$(PERL) $(XSUBPP) $(BASEEXT).xs >tmp
	mv tmp $@
';
}


sub installpm {
    '
$(INSTALLPM):	$(BASEEXT).pm
	@: for better portability we need a way to avoid using -p
	@test -d $(TOP)/lib/$(ROOTEXT) || mkdir -p $(TOP)/lib/$(ROOTEXT)
	cp $(BASEEXT).pm $@
	cd $(TOP); \
	    $(PERL) -Ilib -e \'use AutoSplit; $$AutoSplit::Verbose='.$Verbose.'; \
	    autosplit_lib_modules("$(EXTMODNAME)") ;\'
';
}


sub clean {
    '
clean::
	rm -f *.o *.a mon.out core $(BASEEXT).c so_locations
	rm -f makefile Makefile $(BOOTSTRAP) $(BASEEXT).bso
';
}


sub realclean {
    '
realclean:: 	clean
	rm -f $(INSTALLDYNAMIC) $(INSTALLSTATIC) $(INSTALLBOOT)
	rm -rf $(INSTALLPM) $(AUTOEXT)

purge:	realclean
';
}


sub test {
    '
test: all $(PERL)
	$(PERL) -I$(TOP)/lib -e \'use TestHarness; runtests @ARGV;\' t/*.t
';
}


sub install {
    '
# used if installperl will not be installing it for you
install:: all
	# not yet defined
';
}


sub distclean {
    '
distclean:     clean
	rm -f Makefile *~ t/*~
	cd ..; tar cvf "$(DISTNAME)-$(VERSION).tar" $(BASEEXT)
	cd ..; compress "$(DISTNAME)-$(VERSION).tar"
';
}


sub perldepend {
    '
$(BASEEXT).o : Makefile
$(BASEEXT).o : $(TOP)/EXTERN.h
$(BASEEXT).o : $(TOP)/INTERN.h
$(BASEEXT).o : $(TOP)/XSUB.h
$(BASEEXT).o : $(TOP)/av.h
$(BASEEXT).o : $(TOP)/cop.h
$(BASEEXT).o : $(TOP)/cv.h
$(BASEEXT).o : $(TOP)/dosish.h
$(BASEEXT).o : $(TOP)/embed.h
$(BASEEXT).o : $(TOP)/form.h
$(BASEEXT).o : $(TOP)/gv.h
$(BASEEXT).o : $(TOP)/handy.h
$(BASEEXT).o : $(TOP)/hv.h
$(BASEEXT).o : $(TOP)/keywords.h
$(BASEEXT).o : $(TOP)/mg.h
$(BASEEXT).o : $(TOP)/op.h
$(BASEEXT).o : $(TOP)/opcode.h
$(BASEEXT).o : $(TOP)/patchlevel.h
$(BASEEXT).o : $(TOP)/perl.h
$(BASEEXT).o : $(TOP)/perly.h
$(BASEEXT).o : $(TOP)/pp.h
$(BASEEXT).o : $(TOP)/proto.h
$(BASEEXT).o : $(TOP)/regcomp.h
$(BASEEXT).o : $(TOP)/regexp.h
$(BASEEXT).o : $(TOP)/scope.h
$(BASEEXT).o : $(TOP)/sv.h
$(BASEEXT).o : $(TOP)/unixish.h
$(BASEEXT).o : $(TOP)/util.h

Makefile:	Makefile.PL
	$(PERL) -I$(TOP)/ext/util -I$(TOP)/lib Makefile.PL
';
}


sub postamble{
    "";
}


sub finish {
    chmod 0755, "Makefile";
    system("$eunicefix Makefile") unless $eunicefix eq ":";
}



sub mkbootstrap {
#
# mkbootstrap, by:
#
#	Andreas Koenig <k@otto.ww.TU-Berlin.DE>
#	Tim Bunce <Tim.Bunce@ig.co.uk>
#	Andy Dougherty <doughera@lafcol.lafayette.edu>
#
#  This perl script attempts to make a bootstrap file for use by this
#  system's DynaLoader. It typically gets called from an extension
#  Makefile.
#
# There is no .bs file supplied with the extension. Instead a _BS
# file which has code for the special cases, like posix for berkeley db
# on the NeXT.
# 
# This file will get parsed, and produce a maybe empty
# @Dynaloader::dl_resolve_using array for the current architecture.
# That will be extended by $dynaloadlibs, which was computed by Andy's
# extliblist script. If this array still is empty, we do nothing, else
# we write a .bs file with an @Dynaloader::dl_resolve_using array, but
# without any `if's, because there is no longer a need to deal with
# special cases.
# 
# The _BS file can put some code into the generated .bs file by placing
# it in $bscode. This is a handy 'escape' mechanism that may prove
# useful in complex situations.
# 
# If @DynaLoader::dl_resolve_using contains -L* or -l* entries then
# mkbootstrap will automatically add a dl_findfile() call to the
# generated .bs file.
#
    my($self, @dynaloadlibs)=@_;
    print STDERR "	dynaloadlibs=@dynaloadlibs" if $Verbose;

    &initialize unless defined $att{BOOTSTRAP};

    my($osname) = $Config{'osname'};
    $bscode="";

    rename "$att{BASEEXT}.bs", "$att{BASEEXT}.bso";

    if (-f "$att{BASEEXT}_BS"){
	unshift @INC, ".";
	$_ = "$att{BASEEXT}_BS";
	package DynaLoader; # execute code as if in DynaLoader
	require $_;
    }

    my(@all) = (@dynaloadlibs, @DynaLoader::dl_resolve_using);
    my($method) = '';
    if (@all){
	open BS, ">$att{BASEEXT}.bs"
		or die "Unable to open $att{BASEEXT}.bs: $!";
	print STDOUT "Writing $att{BASEEXT}.bs";
	print STDOUT "	containing: @all" if $Verbose;
	print BS "# $att{BASEEXT} DynaLoader bootstrap file for $osname architecture.\n";
	print BS "# Do not edit this file, changes will be lost.";
	print BS "# This file was automatically generated by the";
	print BS "# mkbootstrap routine in ExtUtils/MakeMaker.pm.\n";
	print BS "\@DynaLoader::dl_resolve_using = ";
	if (" @all" =~ m/ -[lL]/){
	    print BS "  dl_findfile(qw(\n  @all\n  ));\n";
	}else{
	    print BS "  qw(@all);\n";
	}
	# write extra code if *_BS says so
	print BS $DynaLoader::bscode if $DynaLoader::bscode;
	print BS "1;\n";
	close BS;
    }
}

1;
