#!/usr/bin/perl -I/usr/local/lib/autoperl  -w

# -*-CPerl-*- 
#
# Autoperl - a portable build system for Perl applications
#
# Copyright 2003-2004 by Mark Heily <devel@heily.com>
#
# This library is free software; you can redistribute it and/or modify it 
# under the same terms as Perl itself.

use English;
use Data::Dumper;
use File::Copy;
use strict;
use warnings;

use subs qw( vprint );

# Generated by autoperl
unless (defined $ap::CONFIG_H) {

$ap::CONFIG_H = 1;
%ap::config = (
                '' => 1,
                'docdir' => '/usr/local/share/doc/autoperl',
                'mandir' => '/usr/local/man',
                'pkgdatadir' => '/usr/local/share/autoperl',
                'author' => 'Mark Heily <devel@heily.com>',
                'program' => 'autoperl',
                'infodir' => '/usr/local/info',
                'sysconfdir' => 'etc',
                'htmldir' => 'var/www',
                'bindir' => '/usr/local/bin',
                'confdir' => '/etc/autoperl',
                'libexecdir' => '/usr/local/libexec',
                'localedir' => '/usr/local/locale',
                'version' => '0.9.4',
                'cgidir' => 'usr/lib/cgi-bin',
                'includedir' => '/usr/local/lib/site_perl',
                'statedir' => '/var/lib/autoperl',
                'datadir' => '/usr/local/share',
                'sbindir' => '/usr/local/sbin',
                'libdir' => '/usr/local/lib/autoperl',
                'srcdir' => undef,
                'prefix' => '/usr/local'
              );


# Inconvenience hashref
$ap::config = \%ap::config;
}


{
#============================================================================
# Imported from Autoperl.pm by Autoperl
# -*-CPerl-*- 
#
# Autoperl - a portable build system for Perl applications
#
# Copyright 2003-2004 by Mark Heily <devel@heily.com>
#
# This library is free software; you can redistribute it and/or modify it 
# under the same terms as Perl itself.
#

package Autoperl;

use strict;
use warnings;
use Carp;
use POSIX;
use Data::Dumper;
use English;
use Sys::Hostname;
use Cwd 'abs_path';     # aka realpath()

# Generated by autoperl
unless (defined $ap::CONFIG_H) {

$ap::CONFIG_H = 1;
%ap::config = (
                '' => 1,
                'docdir' => '/usr/local/share/doc/autoperl',
                'mandir' => '/usr/local/man',
                'pkgdatadir' => '/usr/local/share/autoperl',
                'author' => 'Mark Heily <devel@heily.com>',
                'program' => 'autoperl',
                'infodir' => '/usr/local/info',
                'sysconfdir' => 'etc',
                'htmldir' => 'var/www',
                'bindir' => '/usr/local/bin',
                'confdir' => '/etc/autoperl',
                'libexecdir' => '/usr/local/libexec',
                'localedir' => '/usr/local/locale',
                'version' => '0.9.4',
                'cgidir' => 'usr/lib/cgi-bin',
                'includedir' => '/usr/local/lib/site_perl',
                'statedir' => '/var/lib/autoperl',
                'datadir' => '/usr/local/share',
                'sbindir' => '/usr/local/sbin',
                'libdir' => '/usr/local/lib/autoperl',
                'srcdir' => undef,
                'prefix' => '/usr/local'
              );


# Inconvenience hashref
$ap::config = \%ap::config;
}


use constant DEBUG => 0;

use constant INSTALL_PATHS => qw( prefix
				  bindir
			          sbindir
			          libexecdir
				  datadir
				  includedir
				  pkgdatadir
			          mandir
			          infodir
				  confdir
				  libdir
				  docdir
		       	          localedir
				  statedir
				  srcdir
				  sysconfdir
				  htmldir
				  cgidir
			        );


#################################################################
#
#			System Tests
#
#################################################################


#
# check_host()
#
#    Determine the host operating system and architecture
#
sub check_host($)
  {
    my $self = shift;

    return if $self->{sys}->{uname};
    print "Determining operating system type... ";
    my $uname_bin = '/bin/uname';
    $uname_bin = '/usr/bin/uname' unless ( -e $uname_bin );
    die unless ( -e $uname_bin );

    chomp ( my $uname = `$uname_bin` );
    chomp ( my $arch = `$uname_bin -m` );

    my $host = "$arch-$uname";

    $self->{sys}->{hostname} = hostname;
    $self->{sys}->{hostname} =~ s/\..*//;

    $self->{sys}->{uname} = $uname;
    chomp ( $self->{sys}->{release} = `$uname_bin -r` );
    $self->{sys}->{arch} = $arch;
    $self->{sys}->{host} = $host;

    #fixme - not GNU compatible
    my $hoststr = "$arch-$uname-" . $self->{sys}->{release};
    $hoststr =~ tr/[A-Z]/[a-z]/;
    print "$hoststr\n";
    return $host;
  }


#
# check_bin()
#
#   Check for the availability of an executable by searching the $PATH
#
sub check_bin 
  {
	my $ap = shift;

# Macro: AC_CHECK_PROG (VARIABLE, PROG-TO-CHECK-FOR, VALUE-IF-FOUND,
#          [VALUE-IF-NOT-FOUND], [PATH], [REJECT])

    my ($var,$bin,$if_found) = @_;

    local $ENV{PATH} .= ":/sbin:/usr/sbin:/usr/local/sbin";

    $bin =~ s/[^A-Za-z0-9.\-]//g;
    print "checking for $bin.. ";
    chomp ( my $result = `/usr/bin/which $bin` ) ;
    print  $result ? "yes" : "no", "\n";
    $ap->{mk}->{custom_args}->{$var} = $result ? 1 : 0;

  }


#
# check_lib() - Determine the availability of a Perl library
#
sub check_lib($$$)
  {
    my ($self,$lib,$flags) = @_;
    my $result = 0;
    my $silent = 1;
    my ($answer, $pathname);

    # Return a cached result
    return $self->{_depends}->{$lib}
      if defined $self->{_depends}->{$lib};

    # Get the path name (Foo::Bar becomes Foo/Bar.pm)
    $pathname = $lib;
    $pathname =~ s/::/\//g;
    $pathname .= '.pm';

    # Only print messages for non-pragmas
    if ( $lib =~ /^[A-Z]/ ) { $silent = 0; }

    if ( not $silent ) {
      print "checking for $lib" . ($flags->{version} ? " ".$flags->{version} : "" ) . ".. ";
    }

    # Try to load the library
    eval "use $lib qw()";
    my $errmsg = $@;

    # Check the error message
    if ( $errmsg =~ /^Can\'t locate / ) {
      $answer = "no";
    } elsif ($errmsg) {
      $errmsg =~ s/\n.*//s;
      $answer = "error, see below:\n" . 
      		 "-"x78 . "\n$errmsg\n" . "-"x78 . "\n";
    } else {
      $answer = "yes";
    }
    $result = ! $errmsg;

    ## Perform version checking
    if ( $flags->{version} ) {
      eval "\$result &&= ( \$".$lib."::VERSION $flags->{version} )";
    }

    ## Build a static library, if available
    my $static;
    $static = `find ./lib 2>/dev/null | grep $pathname` if -e './lib';
    if ( $static and ( not $result or $self->{static} ) ) {
       chomp $static;
       $static =~ m|./lib/.*?/|;
       my $libpath = $&;
       $answer = "yes (in $libpath)";
       
       push @{ $self->{_static_libs}},$libpath
       	unless grep /^$libpath$/, @{ $self->{_static_libs}};
       $result = 1;
    }
       
    print "$answer\n" unless $silent;

    $self->{_depends}->{$lib} = $result;
    return $result;
  }

##########################################################
#
#            BUILD UTILITIES
#
#########################################################

# &get_options()
#
# Read ./configure options from the command line
#
sub get_options($@)
  {
    my $ap = shift;
    # Process overrides
    while (@_) {
      my $key = shift;
      my $val = shift;
      $key =~ s/^-//;
      $ap->{$key} = $val;
    }

    $ap->check_host();
    $ap->check_argv();

  }


# &show_help()
#
# Print the ./configure usage message
#
sub show_help($)
  {
    my $ap = shift;
    my $program = $ap->{program} || "the program";
    my $mk = $ap->{mk};

    print <<__HELP__
Usage: ./configure [OPTIONS]...

Configuration:
  -h, --help             display this help and exit
  -v, --verbose		 be more verbose
  -vv, --very-verbose	 be very verbose

Installation directories:
  --prefix=DIR           use this prefix for installing $program [/usr/local]
  --bindir=DIR           use this prefix for installing $program binary
                         [PREFIX/bin]
  --confdir=DIR          use this prefix for installing configuration files
                         [PREFIX/etc/$program]
  --sysconfdir=DIR       use this prefix for installing system configuration
                         files [PREFIX/etc]
  --datadir=DIR          use this prefix for installing machine independent
                         data files [PREFIX/share]
  --includedir=DIR       public Perl header files [PREFIX/include]
  --libdir=DIR           use this prefix for private libraries [PREFIX/lib]
  --mandir=DIR           use this prefix for installing manpages [PREFIX/man]
  --pkgdatadir=DIR       use this for package-specific machine independent
                         data files [DATADIR/program-name]
  --htmldir=DIR		 use this prefix for publishing HTML documents via
                         a web server [/var/www]
  --cgidir=DIR           use this prefix for installing web server CGI 
  			 programs [LIBDIR/cgi-bin]
             
Compilation options:
  --static               do not use any shared system libraries [no]

Optional Features:
  --disable-FEATURE      do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG] include FEATURE [ARG=yes]

Custom options:
__HELP__
      ;

    # Display custom options
    foreach my $name ( keys %{$mk->{help_string}} ) {
      my $val = $mk->{custom_args}->{$name};
      my $desc = $mk->{help_string}->{$name};
      if ( defined $val and $val =~ /^[01]$/ ) {
	$val = ( $val eq '1' ) ? 'yes' : 'no';
      }
      print "  --$name" . ' 'x(21-length($name)) . $desc;
      print ' [' . $val . "]" if defined $val;
      print "\n";
    }
    print "\n";

    exit 0;
  }


# Scan the Makefile parse tree and check dependencies
sub check_all_depends
{
	my $ap = shift;
	my $top = $ap->{mk};

	# Build a queue of Parser objects to process (depth=1)
	my @q = ( $top );
	
	while (@q) {
	   my $mk = shift @q;
	   my $curdir = $mk->{curdir};

	   # Parse all sources and headers
	   foreach my $src ( mk_get_all_sources($mk), 
	  	 	@{$mk->{headers}} ) {
#		$log->info("Marking $_ for dependency checking");
		$ap->check_depends("$curdir/$src");
	   }
	   
	   # If the binaries exist, check them too
	   # (Special case)
	   foreach ( @{$mk->{bin_programs}}, @{$mk->{sbin_programs}}) {
		next unless -e $_;
		#$log->info("Marking $_ for dependency checking");
		$ap->check_depends("$curdir/$_");
	    }   

	   # Add any children to the queue
  	   foreach my $child (keys %{$mk->{child}}) {
		push @q, $mk->{child}->{$child};
	   }
	}
}

sub write_all_makefiles
{
	my ($ap) = @_;
	my $top = $ap->{mk};
	
	# Build a queue of Parser objects to process (depth=1)
	my @q = ( $top );
	
	while (@q) {
	   my $mk = shift @q;
	   
	   # Write the Makefile
	   $ap->write_makefile($mk);

	   # Add any children to the queue
  	   foreach my $child (keys %{$mk->{child}}) {
		push @q, $mk->{child}->{$child};
	   }
	}
}

# WORKAROUND: copied from parser.pm
sub mk_get_all_sources
{
  my $mk = shift ||die;
  my @s;
  
  foreach my $x ( keys %{$mk->{sources}} ) {
     foreach my $y ( @{$mk->{sources}->{$x}} ) {
     	push @s, $y;
     }
  }

  return @s;
}

# &check_recursive_depends(target)
#
# Scans all files within a directory for library dependencies
#
sub check_recursive_depends($$)
{
     my ($ap,$target) = @_;

     die "$target: not a directory" unless -d $target;
     opendir (my $dh, $target) or die "$target: error opening directory";
     while (my $dirent = readdir ($dh)) {
	my $abspath = "$target/$dirent";
	
	
	next if $dirent eq '.' or $dirent eq '..'
		or $dirent =~ m|/\.$| or $dirent =~ m|/\.\.|;
			
	$ap->check_recursive_depends($abspath) if -d $abspath;
	$ap->check_depends($abspath) if $abspath =~ /\.p[lm]/;
     }
     closedir ($dh);
}

# &check_depends(target)
#
# Parse a Perl source file, and check it's dependencies
#
# OR: if given a directory, scan all files within the directory
#
# Returns : True, if all deps found, FALSE if not
#
sub check_depends($$) {
  my ($ap,$target) = @_;
  my $success = 1;
  my $lineno = 0;
  chomp $target; #workaround

  our %_dep_cache;

  return $_dep_cache{$target} if exists $_dep_cache{$target};
  return 1 unless $ap->{dependency_tracking};
  return $ap->check_recursive_depends($target) if -d $target;

  $ap->vprint("scanning $target for library dependencies");
  open (TARGET, "<$target") or $ap->fatal("$target: $!");
  while (<TARGET>) {
    chomp;
    my $line = $_;
    $lineno++;
    last if $line eq '__END__';

    # Trim leading & trailing whitespace
    $line =~ s/^\s*//;
    $line =~ s/\s*$//;
    $line =~ s/#.*//;
    $line =~ s/;.*//;
    $line .= ' ';
    next unless $line =~ /^\s*use [A-Za-z0-9\:\-\_]+/;
    my ($use,$lib,$flags) = split / +/, $line, 3;
    
    
    #XXX-WORKAROUND -FIX PARSER!
    next if $lib eq 'use'; ##XXX workaround for parser error
    next unless $lib =~ /^[A-Za-z0-9\-\_\:]+$/;
    
    $ap->vprint("${target}:${lineno}: checking dependency for $lib");

    # Don't run duplicate tests
    next if defined $ap->{_depends}->{$lib};

    # Don't test for it if the project provides it
    next if grep /^$lib$/, @{$ap->{mk}->{PROVIDES}};
    
    # Test it!
    $success = 0 unless $ap->check_lib($lib, {});
  }
  $_dep_cache{$target} = $success;
  return $success;
}


# &check_argv()
#
# Process the arguments to a ./configure script
#
sub check_argv($)
  {
    my $ap = shift;
    my $mk = $ap->{mk};
    
    my %aliases = ( 
    			'-v' => '--verbose',
    			'-vv' => '--very-verbose',
    		  );
     
    foreach my $arg ( @ARGV ) {
      $arg = $aliases{$arg} if defined $aliases{$arg};

      die "invalid argument '$arg'" unless $arg =~ /^--/;
      $arg =~ s/^--//;
      my ($option, $value);
      if ( $arg =~ /=/ ) {
	($option,$value) = split /=/, $arg;
      } else {
	$option = $arg;
	$value = 1;
      }

      if ( $option =~ /^(without|disable)-(.*)/ ) {
	$option = $2;
	$value = 0;
      }
      if ( $option =~ /^(with|enable)-(.*)/ ) {
	$option = $2;
	$value = 1;
      }

      #FIXME-workaround
      if ( $option =~ /^disable_dependency_tracking/ ) {
	  $ap->{dependency_tracking} = 0;
      } 
      elsif ( $option =~ /^(h|help)$/ ) {
	$ap->show_help();
      } 
      elsif ( grep /^$option$/, keys %{$ap} ) {
	$ap->{$option} = $value;
      }
      elsif ( grep /^$option$/, keys %{$mk->{custom_args}} ) {
	$mk->{custom_args}->{$option} = $value;
      }
      else {
	$mk->{custom_args}->{$option} = $value;
      }
    }
    1;
  }


# &finalize()
# 
# Combine prefix and installation path to create the final destination
# for various paths.
#
sub finalize($) {
  my $ap = shift;

  $ap->{pkgdatadir} = $ap->{datadir};

  # Some paths don't have a prefix, but have a suffix
  foreach my $path (qw(pkgdatadir confdir statedir)) {
    $ap->{$path} = '/' . $ap->{$path} . '/' . $ap->{program} . '/';
   }

  # Combine the prefix with the path
  foreach my $path (qw(bindir
		       sbindir
		       libexecdir
		       datadir
		       pkgdatadir
		       mandir
		       infodir
		       localedir
		       )
		   ) {
      $ap->{$path} = $ap->prefix . '/' . $ap->{$path} . '/';
    }

  # Certain paths contain the name of the program (e.g. /etc/myprogram)
  foreach my $path (qw(libdir
		       docdir
		       )
		   ) {
    $ap->{$path} = $ap->prefix . '/' . $ap->{$path} . '/' .  $ap->{program} . '/';
  }

  # Remove any double slashes (//) and trailing slashes in the paths
  foreach my $key (keys %{$ap}) {
	next unless $key =~ /dir$/ or $key =~ /^(prefix)$/;
	$ap->{$key} =~ s|/+|/|g;
	$ap->{$key} =~ s|/$||;
  } 

}

# &write_makefile()
#
# Write the Make and Perl header files
#

sub write_makefile($$) {
    my ($ap,$mk) = @_;
    my $target = $mk->{curdir} . '/Makefile';
    my ($basename,$topdir) = ("","");
    
    # Get basename and topdir
    $target =~ /.*\//;
    $basename = $&;
    $basename = "" unless defined $basename;
    $basename = "" if $basename =~ m|^\./?$|;
    if ($basename) {
    	$topdir = $basename;
	$topdir =~ s/[a-zA-Z0-9\-\_\.]+/\.\./g;
    }
    
    # Symlink config.h into tho target directory
    if ($basename and ! -e "$basename/config.h") {
    	system "ln -s '../config.h' $basename/config.h";
    }

    print "writing $target.. ";
    open ( MKFILE, ">$target" ) or die $!;

    print MKFILE "# Generated by\n#\n#    ./configure --" . join("\n#" . ' 'x16 . '--' ,@ARGV) . "\n#\n";

    foreach my $id ( keys %{ $ap } ) {
	next if ref($ap->{$id});
 	next if $id =~ /^_/;  		# don't print internal structures
	
	my $uc_id = $id;
	$uc_id =~ tr/a-z/A-Z/;
	my $val = $ap->{$id};

	$val = '$$DESTDIR' . $val if $id =~ /dir$/;
	die "null values for $id not permitted" unless defined $val;
	print MKFILE $uc_id . " = $val\n";
      }

print MKFILE "TOPDIR = " . $ap->{topdir}. "\n";
print MKFILE "DISTDIR = ${topdir}\$(PROGRAM)-\$(VERSION)/${basename}\n";

  Autoperl::Generator::write_makefile($mk,*MKFILE);
  close(MKFILE);

  print "done\n";


  }

# &errors()
#
# Return true if threre are unresolved dependencies
#
sub errors {
  my $self = shift;
  return ($self->{_errors} > 0) ? 1 : 0;
}

sub generate_config_h
{
	my $self = shift;

 	# Generate a 'cfg' object to be included in the binary
	my $cfg;
	foreach my $key (INSTALL_PATHS, qw(program author version)) {
	    $cfg->{$key} = $self->{$key};
	}
	foreach my $key (keys %{$self->{mk}->{custom_args}}) {
	    $cfg->{$key} = $self->{mk}->{custom_args}->{$key};
	    $cfg->{$key} = 1 unless defined $cfg->{$key}
	}

	open (FH, ">config.h") or die "config.h: $!";
	print FH "# Generated by autoperl\n";
        print FH "unless (defined \$ap::CONFIG_H) {\n";
        print FH "\n\$ap::CONFIG_H = 1;\n";
	print FH Data::Dumper->Dump([$cfg],["*ap::config"]);
	
        #FIXME: This creates problems when require()d multiple times
        #print FH "\n# Accessor methods\n\n";
	#print FH "eval {\n";
        #foreach my $key (keys %{$cfg}) { 
	#   my $val = $cfg->{$key};
	#   $val = '' unless defined $val;
	#   print FH "sub ap::$key { '$val' }\n";
	#} 
	#print FH "};\n";
        print FH "\n\n# Inconvenience hashref\n";
	print FH '$ap::config = \%ap::config;' . "\n";

        print FH "}\n";
	print FH "\n1;\n";
	close (FH);
}


# &new
#
# Create a new Autoperl object
#
sub new
  {
    my $class = shift;
    my $ap = bless {

    		 # Permanent properties (TODO-Make project file i.e. metaconf)
		 program => 'undefined-program',
		 author => 'Undefined-author',
		 version => 0.01,

		 # Installation paths
		 prefix => '/usr/local',
		 bindir => 'bin',
		 sbindir => 'sbin',
		 libexecdir => 'libexec',
		 datadir => 'share',
		 mandir => 'man',
		 includedir => '/usr/local/lib/site_perl',
		 infodir => 'info',
		 confdir => 'etc',
		 sysconfdir => 'etc',
		 libdir => 'lib',
		 docdir => 'share/doc',
		 localedir => 'locale',
		 statedir => 'var/lib',
		 htmldir => 'var/www',
		 cgidir => 'usr/lib/cgi-bin',

		 # Build flags
		 static => 0,
		 verbose => 0,
		 dependency_tracking => 1,

		 # Internal structures
		 mk => new Autoperl::Parser(),
		 custom_args => +{},
		 topdir => abs_path(getcwd),
		 sys => +{},
		 _sources => [],
		 _dirs => [],
		 _errors => 0,
		 _depends => +{ Autoperl => 1, },
		 _static_libs => [],
		 _ignore_libs => [],
		}, $class;
    return $ap;
  }

sub DESTROY {1;}

# &finished()
#
# Signal the end of the autoperl configure script and write the
# output, if successful.
#
sub configure($) {
  my $self = shift;

  $self->get_options();

  $self->check_all_depends();

  # Missing dependencies?
  my @missing;
  foreach my $lib ( keys %{$self->{_depends}} ) {
     next if grep /^$lib$/, @{$self->{_ignore_libs}};
     my $valid = $self->{_depends}->{$lib};
     push @missing, $lib unless $valid;
  }
  if ( @missing and $self->{dependency_tracking}) {
     print "\nThe following libraries were not found:\n\t" . 
     	join ("\n\t", @missing) . "\n\n";
     $self->quit('aborting due to missing or broken dependencies.');
  }

  $self->fatal() if $self->errors; 
  unlink "build-stamp";
 
  $self->finalize();

  print "creating config.h..\n";
  $self->generate_config_h();  
  
  $self->write_all_makefiles();
}

# quit(msg)
# 
#  Abort processing due to a normal error
#
sub quit($$) {
   my ($self,$msg) = @_;
   print "./configure: $msg\n";
   print Dumper($self) if DEBUG;
   POSIX::_exit(1);
}

# fatal(msg)
# 
# Throw a fatal exception with stack backtrace
#
sub fatal($$) {
   print "./configure: caught fatal exception: $_[1]\n";
   open (CORE, ">configure.core") or die $!;
   print CORE $_[1] . "\n\n" . Dumper($_[0]) . Carp::longmess;
   close CORE;
   POSIX::_exit(255);
}

# vprint(msg)
# vvprint(msg)
#
# Print a verbose message
# Print a very verbose message
#
sub vprint($$) { print $_[1] . "\n" if $_[0]->verbose; }
sub vvprint($$) { print $_[1] . "\n" if $_[0]->very_verbose; }

# AUTOLOAD()
#
# Allow %ap keys to be accessed via accessor methods
#
sub AUTOLOAD {
  use vars qw($AUTOLOAD);
  my $ap = shift;
  my $key = $AUTOLOAD;
  $key =~ s/.*:://;
  if ( defined $ap->{$key} ) { return $ap->{$key} }
  confess "unknown method or attribute '$key'";
}

1;
#============================================================================
}
{
#============================================================================
# Imported from Autoperl/Parser.pm by Autoperl
# parser.pm
#
# Functions that parse configuration files
#
package Autoperl::Parser;
use strict;
use warnings;
use Carp;
use Data::Dumper;

use subs qw(raise);

sub parse_all
{
	my $mk = shift || confess;  

	$mk->parse_makefile_am('Makefile');
	$mk->parse_package_in();
}

sub raise { 
	print "autoperl: ERROR: " . join("\n",@_) . "\n"; 
	confess() if 0;#TODO:verbosity
	exit(255);
	}
	

sub init_manifest
{
        my $project = +{
               compat => 1,
               name => undef,
               version => undef,
               author => undef,
	       title => undef,
               synopsis => undef,
               description => undef,
               category => undef,
               license => undef,
               project_uri => undef,
               source_uri => undef,
               vuxml_uri => undef,
               build_depends => [],
               build_optional => [],
               build_architectures => [],
               runtime_depends => [],
               library_depends => [],
               depends => [],
               suggests => [],
               replaces => [],
               };
   return $project;
}

sub new
{
	my $class = shift;
	my $parent = shift;

	# Variables defined in Makefile.am
	my $self = +{

                # Global variables from configure.in
                # TODO- reorganize this crap
                program => 'my-program',
                version => '0.1',
                author => 'Anonymous <nobody@nowhere.com>',

		# The current directory, relative to the project root
		curdir => '.',
		
		# Pointer to the parent and the top-level parser object
		# Pointer to child Makefile.am's defined in SUBDIRS
		parent => undef,
		top => undef,
		child => +{},
		
		# A list of Perl package names and/or binaries that this 
		# program provides.
		# Indexed by packagename -> filename
		provides => +{},

		# Program files to be compiled, and their sources
		bin_programs => [],
		sbin_programs => [],
		sources => +{},

		# Headers to install publicly in $(includedir)
		headers => [],
			     
		subdirs => [],
		extra_dist => [],
		manpages => +{},
		pkgdata => [],
		pkgdocs => [],
		makefiles => [],

		# All user-defined Makefile targets
		targets => +{},

		# Most system and user-defined variables
		vars => +{
			AUTOPERL => '$(TOPDIR)/configure --autoperl',
			INSTALL => '$(AUTOPERL) install -p',
			MAKE => '/usr/bin/make',
			PERL => '/usr/bin/perl',
			CC => '/usr/bin/perl -c',
 			LD => '$(AUTOPERL) link', 
			},
	
		# User-defined ./configure --help strings
		custom_arg => +{}, 
		help_string => +{},

                # User-defined hooks
                hooks => [],

                # Package manifest
                manifest => undef,
		};
		
	if (defined $parent) {
		$self->{parent} = $parent;
		$self->{top} = $parent->{top};
                $self->{manifest} = $parent->{top}->{manifest};
	} else {
		$self->{top} = $self;

		# Top-level objects have special concatenated variables
		# so code does not have to be recursive
		$self->{PROVIDES} = [];
	}

	bless $self, $class;
	return $self;
}


sub parse_makefile_am($$)
{
my ($mk,$input) = @_;
$input .= '.am';

raise "$input not found" unless -e $input;

# Get the current directory
$input =~ /(.*)\//;
my $curdir = $1;;
$curdir = '.' unless defined $curdir;
$curdir =~ s|^\./||;
$mk->{curdir} = $curdir;

# Parse the 'aplocal.inc' file, if it exists
$mk->parse_aplocal_inc("$curdir/aplocal.inc"); 

my $lineno = 0;
my $cur_target;
my $line;
open ( my $infile, "<./$input") or raise "$input: $!";
while (<$infile>) {
  $lineno++;
  chomp;
  $line .= $_;
  
  # Import Make-style targets
  if ($line =~ /^([a-zA-Z\-\_]+?)\:\s*(.*)/) {
  	$cur_target = $1;
	my $depends = $2;
	$mk->{targets}->{$cur_target} = +{ 
			depends => defined $depends ? $depends : '',
			lines => [],
			};
	$line = "";
 	next;
  }
  if ($line =~ /^\t/) {
	push @{$mk->{targets}->{$cur_target}->{lines}}, $line;
	$line = "";
	next;
  }

  # Ignore comments and blank lines
  $line =~ s/#.*//;
  next if $line =~ /^\s*$/;
  next unless $line;
  
  # A line that ends with a backslash (\) is continuation line
  if ($line =~ /\\$/) {
  	chop $line;
#	chop $line;
	next;
  } 

  # This section parses variable definitions (X=Y)
  my ($token, $value);
  if ($line =~ /^\s*([A-Za-z0-9\-\_]+)\s*=\s*(.*)\s*$/) {
     ($token, $value) = ($1,$2);
  }

  # Some tokens are special
  if (grep /^$token$/, qw( PROGRAM VERSION AUTHOR )) {
	$mk->{top}->{lc $token} = $value;
  } elsif ($token =~ /_ARG$/) {
  	my $arg = $`;
	$arg =~ tr/_/-/;
	$mk->{top}->{custom_arg}->{$arg} = $value;
  } elsif ($token =~ /_ARG_HELP$/) {
  	my $arg = $`;
	$arg =~ tr/_/-/;
	$mk->{top}->{help_string}->{$arg} = $value;
  } elsif ($token =~ /(.*)_SOURCES/) {
  	my $binary = "$1.pl";
	my @src = split /\s+/, $value;
	@{$mk->{sources}->{$binary}} = @src;
	foreach my $srcfile (@src) {
		my $pkgname = $mk->get_package_from_source($srcfile);
		next unless $pkgname;
		$mk->{provides}->{$pkgname} = $srcfile;
		push @{$mk->{top}->{PROVIDES}}, $pkgname;
	}
  } elsif ($token eq 'SUBDIRS') {
  	$mk->{subdirs} = [ split /\s+/, $value ];

	# FIXME-
	#
	# Each SUBDIR should have it's Makefile generated
	# This doesn't play nice with non-Autoperl makefiles :(
	# We should really fix the autoperl --init generation
	# the AC_CONFIG_FILES macro. That would introduce another
	# problem: what happens when you add a directory after running
	# --init; the user would need to edit configure.in.
	# 
	# For now this is OK.
	#
	foreach my $subdir (@{$mk->{subdirs}}) {
		my $input = $curdir . '/' . $subdir . '/Makefile';
		push @{$mk->{makefiles}}, $input;
		
	# RECURSION:
	#
	# Create a new Parser object and parse each Makefile.am
	# under SUBDIRS, storing in $child
		my $submk = new Autoperl::Parser($mk);
		$submk->parse_makefile_am($input);
		$mk->{child}->{$input} = $submk;
	}
	
	
  } elsif ($token =~ /(dist_)?(man[0-9])_MANS/) {
  	my ($section,$files) = ( $2, $value);
	@{$mk->{manpages}->{$section}} = split /\s+/, $files;
  } elsif ($token =~ /(dist_)pkgdata_DOCS/) {
  	$mk->{pkgdocs} = [ split /\s+/, $value ];
  } elsif ($token =~ /(dist_)pkgdata_DATA/) {
  	$mk->{pkgdata} = [ split /\s+/, $value ];
  } elsif ($token =~ /EXTRA_DIST/) {
  	$mk->{extra_dist} = [ split /\s+/, $value ];
  } elsif ($token =~ /s?bin_(PROGRAMS|SCRIPTS)/) {
	$mk->{lc $token} = [ split /\s+/, $value ];
  } elsif ($token =~ /include_HEADERS/) {
	my @hdr = split /\s+/, $value;
	@{$mk->{headers}} = @hdr;
	foreach my $srcfile (@hdr) {
		my $pkgname = $mk->get_package_from_source($srcfile);
		next unless $pkgname;
		$mk->{provides}->{$pkgname} = $srcfile;
		push @{$mk->{top}->{PROVIDES}}, $pkgname;
	}
  } elsif (defined $token and defined $value) {
	$mk->{vars}->{$token} = $value;
  } else {
  warn "line:\n`$line'\ntoken = `$token'\nvalue = `$value'";
  raise "Makefile.am:$lineno: parse error";
  }
  $line = "";
}
close($infile);
}


sub parse_aplocal_inc 
{
	my ($mk,$input) = @_;
	return unless -e $input;

	# Read the entire file
	open( my $infile, "<$input") or die "$input: $!";
	my @lines = <$infile>;
	close($infile);

	# Find the 'hook' functions
	my @valid_hooks = qw( configure make_all make_install
			      make_dist make_uninstall make_package
                              make_clean
                            );
	foreach (grep( /^\s*sub /, @lines )) {
	   /sub ([A-Za-z0-9_]+)/;
	   my $sub = $1;
	   next unless $sub =~ /^(pre|post)_(.*?)_hook/;
	   my $hook = $2;
	   die 'invalid hook: ' . $sub 
		unless grep /^$hook$/, @valid_hooks;
           push @{$mk->{hooks}}, "$1_$hook";
	}
}


# Parse package information file
#
sub parse_package_in
{
  my $self = shift;
  my %r;

  return unless -e 'package.in';

  # Define the grammar
  my @multiline = qw( Description 
		    );
  my @array = qw( Requires 
		);

  my @scalar = qw( Package Title License
                   Project-URI Source-URI VuXML-URI 
		 );

  # Grab the whole file
  open(my $infile, "<package.in") or die "package.in: $!";
  my @lines = <$infile>;
  close($infile);
 
  # Parse it
  my $pkg = "";
  my $key = "";
  my $value = "";
  for (my $i = 0; $i <= $#lines; $i++) {
	my $line = $lines[$i];
	$line =~ s/\#.*//;
	next unless $line =~ /\w/ or 
	   (defined $key and grep /^$key$/, @multiline);

        if ($line =~ /^([A-Za-z\-\_]+)\:\s*(.*)$/) {
	     $key = $1;
	     $value = $2;
	     $pkg = $value if $key eq 'Package';
 	     $pkg =~ s/^\s*//;
	     $value =~ s/\s*$//;
	} else {
	     $value = $line;
	}

	die 'package.in: must declare "Package" before other variables'
	    if $key and not $pkg;

	die 'package.in: '.$i.': parser error' unless $key;
	
        $r{$pkg} = +{} unless defined $r{$pkg};

        if (grep /^$key$/, @multiline) {
            $r{$pkg}->{$key} = "" unless defined $r{$pkg}->{$key};
            $r{$pkg}->{$key} .= $value;
        } elsif (grep /^$key$/, @scalar) {
	    $value =~ s/^\s*//;
	    $value =~ s/\s*$//;
	    die 'package.in: '.$i.': '.$key.' cannot be redefined'
		if exists $r{$pkg}->{$key};
            $r{$pkg}->{$key} = $value;
        } elsif (grep /^$key$/, @array) {
	    $value =~ s/^\s*//;
	    $value =~ s/\s*$//;
	    my @subvalues = split /\s+/, $value;
            $r{$pkg}->{$key} = [] unless defined $r{$pkg}->{$key};
	    push @{$r{$pkg}->{$key}}, @subvalues;
	} else {
	    die 'package.in: '.$i.': unknown variable "'.$key.'"';
	}
  }
  $self->{packager} = \%r;
  bless $self->{packager}, "Autoperl::Packager";
  return \%r;
}


# get_package_from_source(src)
#
# Parse a source code file and return the package name
# based first occurance of 'package <foo>'
#
# NOTE: This cant handle multiple packages inside the same file.
# 
sub get_package_from_source($$)
{
	my ($self,$src) = @_;
	my $result = "";
	
	$src = $self->{curdir} . '/' . $src;

	open( my $infile, "<$src") or die "get_package_from_source(): $src: $!";
	while (<$infile>) {
		next unless /^\s*package ([A-Za-z0-9\:\_]+)\;/;
		$result = $1;
		last;
	}
	close($infile);
	return $result;
}

		
############ Flattening routines

sub get_all_vars($)
{
	my $self = shift;

	my $s = "";
	
	foreach my $key (keys %{$self->{vars}}) {
		$s .= $key . ' := ' . $self->{vars}->{$key} . "\n";
	}
	return $s;
}

# KLUDGE - flatten the $mk->{'sources'} key 
# 		into a list of all source code files
# 
sub get_all_sources
{
  my $mk = shift ||die;
  my @s;
  
  foreach my $x ( keys %{$mk->{sources}} ) {
     foreach my $y ( @{$mk->{sources}->{$x}} ) {
     	push @s, $y;
     }
  }

  return @s;
}

sub get_all_binaries
{
  my $mk = shift ||die;
  my @s;
  
  foreach (@{$mk->{bin_programs}}) { push @s, $_ }
  foreach (@{$mk->{sbin_programs}}) { push @s, $_ }
  foreach (@{$mk->{bin_scripts}}) { push @s, $_ }
  foreach (@{$mk->{sbin_scripts}}) { push @s, $_ }
  
  return join(' ',@s);
}

sub get_all_manpages
{
  my $mk = shift||die;
  
  my @m;
  
foreach my $section (keys %{$mk->{manpages}}) {
	foreach my $manpage (@{$mk->{manpages}->{$section}}) {
		push @m, $manpage;
	}
	}
return @m;
}

sub get_all_makefiles($)
{
	my $mk = shift;

	return ( unique(@{$mk->{makefiles}}) );
}

sub dump($)
{
 	return "\n\nAutoperl::Parser dump follows:\n" . Dumper($_[0]);
}

#------------------ Utility Functions -------------------------

# unique(@foo)
#
# Given a list @foo, make a copy, remove any duplicate elements,
# and return a list containing unique items.
#
sub unique
{
	my %saw;
	my @out = grep(!$saw{$_}++, @_);

	return ( @out );
}


# file_exists(@in)
#
# Give a list of files (@in), check if each file exists.
# die()s if not.
# 
sub check_file_exists
{
  foreach my $fn (@_) {
  	die "$fn: no such file or directory" unless -e $fn;
  }
  1;
}


1;
#============================================================================
}
{
#============================================================================
# Imported from Autoperl/Generator.pm by Autoperl
# generator.pm
#
# Functions that generate datafiles
#
package Autoperl::Generator;

use strict;
use warnings;
use English;
use Data::Dumper;

# KLDUGE: Autoperl::write_makefile calls this with an open file descriptor
# to the current Makefile
#
sub write_makefile
{
my $mk = shift;
*MOUT = shift;
my $curdir = $mk->{curdir};
my $basename = $curdir;

# Get the output name
my $output = $curdir . '/Makefile.in';

# Generate all variable definitions
my $subdirs = join(' ',@{$mk->{subdirs}}); 
print MOUT "SUBDIRS = $subdirs\n" if $subdirs;
if ($mk->get_all_vars()) {
	#print MOUT "\n\n#---- User defined variables ----\n\n";
	print MOUT $mk->get_all_vars() . "\n";
}
print MOUT "APLOCAL = \$(PERL) -e 'do \"config.h\"; do \"aplocal.inc\";' -e \n";


# ----------- BEGIN targets -------------

my @recursive_targets = qw(all install dist clean test uninstall);

print MOUT "\ndefault: all\n\n";

# Declare 'phony' targets
print MOUT "\n.PHONY : package ";
print MOUT "\$(SUBDIRS) " if $subdirs;
print MOUT join(' ', @recursive_targets);
print MOUT "\n\n";

# FIXME-fugly
# Generate some recursive targets
if ($subdirs) {
foreach my $target (@recursive_targets) {
print MOUT "recursive-$target:\n";
foreach my $subdir (@{$mk->{subdirs}}) {
	print MOUT "\tcd $subdir && \$(MAKE) $target && cd ..\n";
 	}
print MOUT "\n";
	}
}

# Generate the 'make all' target
unless ( exists $mk->{targets}->{'all-local'} ) {
print MOUT "all: ".($subdirs ? 'recursive-all' : '') . "\n";
print MOUT "\t\$(APLOCAL) pre_make_all_hook\n" 
   if grep /pre_make_all/, @{$mk->{hooks}};

# Emulate the compilation stage by validating syntax
#
# FIXME-XXX this fails when packages import symbols from 
# other parts of the project tree and don't qualify their use.
# 
# MakeMaker builds a 'blib/' tree and runs compilation checks
# from blib/ so that use() statements work.
#
# See the kolab-perl source tree for example of module interdepency
#
#my @sources =  ( $mk->get_all_sources(), @{$mk->{headers}} );
#foreach my $src (@sources) { 
#	next unless $src;
#	print MOUT "\t\$(CC) $src\n" 
#}

# Compress all manpages
foreach my $manpage ($mk->get_all_manpages()) {
	print MOUT "\tgzip -c $manpage > ${manpage}.gz\n";
}

# Emulate the linker stage by merging source code files
foreach my $src ( keys %{$mk->{sources}} ) {
	my @objs = @{$mk->{sources}->{$src}};
	my $obj = ' ' . join(' ', @{$mk->{sources}->{$src}}) . ' ';
	my $bin = $src; 
	$bin =~ s/\.pl$//;

	# Basic support for C programs
	if ( $obj =~ /\.c / ) {
		$obj =~ s/ (.*?)\.h / /g;
		print MOUT "\tgcc -o $bin";
		foreach (@objs) { print MOUT " $_" if /\.c$/ }
		print MOUT "\n";
	} else {
		print MOUT "\t\$(LD) -o $bin $obj\n";
	}
}
print MOUT "\t\$(APLOCAL) post_make_all_hook\n" 
	if grep /post_make_all/, @{$mk->{hooks}};
print MOUT "\n";
}

# Generate the targets for SUBDIRs
foreach my $subdir (@{$mk->{subdirs}}) {
	print MOUT "$subdir:\n";
	print MOUT "\tcd $subdir && \$(MAKE) && cd ..\n";
	print MOUT "\n";
}

# Generate the 'make install' target
print MOUT "install: ".($subdirs ? 'recursive-install' : '') . "\n";
print MOUT "\t\$(APLOCAL) pre_make_install_hook\n" 
	if grep /pre_make_install/, @{$mk->{hooks}};

my $abspath = +{
		'$(BINDIR)' => $mk->{bin_programs},
		'$(SBINDIR)' => $mk->{sbin_programs},
		};
foreach my $base (keys %{$abspath}) { 
	foreach my $src ( @{$abspath->{$base}} ) {
		my $dest = $src;
		$dest =~ s/\.pl$//;
		$dest = $base.'/' . $dest;
		print MOUT "\t\$(INSTALL) -m 755 $src $dest\n";
	}
    }

# Install all modules that the sources depend on
foreach my $src ( keys %{$mk->{sources}} ) {
        my @objs = @{$mk->{sources}->{$src}};
	foreach my $obj (@objs) {
		next unless $obj =~ /\.pm$/;
		my $pkg_path = $mk->get_package_from_source($obj);
		$pkg_path =~ s/::/\//g;
		my $dest = "\$(LIBDIR)/$pkg_path.pm";
                print MOUT "\t\$(INSTALL) -m 755 $obj $dest\n";
        }
}

foreach my $script (@{$mk->{bin_scripts}}) {
	print MOUT "\t\$(INSTALL) -m 755 $script \$(BINDIR)\n";
}
foreach my $script (@{$mk->{sbin_scripts}}) {
	print MOUT "\t\$(INSTALL) -m 755 $script \$(SBINDIR)\n";
}

if (exists $mk->{targets}->{'install-exec-hook'}) {
	print MOUT "\tmake install-exec-hook\n";
}
foreach my $manpage ($mk->get_all_manpages()) { 
	$manpage =~ /\.([0-9])$/;
	my $section = $1;
 	print MOUT "\t\$(INSTALL) -m 644 ${manpage}.gz " .
		   "\$(MANDIR)/man${section}/${manpage}.gz\n";
}
foreach my $pkgdata (@{$mk->{pkgdata}}) {
	print MOUT "\t\$(INSTALL) $pkgdata \$(PKGDATADIR)/$pkgdata\n";
}
foreach my $pkgdoc (@{$mk->{pkgdocs}}) {
	print MOUT "\t\$(INSTALL) $pkgdoc \$(DOCDIR)/$pkgdoc\n";
}
if (exists $mk->{targets}->{'install-data-hook'}) {
	print MOUT "\tmake install-data-hook\n";
}

# Install headers into $(includedir)
print MOUT "\t\$(INSTALL) -d \$(INCLUDEDIR)\n" if (@{$mk->{headers}}); 
foreach my $header (@{$mk->{headers}}) {
	my $pkg_path = $mk->get_package_from_source($header)
		or die 'error';
	$pkg_path =~ s/::/\//g;
	my $dest = "\$(INCLUDEDIR)/$pkg_path.pm";
	print MOUT "\t\$(INSTALL) -m 644 $header $dest\n";
}

print MOUT "\t\$(APLOCAL) post_make_install_hook\n" 
	if grep /post_make_install/, @{$mk->{hooks}};

print MOUT "\n";

#-------------------------------------
# Generate the 'make uninstall' target
#-------------------------------------

print MOUT "uninstall: ".($subdirs ? 'recursive-uninstall' : '') . "\n";
print MOUT "\t\$(APLOCAL) pre_make_uninstall_hook\n" 
	if grep /pre_make_uninstall/, @{$mk->{hooks}};

# Note: $abspath is defined in the 'install' target
foreach my $base (keys %{$abspath}) {
        foreach my $src ( @{$abspath->{$base}} ) {
                my $dest = $src;
                $dest =~ s/\.pl$//;
                $dest = $base.'/' . $dest;
                print MOUT "\trm $dest\n";
        }
    }

# Uninstall all modules that the sources depend on
foreach my $src ( keys %{$mk->{sources}} ) {
        my @objs = @{$mk->{sources}->{$src}};
        foreach my $obj (@objs) {
                next unless $obj =~ /\.pm$/;
                my $pkg_path = $mk->get_package_from_source($obj);
                $pkg_path =~ s/::/\//g;
                my $dest = "\$(LIBDIR)/$pkg_path.pm";
                print MOUT "\trm $dest\n";
        }
}

foreach my $script (@{$mk->{bin_scripts}}) {
        print MOUT "\trm \$(BINDIR)/$script\n";
}

foreach my $script (@{$mk->{sbin_scripts}}) {
        print MOUT "\trm \$(SBINDIR)/$script\n";
}

foreach my $manpage ($mk->get_all_manpages()) {
        $manpage =~ /\.([0-9])$/;
        my $section = $1;
        print MOUT "\trm \$(MANDIR)/man${section}/${manpage}.gz\n";
}

foreach my $pkgdata (@{$mk->{pkgdata}}) {
        print MOUT "\trm \$(PKGDATADIR)/$pkgdata\n";
}
foreach my $pkgdoc (@{$mk->{pkgdocs}}) {
	print MOUT "\trm \$(DOCDIR)/$pkgdoc\n";
}

# Uninstall headers from $(includedir)
foreach my $header (@{$mk->{headers}}) {
        my $pkg_path = $mk->get_package_from_source($header)
                or die 'error';
        $pkg_path =~ s/::/\//g;
        my $dest = "\$(INCLUDEDIR)/$pkg_path.pm";
        print MOUT "\trm $dest\n";
}

print MOUT "\t\$(APLOCAL) post_make_uninstall_hook\n" 
	if grep /post_make_uninstall/, @{$mk->{hooks}};

print MOUT "\n";
#--------------------------------
# Generate the 'make dist' target
#
print MOUT "dist: ".($subdirs ? 'recursive-dist' : '') . "\n";

print MOUT "\t\$(APLOCAL) pre_make_dist_hook\n" 
   if grep /pre_make_dist/, @{$mk->{hooks}};

# Initialize the buildd, if we are in TOPDIR
my $buildd = '$(DISTDIR)';
print MOUT "\tinstall -d -m 755 \$(DISTDIR)\n";

# Install some optional files
my @optional;
foreach my $opt_fn (qw(configure package.in Makefile.am ChangeLog 
		AUTHORS COPYING NEWS README BUGS THANKS)) {
		push @optional, $opt_fn if -e "$curdir/$opt_fn";
		}
if (@optional) {
	print MOUT "\t\$(INSTALL) " . join(" ",@optional) . " \$(DISTDIR)\n";
}

# Copy all extra dist, sources, headers, and manpages into buildd
my @ifiles = ( $mk->get_all_sources(),
	       @{$mk->{headers}},
               $mk->get_all_manpages(),
	       @{$mk->{extra_dist}},
	       @{$mk->{pkgdata}},
	      );
foreach (@ifiles) {
	print MOUT "\t\$(INSTALL) $_ $buildd/$_\n";
}

print MOUT "\t\$(APLOCAL) post_make_dist_hook\n" 
   if grep /post_make_dist/, @{$mk->{hooks}};

# Create the tarball and clean up
if ( $curdir eq '.' ) {
	print MOUT "\ttar zcvf ".$mk->{top}->{program}."-".$mk->{version}.".tar.gz $buildd\n";
	print MOUT "\trm -rf $buildd\n";
}
print MOUT "\n";

#----- Generate the 'make package' target ------
if ($mk eq $mk->{top}) {

print MOUT "package: all\n";

print MOUT "\t\$(APLOCAL) pre_make_package_hook\n" 
   if grep /pre_make_package/, @{$mk->{hooks}};

print MOUT "\t\$(AUTOPERL) package\n";

print MOUT "\t\$(APLOCAL) post_make_package_hook\n" 
   if grep /post_make_package/, @{$mk->{hooks}};

print MOUT "\n";
}

#----- Generate the 'make clean' target ------
if ( ! $mk->{targets}->{'clean-local'} ) {
	print MOUT "clean: ".($subdirs ? 'recursive-clean' : '') . "\n";
        print MOUT "\t\$(APLOCAL) pre_make_clean_hook\n" 
            if grep /pre_make_clean/, @{$mk->{hooks}};
	
        my $derived = join(' ', @{$mk->{bin_programs}},
				@{$mk->{sbin_programs}});
	print MOUT "\trm -f $derived\n" if $derived;
        print MOUT "\t\$(APLOCAL) post_make_clean_hook\n" 
            if grep /post_make_clean/, @{$mk->{hooks}};
}
print MOUT "\n";

#----- Generate the 'make test' target -----
print MOUT "test: ".($subdirs ? 'recursive-test' : '') . "\n";

print MOUT "\t\$(APLOCAL) pre_make_test_hook\n" 
   if grep /pre_make_test/, @{$mk->{hooks}};


# Try to compile all of the source code
foreach my $src ( keys %{$mk->{sources}} ) {
        my @objs = @{$mk->{sources}->{$src}};
        foreach my $obj (@objs) {
                next unless $obj =~ /\.pm$/;
                my $pkg_path = $mk->get_package_from_source($obj);
                print MOUT "\tperl -w -c $obj\n";
        }
}


if ( -d "$curdir/t") {
	print MOUT "\t\$(PERL) -e 'use Test::Harness; runtests(\@ARGV)' t/*.t\n";
}

print MOUT "\t\$(APLOCAL) post_make_test_hook\n" 
   if grep /post_make_test/, @{$mk->{hooks}};

print MOUT "\n";

#----- Append all user-defined targets --------
my $user_defined = generate_synthetic_targets($mk);
if ($user_defined) {
	print MOUT "\n#--User defined targets--\n" . $user_defined;
}
	
}

# Return a text string containing 'synthetic' targets
sub generate_synthetic_targets($)
{
	my $mk = shift;
	my $s;
	
	foreach my $key (keys %{$mk->{targets}}) {
		my $target = $key;
		if ($target =~ /\-local$/) {
			$target = $`;
		}
	$s .= "\n$target: " . $mk->{targets}->{$key}->{depends} . "\n" .
		join("\n", @{$mk->{targets}->{$key}->{lines}}) . "\n";	
	}
	return $s;
}

1;
#============================================================================
}
{
#============================================================================
# Imported from Autoperl/Installer.pm by Autoperl
# install.pl - Perl replacement for install(1)
#
# Adapted from Jon Ericson's BSD install(1) replacement at:
#
# http://backpan.cpan.org/authors/id/J/JE/JERICSON/install/install-1.31.pl
#
package Autoperl::Installer;

# Generated by autoperl
unless (defined $ap::CONFIG_H) {

$ap::CONFIG_H = 1;
%ap::config = (
                '' => 1,
                'docdir' => '/usr/local/share/doc/autoperl',
                'mandir' => '/usr/local/man',
                'pkgdatadir' => '/usr/local/share/autoperl',
                'author' => 'Mark Heily <devel@heily.com>',
                'program' => 'autoperl',
                'infodir' => '/usr/local/info',
                'sysconfdir' => 'etc',
                'htmldir' => 'var/www',
                'bindir' => '/usr/local/bin',
                'confdir' => '/etc/autoperl',
                'libexecdir' => '/usr/local/libexec',
                'localedir' => '/usr/local/locale',
                'version' => '0.9.4',
                'cgidir' => 'usr/lib/cgi-bin',
                'includedir' => '/usr/local/lib/site_perl',
                'statedir' => '/var/lib/autoperl',
                'datadir' => '/usr/local/share',
                'sbindir' => '/usr/local/sbin',
                'libdir' => '/usr/local/lib/autoperl',
                'srcdir' => undef,
                'prefix' => '/usr/local'
              );


# Inconvenience hashref
$ap::config = \%ap::config;
}


use strict;

use Getopt::Long qw(:config bundling_override);
use Pod::Usage;

use File::Copy;
use File::Basename;
use File::Compare;
use File::Spec::Functions ':ALL';

sub makedirs;
sub install;
sub message;
sub logaction;
sub preaction;
sub postaction;
sub setmode;
sub setgroup;
sub setowner;


my %opt = (
           help =>0,
           man => 0,
           version => 0,
           directory => 0,
           backup => 0,
           B => '.old',
           force => 0,
           compare => 0,
           preserve => 0,
           mode => undef,
           owner => undef,
           group => undef,
           verbose => 0,
           log => 'install.log',
           pre => [],
           post => [],
);
my $log;


sub main {
GetOptions (\%opt,
            'help|?',
	    'man',
	    'version',
            'directory|d',
	    'backup|b',
	    'B=s',
            'force|f',
            'compare|C',
	    'preserve|p',
	    'mode|m=s',
	    'owner|o=s',
	    'group|g=s',
	    'verbose|v',
            'log=s',
	    'pre=s',
	    'post=s',
	   ) or pod2usage(1);
pod2usage(1) if $opt{help};
pod2usage(-exitstatus => 0, -verbose => 2) if $opt{man};


if (defined $opt{log}) {
    no strict 'refs';
    open($log, ">> $opt{log}") or die "can't open $opt{log}: $!";
};

if (defined $opt{mode}){
  my %likely = (
		777 => 1, 776 => 1, 775 => 1, 774 => 1, 766 => 1,
		755 => 1, 744 => 1, 700 => 1,
		666 => 1, 665 => 1, 664 => 1, 655 => 1, 644 => 1,
		600 => 1,
		555 => 1, 554 => 1, 544 => 1, 500 => 1,
		444 => 1, 400 => 1,
	       );

  warn "$opt{mode} seems an unlikely mode"
    unless $likely{sprintf "%d", $opt{mode}};
};

if ($opt{directory}) {
    pod2usage("$0: not enough arguments") unless @ARGV > 0;

    makedirs(@ARGV);
} elsif (@ARGV == 2 && ! -d $ARGV[1]){
    install $ARGV[0], $ARGV[1];
} else {
    pod2usage("$0: not enough arguments") unless @ARGV > 1;

    my $dest = pop @ARGV;

    pod2usage "$0: `$dest' is not a directory" unless -d $dest;

    for (@ARGV){
      my $base = basename($_);
      my $target = catfile($dest, $base);

      install $_, $target;
    };
};

}

sub makedirs{
    # print "makedirs called with: @_\n";
    for (@_) {

        if(-d $_){
	  postaction($_);
	  next;
	};

        #print "trying $_\n";
        if (-d dirname($_)) {
            mkdir $_ or die "can't mkdir $_: $!";
            message $_;
	    logaction "mkdir $_";
	    postaction $_;
        }else {
            makedirs(dirname($_), $_);
        };
    };
};

sub install{
  my $source = shift;
  my $target = shift;
  my $base = basename($source);
  my $target_dir = dirname($target);
  my $old;

#  die "$source is not a file" unless -f $source;

  preaction($source);

  #FIXME - use makedirs 
  system "/usr/bin/install -d -m 755 $target_dir"
        unless -d $target_dir;

  if ($opt{compare} and compare($source, $target) == 0){
      logaction "$source and $target are the same";
  } else {
      if ($opt{backup} && -f $target){
          my $ext = $opt{B};
          if ($ext eq 'numbered'){
              $ext = 1;
              while (-f "$target.$ext"){$ext++};
              $ext = ".$ext";
          };
          $old = "$target$ext";

          move $target => $old or die "can't move $target to $old: $!";
          message $old;
          logaction "$target => $old";
      };

      my ($dev, $ino) = (stat $source)[0,1];
      if (-f $target && $dev == (stat $target)[0] && $ino == (stat _)[1]){
          die "$source and $target are the same file";
      };

      my $copied = copy $source, $target;

      unless ($copied){
          if ($opt{force} && -f $target){
              unlink $target or die "can't unlink $target:$!";
              logaction "unlink $target";
              $copied = copy $source, $target;
          };
          if ($opt{backup}) {
              move $old => $target or die "can't move $old to $target: $!";
              message "restoring $target from $old";
              logaction "$old => $target";
          }
      };
      die "can't copy $source to $target: $!" unless $copied;

      message $target;
      logaction "$source -> $target";

      apsubst($target) if $source =~ /\.p[lm]$/;
  };

  # Code cribbed from
  # <http://www.perl.com/language/ppt/src/cp/cp.schumacks>
  if ($opt{preserve}){
    my($mode, $uid, $gid, $atime, $mtime) = (stat $source)[2,4,5,8,9];
    utime $atime, $mtime, $target or die "can't utime $target: $!";
    my $oldmode = (07777 & $mode);
    chmod $oldmode, $target or die "can't chmod $target: $!";
    chown $uid, $gid, $target
      or warn "can't chown $target to $mode: $!";
  };

  postaction($target);
};

sub preaction{
  my $source = shift;
  for my $pre (@{$opt{pre}}){
    system "$pre $source" and die "--pre command `$pre' failed: $!";
    logaction "$pre $source";
  };
};

sub postaction{
  my $target = shift;
  setmode($opt{mode}, $target) if (defined $opt{mode});
  setowner($opt{owner}, $target) if (defined $opt{owner});
  setgroup($opt{group}, $target) if (defined $opt{group});

  for my $post (@{$opt{post}}){
    system "$post $target" and die "--post command `$post' failed: $!";
    logaction "$post $target";
  };

};

sub setmode{
  my $mode = shift;
  $mode = oct($mode);


  for (@_){
    chmod $mode, $_ or die "can't chmod $_ to $mode: $!";
    logaction "chmod $mode, $_";
  };

};

sub setowner{
  my $owner = shift;
  my $uid;

  if ($owner =~ /^\d+$/) {
      ($uid, $owner) = ($owner, getpwuid $owner);
      die "can't getpwuid $uid: $!" unless defined $owner;
  } else {
      $uid = getpwnam $owner;
      die "can't getpwnam $owner: $!" unless defined $uid;
  }

  for (@_){
    chown $uid, -1, $_ or die "can't chown $_ to $owner: $!";
    logaction "chown $uid, -1, $_";
  };

};

sub setgroup{
  my $group = shift;
  my $gid;

  if ($group =~ /^\d+$/) {
      ($gid, $group) = ($group, getgrgid $group);
      die "can't getgrnam $gid: $!" unless defined $group;
  }else {
      $gid = getgrnam $group;
      die "can't getgrnam $group: $!" unless defined $gid;
  }

  for (@_){
    chown -1, $gid, $_ or die "can't chown $_ to $group: $!";
    logaction "chown -1, $gid, $_";
  };

};

sub message{
    print @_, "\n" if $opt{verbose};
}

sub logaction{
    no strict 'refs';
    print $log scalar gmtime, ': ', @_, "\n" if defined $opt{log};
};

sub apsubst{
     my $target = shift;
     my $found = 0;
     my @src;

     open(my $config_h, "<config.h") or die "config.h: $!";
     my @config = <$config_h>;
     close($config_h);

     # The last line is '1;' which terminates processing. Don't include it.
     pop @config;

     my $repl = join('', @config);
     open(my $input, "<$target") or die "open failed";
     while (<$input>) {
	if (/^\s*(require|do) \"config.h\";/) {
	    $_ = $repl;
	    $found++;
	}
	push @src, $_;
     }
     close ($input);
     return unless $found;

     # Rewrite the shebang line to point to $LIBDIR
     if ($src[0] =~ /^\#\!(.*?)perl/ ) {
	my $flags = $';
	$flags = "" unless defined $flags;
     	chomp $src[0];
        $src[0] = '#!' .
		#FIXME- should be $ap::config->{perl} . 
		'/usr/bin/perl' .  
		' -I'.$ap::config->{libdir} . 
		" $flags\n";
     }

     open(my $output, ">$target") or die "open failed";
     print $output @src;
     close ($output);
}

1;
#============================================================================
}
{
#============================================================================
# Imported from Autoperl/Linker.pm by Autoperl
package Autoperl::Linker;

use Data::Dumper;

sub new
{
   my $class = shift;
   my $argv = shift;
   my $self = +{
   		output => undef,
		input => [],
   		};
   bless $self, $class;
   $self->parse_argv($argv) if $argv;
   return $self;
}

sub parse_argv($$)
{
	my ($self,$s) = @_;

	# Find the output file
	my $output;
	$s =~ /-o [A-za-z0-9\.]+/;
	die 'output file required' unless $&;
	$self->{output} = $&;
	$s =~ s/$&//;
	$self->{output} =~ s/^-o //;

	# Get the input files
	$s =~ s/^\s*//;
	@{$self->{input}} = split / /, $s;
}

sub run_linker($)
{
 	my $self = shift;
	my @input = @{$self->{input}};
	my $output = $self->{output} || die 'output undefined';
	my $hr = '#' . '='x76 . "\n";

	return if @input == @{ $output };

	# Find the 'main' module by looking for a .pl extension
	my $main;
	foreach my $module (@input) {
	    if ($module =~ /\.pl$/) {
		    	if ($main) {
				die 'cannot link multiple .pl files together';
			} else {
				$main = $module;
			}
	     }
	    }

	# Slurp $main into @lines
	open (MM, "<$main") or die "$!";
	my @lines = <MM>;
	close (MM);

	# Parse @lines, looking for 'use' or 'require' statements
	for (my $x = 0; $x < $#lines; $x++) {
	    my $line = $lines[$x];

	    next unless $line =~ /\s*(use|require) (.*);/;
	    my ($method,$target) = ($1,$2);
	    $target =~ s/"//g if $method eq 'require';
	    $target =~ s/::/\//g if $method eq 'use';
	    $target .= '.pm' if $method eq 'use';
	    next unless grep /$target/, @input or $target =~ /config.h$/;
	    #warn "merging $target";
	    #print "${x}: $method $target\n";
	    my $mod_text = read_file($target);
	    $lines[$x] = "{\n" . 
			$hr .
			 "# Imported from $target by Autoperl\n" . 
	    		$mod_text .
			$hr .
			"}\n";
	}
	
	open (FH, ">$output") or die "$!";
	print FH @lines;
	close (FH);
	chmod 0755, $output;
}


sub read_file($) { 
	my $infile = shift;
	open(FH,"<$infile") or die "$!";
	my @s = <FH>;
	close(FH);

	# Remove the __END__ tag and anything after it
	# Crap out if __DATA__ tag found 
	for (my $i = 0; $i < $#s; $i++) {
	    die "Autoperl linker does not support __DATA__ sections"
	       if $s[$i] =~ /^__DATA__/;
	    next unless $s[$i] =~ /^__END__/;
	    splice @s, $i;
	}

	
	return join('',@s);
}

1;
#============================================================================
}
{
#============================================================================
# Imported from Autoperl/Logger.pm by Autoperl
#
# logger.pm 
#
# An object that can process logging, trace, and debugging output
#
package Autoperl::Logger;

sub new
{
my $class = shift;
my $logfile = shift || 'config.log';

my $self = +{
		logfile => $logfile,
		fh => undef,
	    };
bless $self, $class;
$self->open($logfile);
return $self;
}

sub open($$)
{
	my ($self,$fn) = @_;
	
	open (FH, ">" . $fn) or die "$fn: $!";

}

sub AUTOLOAD
{
   my $sub = our $AUTOLOAD;
   
   if ( $sub =~ /^Autoperl::Logger::(debug|info|warn|crit)$/ ) {
	print FH $_[1] . "\n";
   } else {
   die "Method not found: \&$sub";
   }
}

sub DESTROY
{
   close(FH);
}

1;
#============================================================================
}
{
#============================================================================
# Imported from Autoperl/Packager.pm by Autoperl
package Autoperl::Packager;

use Cwd;
use strict;
use warnings;
use Data::Dumper;

our %manifest;

# make_package()
#
# Build a native binary package
#
sub make_package
{
	my $mk = shift;
	my $pkg_in = Autoperl::Parser::parse_package_in();

# Stat the local OS
	my $uname = $^O;
	foreach my $package (keys %{$pkg_in}) {
		my $manifest_ref = $pkg_in->{$package};
		%manifest = %{$manifest_ref};
		if ($uname eq 'openbsd') {
			make_openbsd_package();
		} elsif ($^O eq 'linux' and -e '/etc/debian_version') {
			make_deb_package();
		} elsif ($^O eq 'linux' and -e '/etc/redhat-release') {
			make_rpm_package();
		} else {
			die "Autoperl does not support building binary packages on this operating system ($^O)"
		}
	}
}

# '''''''''''''''''''''''' DEBIAN

sub make_deb_package
  {
    my $program = $ap::config{program};
    my $version = $ap::config{version};

    die "Cannot find dpkg-buildpackage; please install the debhelper package" 
	unless `which dpkg-buildpackage`;

    die "Cannot find fakeroot; please install the fakeroot package" 
	unless `which fakeroot`;

    die "A subdirectory named 'debian/' already exists, cannot continue"
	if -d 'debian/';
    mkdir 'debian' or die "mkdir: $!";

    my $cwd = getcwd;

    my $version_str = "$program ($version) unstable; urgency=low";
    open (CHANGELOG, ">debian/changelog") || die "$!";
    print CHANGELOG $version_str . "\n\n";
    print CHANGELOG "  * Automatically generated by autoperl\n\n";
    print CHANGELOG " -- $ap::config{author}  " . `date -R` . "\n\n";
    close (CHANGELOG);

    my $depends = "";
    my $arch = 'any'; #TODO: $spec->{'architecture'}

    # TODO: calculate dependencies
    # map { $depends .= "," . $self->getCanonicalName($_); } @{$spec->{depends}};

    # reformat the description to satisfy debian quirkyness
    # remove blank lines, [FIXME-TODO] shift each paragraph beginning right 1 space.

    my $synopsis = $manifest{Title};
    my $original = $manifest{Description};
    my $description;
    my $para_marker = 0;
    foreach my $line ( split /\n/, $manifest{Description} ) {
      unless ( $line =~ /\w/ ) { $para_marker = 1; next; }
      if ( $para_marker ) {
	$line = ".\n $line";
	$para_marker = 0;
      }
      $description .= " $line\n";
    }

    open ( CONTROL, ">debian/control" ) or die "$!";
    print CONTROL <<EOF
Source: $ap::config{program}
Section: unknown
Priority: optional
Maintainer: $ap::config{author}
Build-Depends: debhelper (>> 3.0.0)
Standards-Version: 3.5.2

Package: $ap::config{program}
Architecture: $arch
Depends: \${shlibs:Depends} $depends
Description: $synopsis
$description
EOF
;
    close ( CONTROL );

    ## Create debian/rules Makefile


    open ( RULES, ">debian/rules" ) or die "$!";
    print RULES <<EOF
#!/usr/bin/make -f
# Automatically generated debian/rules by autoperl(1)

config.status:
	dh_testdir
	touch config.status

build: build-stamp

build-stamp:  config.status
	dh_testdir
	make
	touch build-stamp

clean:
	dh_testdir
	dh_testroot
	rm -f build-stamp 

	# Add here commands to clean up after the build process.
	#-\$(MAKE) distclean

	dh_clean

install: build
	dh_testdir
	dh_testroot
	dh_clean -k
	dh_installdirs

	# Copy all files to debian/[package-name]
	install -d -m 700 debian/$program
	make install DESTDIR=$cwd/debian/$program

# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.

# Build architecture-dependent files here.
binary-arch: build install
	dh_testdir
	dh_testroot

#	dh_installdocs
#	dh_installexamples
	dh_install
#	dh_installmenu
#	dh_installdebconf	
#	dh_installlogrotate
#	dh_installemacsen
#	dh_installpam
#	dh_installmime
#	dh_installinit
#	dh_installcron
#	dh_installinfo
#	dh_installman
	dh_link
	dh_strip
	dh_compress
	dh_fixperms
#	dh_perl
#	dh_python
#	dh_makeshlibs
	dh_installdeb
	dh_shlibdeps
	dh_gencontrol
	dh_md5sums
	dh_builddeb

binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install 


EOF
;
    close ( RULES );
    chmod 0755, 'debian/rules';

    #XXX-FIXME-this does wierd things
#    open ( DIRS, ">debian/dirs" ) or die "$!";
#    foreach ( @{$spec->{dirs}} ) {
#      print DIRS "$_\n";
#    }
#    close ( DIRS );

    system "echo 4 > debian/compat";

#    $self->SUPER::create("post");
    system "bash -c 'dpkg-buildpackage -b -us -uc -rfakeroot'";
    if ( $? ) {
      die "dpkg-buildpackage returned an error";
    }
    my $deb_file = Cwd::abs_path('..') . "/${program}_${version}_i386.deb"; #FIXME-hardcoded
    if ( ! -e $deb_file ) { die "could not find deb package $deb_file, or error copying";    }

    system "rm -rf debian/ ../${program}_*.changes";
    die "cleanup of 'debian/' failed" if $?;
      
    $deb_file =~ m|^.*/|;
    rename $deb_file, $';
  }


sub make_rpm_package 
  {
      my $program = $ap::config{program};
      my $package = $program;
      my $version = $ap::config{version};
      my $title = $manifest{Title};
      my $description = $manifest{Description};
      my $author = $ap::config{author};
										    my $cwd = getcwd();
    my $tmpdir = "$cwd/rpm-build";
    my $specfile = "$tmpdir/rpm.spec";
    my $rpm_base = $tmpdir;
    my $buildroot = "$rpm_base/BUILD/$package-$version";

    # Cross-compiling presents a problem for the find-requires script
    my $cross_compiling = 0;

    ## Create SOURCES, RPMS directories if needed
    foreach ($tmpdir, "$rpm_base/BUILD", "$rpm_base/SOURCES",
    		"$rpm_base/RPMS", $buildroot)
	   { 
	    	print "mkdir $_\n";
	    	mkdir $_ or die "*ERROR* $!" 
	}
    
    # Install the package into $buildroot
    my @files = install_all($buildroot);

    ## Eliminate the RPM 'find-requires' script, since it is not portable (!)
    if ($cross_compiling) {
    open (FINDREQ, ">$rpm_base/find-requires" ) || die "$!";
    print FINDREQ <<EOF
#!/bin/sh
xargs >/dev/null
echo ""
EOF
    ;
    close (FINDREQ);
    chmod 0755, "$rpm_base/find-requires";
    }

    ## RPM '%files' requires leading slashes
    for ( my $i; $i <= $#files; $i++ ) { 
    	$files[$i] = "/" . $files[$i]; 
    }
 
    ## Generate the make(1) commands
    open ("SPEC", ">$specfile") or die "$specfile: $!";

print SPEC "# autoperl generated spec file " .
	 	"for package $package (Version $version)\n\n";

foreach (keys %ap::config) {
	my $value = $ap::config{$_};
	next unless defined $value and $_;
	print SPEC "\%define _$_ $value\n";
}

print SPEC "\%define __find_requires $tmpdir/find-requires\n"
	if $cross_compiling;

die Dumper(%manifest);
    print SPEC <<"__EOF__";
%define   _topdir   $tmpdir
Name:      $package
Summary:   $title
Version:   $version
License:   $manifest{License} 
Vendor:    $author
Packager:  $author
Release:   1
Group:     Other
BuildRoot: $buildroot

\%description
$manifest{Description}

\%prep
###%setup -q
###echo %_target
###echo %_target_alias
###echo %_target_cpu
###echo %_target_os
###echo %_target_vendor

\%build
true

\%install
true

\%clean
true

\%post
true

\%postun
true

\%files
%defattr(-,root,root)
__EOF__

foreach (@files) {
print SPEC "$_\n";
}

    close SPEC;

    ## Compile the software
    chdir $rpm_base or die "$!";
    system "rpm -bb rpm.spec";  
    my $result = $?;
    chdir '..';
    if ( $result ) {  
       die "RPM failed to create the package (message: $?)";  
    }  
    
    map { 
    	chomp;
    	my $src = $_;
	$src =~ m|^.*/|;
	my $dest = $';
	rename $src, $dest or die "error moving $src to $dest: $!";
	print "$dest\n";
    } `find $rpm_base/RPMS -name '*.rpm'`;  

    system "rm -rf $tmpdir";
  }


sub make_openbsd_package
{
   my $tmpdir = './bsd-package';
   my @files = install_all($tmpdir);
   
   chomp(my $release = `/usr/bin/uname -r`);
   $release =~ s/\.//g;
   chomp(my $machine = `/usr/bin/uname -m`);
   open (my $plist,">plist") or die "plist:$!";
   print $plist join("\n",map { s|^usr/local/||; $_ } @files);
   close ($plist);

   my $output_fn = $ap::config{program} .
                   '-' .
                   $ap::config{version} .
                   ".tgz";

   system "pkg_create -f plist -B $tmpdir -p /usr/local " .
                        " -c '-package title' -d '-longdesc' " .
                        " $output_fn";

#my @cmd = ( "pkg_create -f pkg/PLIST ",
#            "\t   -p /usr/local",
#            "\t   -c '" . $manifest->{synopsis} . "'",
#            "\t   -d pkg/DESC",
            #"\t   -i pkg/INSTALL",
            #"\t   -k DEINSTALL",
#            $output_fn,
#          );
	system "rm -rf $tmpdir";
        unlink "plist";
}

sub install_all
{

        my $dest = shift || die;
        my $cwd = getcwd;
	die 'invalid install_all() target: '.$dest
		unless $dest =~ m|^(\./\|/)|;
	system "rm -rf $dest";
	$dest =~ s|^\./|$cwd|;
	system "make install DESTDIR=$dest/";

	# Get a list of all installed files
	 my @files = map { s|^$dest/||; chomp; $_; } 
	 	`find $dest -type f`;

	return @files;
}

1;
#============================================================================
}


# Parse ARGV
my $action = shift @ARGV;
$action = '' unless defined $action;
$action =~ s/^--//;

if ($action eq 'autoperl') {
   $action = shift @ARGV;
   $action = '' unless defined $action;
	if ($action eq 'init') {
		Autoperl::Generator::generate_configure_in();
	} elsif ($action eq 'link') {
		my $ld = new Autoperl::Linker(join(' ',@ARGV));
		$ld->run_linker();
	} elsif ($action eq 'package') {
		Autoperl::Packager::make_package();
	} elsif ($action eq 'install') {
		Autoperl::Installer::main();
	} else {
		die 'unsupported autoperl action';
	}
} else {
	# Initialize globals
	our $log = new Autoperl::Logger;
	our $ap = new Autoperl();
	unshift @ARGV, "--$action";
	$ap->{mk}->parse_all();
	# FIXME-WORKAROUND for $ap->{program}
	# this is ugly 
 	$ap->{program} = $ap->{mk}->{program};	
 	$ap->{author} = $ap->{mk}->{author};	
 	$ap->{version} = $ap->{mk}->{version};	
	$ap->configure();
}
