# $File: //depot/cpan/Module-Install/lib/Module/Install.pm $ $Author: autrijus $
# $Revision: #68 $ $Change: 2285 $ $DateTime: 2004/07/01 03:16:20 $ vim: expandtab shiftwidth=4

package Module::Install;
$VERSION = '0.34';

die << "." unless $INC{join('/', inc => split(/::/, __PACKAGE__)).'.pm'};
Please invoke ${\__PACKAGE__} with:

    use inc::${\__PACKAGE__};

not:

    use ${\__PACKAGE__};

.

use strict 'vars';
use Cwd ();
use File::Find ();
use File::Path ();

@inc::Module::Install::ISA = 'Module::Install';

=head1 NAME

Module::Install - Standalone, extensible Perl module installer

=head1 VERSION

This document describes version 0.34 of Module::Install, released
July 1, 2004.

=head1 SYNOPSIS

In your F<Makefile.PL>:

    # drop-in replacement to ExtUtils::MakeMaker!
    use inc::Module::Install;
    WriteMakefile( ... );

Standard usage:

    use inc::Module::Install;

    name            ('Your-Module');
    abstract        ('Some Abstract here');
    author          ('Your Name <email@example.com>');
    version_from    ('lib/Your/Module.pm');
    license         ('perl');

    requires        ('perl' => 5.005);
    requires        ('Acme::Hello');
    build_requires  ('Test::More');
    recommends      ('Acme::ComeFrom' => 0.01);

    # -- You'll likely only want one of the below --
    # auto_bundle();       # bundle run-time dependencies
    # auto_include();      # include build-time dependencies
    # auto_include_deps(); # same as above, plus recursive dependencies
    # auto_install();      # auto-install all dependencies from CPAN

    &WriteAll;

If it is invoked as F<Makefile.PL>, it will write a standard F<Makefile>,
and also download a F<nmake.exe> on Microsoft Windows if needed.  If invoked
as F<Build.PL>, it writes a standard F<Build> script that works with the
L<Module::Build> framework.

You can even support both by having a dummy F<Build.PL> that reads:

    require 'Makefile.PL';

=head1 DESCRIPTION

This module provides a drop-in replacement for B<ExtUtils::MakeMaker>.
For first-time users, Brian Ingerson's I<Creating Module Distributions
with Module::Install> in June 2003 issue of The Perl Journal
(L<http://www.tpj.com/issues/>) provides a gentle introduction to how
this module works.

If you want to start working with real-world examples right away, check
out L<Module::Install-Cookbook>.  For some personal opinions behind this
module's making, see L<Module::Install-Philosophy>.

This module is designed to let module authors eliminate all duplicated
codes in F<Makefile.PL> and F<Build.PL>, by abstracting them into
I<extensions>, and distribute them under the F<inc/> directory.

To start using it, just replace the C<use ExtUtils::MakeMaker;> line
from F<Makefile.PL> with C<use inc::Module::Install;>, then run it once:

    % perl Makefile.PL
    include inc/Module/Install.pm
    include inc/Module/Install/MakeMaker.pm
    include inc/Module/Install/Base.pm
    include inc/Module/Install/Makefile.pm
    include inc/Module/Install/Metadata.pm
    Writing Makefile for foo
    Creating META.yml

Now your distribution will have an extra F<inc/> directory, with the
minimal loader code F<inc/Module/Install.pm> and base extension class
B<Module::Install::Base> copied into it.  Also, since you made use of
the C<WriteMakefile> function, the B<Module::Install::MakeMaker>
extension is also copied into F<inc/>, along with two other extensions
called from B<Module::Install::MakeMaker>.

End-users of your distribution do not need to install anything extra;
the distribution already includes all necessary extensions, with their
POD documentations removed.  Note that because it does not include
unused extensions or B<Module::Install> itself, the impact on
distribution size is minimized.

=head1 METHODS

=over 4

=item import(@args)

If this module was not loaded from F<inc/>, calls the C<init>
method of B<Module::Install::Admin> to include and reload itself;
see L<Module::Install::Admin/Bootstrapping> for details.

Otherwise, export a default C<AUTOLOAD> handler to the caller's package.

The C<@args> array is passed to C<new> to intialize the top-level
B<Module::Install> object; it should usually be left empty.

=cut

sub import {
    my $class = shift;
    my $self = $class->new(@_);

    if (not -f $self->{file}) {
        require "$self->{path}/$self->{dispatch}.pm";
        File::Path::mkpath("$self->{prefix}/$self->{author}");
        $self->{admin} = 
          "$self->{name}::$self->{dispatch}"->new(_top => $self);
        $self->{admin}->init;
        @_ = ($class, _self => $self);
        goto &{"$self->{name}::import"};
    }

    *{caller(0) . "::AUTOLOAD"} = $self->autoload;

    # Unregister loader and worker packages so subdirs can use them again
    delete $INC{"$self->{file}"};
    delete $INC{"$self->{path}.pm"};
}

=item autoload()

Returns an AUTOLOAD handler bound to the caller package.

=cut

sub autoload {
    my $self = shift;
    my $caller = caller;

    my $cwd = Cwd::cwd();
    my $sym = "$caller\::AUTOLOAD";

    $sym->{$cwd} = sub {
        my $pwd = Cwd::cwd();
        if (my $code = $sym->{$pwd}) {
            goto &$code unless $cwd eq $pwd; # delegate back to parent dirs
        }
        $$sym =~ /([^:]+)$/ or die "Cannot autoload $caller";
        unshift @_, ($self, $1);
        goto &{$self->can('call')} unless uc($1) eq $1;
    };
}

=item new(%args)

Constructor, taking a hash of named arguments.  Usually you do not want
change any of them.

=cut

sub new {
    my ($class, %args) = @_;

    return $args{_self} if $args{_self};

    $args{dispatch} ||= 'Admin';
    $args{prefix}   ||= 'inc';
    $args{author}   ||= '.author';
    $args{bundle}   ||= 'inc/BUNDLES';

    $class =~ s/^\Q$args{prefix}\E:://;
    $args{name}     ||= $class;
    $args{version}  ||= $class->VERSION;

    unless ($args{path}) {
        $args{path}  = $args{name};
        $args{path}  =~ s!::!/!g;
    }
    $args{file}     ||= "$args{prefix}/$args{path}.pm";

    bless(\%args, $class);
}

=item call($method, @args)

Call an extension method, passing C<@args> to it.

=cut

sub call {
    my $self   = shift;
    my $method = shift;
    my $obj = $self->load($method) or return;

    unshift @_, $obj;
    goto &{$obj->can($method)};
}

=item load($method)

Include and load an extension object implementing C<$method>.

=cut

sub load {
    my ($self, $method) = @_;

    $self->load_extensions(
        "$self->{prefix}/$self->{path}", $self
    ) unless $self->{extensions};

    foreach my $obj (@{$self->{extensions}}) {
        return $obj if $obj->can($method);
    }

    my $admin = $self->{admin} or die << "END";
The '$method' method does not exist in the '$self->{prefix}' path!
Please remove the '$self->{prefix}' directory and run $0 again to load it.
END

    my $obj = $admin->load($method, 1);
    push @{$self->{extensions}}, $obj;

    $obj;
}

=item load_extensions($path, $top_obj)

Loads all extensions under C<$path>; for each extension, create a
singleton object with C<_top> pointing to C<$top_obj>, and populates the
arrayref C<$self-E<gt>{extensions}> with those objects.

=cut

sub load_extensions {
    my ($self, $path, $top_obj) = @_;

    unshift @INC, $self->{prefix}
        unless grep { $_ eq $self->{prefix} } @INC;

    local @INC = ($path, @INC);
    foreach my $rv ($self->find_extensions($path)) {
        my ($file, $pkg) = @{$rv};
        next if $self->{pathnames}{$pkg};

        eval { require $file; 1 } or (warn($@), next);
        $self->{pathnames}{$pkg} = delete $INC{$file};
        push @{$self->{extensions}}, $pkg->new( _top => $top_obj );
    }
}

=item load_extensions($path)

Returns an array of C<[ $file_name, $package_name ]> for each extension
module found under C<$path> and its subdirectories.

=cut

sub find_extensions {
    my ($self, $path) = @_;
    my @found;

    File::Find::find(sub {
        my $file = $File::Find::name;
        return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
        return if $1 eq $self->{dispatch};

        $file = "$self->{path}/$1.pm";
        my $pkg = "$self->{name}::$1"; $pkg =~ s!/!::!g;
        push @found, [$file, $pkg];
    }, $path) if -d $path;

    @found;
}

1;

__END__

=back

=head1 EXTENSIONS

All extensions belong to the B<Module::Install::*> namespace, and
inherit from B<Module::Install::Base>.  There are three categories
of extensions:

=over 4

=item Standard Extensions

Methods defined by a standard extension may be called as plain functions
inside F<Makefile.PL>; a corresponding singleton object will be spawned
automatically.  Other extensions may also invoke its methods just like
their own methods:

    # delegates to $other_extension_obj->method_name(@args)
    $self->method_name(@args);

At the first time an extension's method is invoked, a POD-stripped
version of it will be included under the F<inc/Module/Install/>
directory, and becomes I<fixed> -- i.e. even if the user had installed a
different version of the same extension, the included one will still be
used instead.

If the author wish to upgrade extensions in F<inc/> with installed ones,
simply run C<perl Makefile.PL> again; B<Module::Install> determines
whether you are an author by the existence of the F<inc/.author/>
directory.  End-users can reinitialize everything and become the author
by typing C<make realclean> and C<perl Makefile.PL>.

=item Private Extensions

Those extensions take the form of B<Module::Install::PRIVATE> and
B<Module::Install::PRIVATE::*>.

Authors are encouraged to put all existing F<Makefile.PL> magics into
such extensions (e.g. F<Module::Install::PRIVATE> for common bits;
F<Module::Install::PRIVATE::DISTNAME> for functions specific to a
distribution).

Private extensions should not to be released on CPAN; simply put them
somewhere in your C<@INC>, under the C<Module/Install/> directory, and
start using their functions in F<Makefile.PL>.  Like standard
extensions, they will never be installed on the end-user's machine,
and therefore never conflict with other people's private extensions.

=item Administrative Extensions

Extensions under the B<Module::Install::Admin::*> namespace are never
included with the distribution.  Their methods are not directly
accessible from F<Makefile.PL> or other extensions; they are invoked
like this:

    # delegates to $other_admin_extension_obj->method_name(@args)
    $self->admin->method_name(@args);

These methods only take effect during the I<initialization> run, when
F<inc/> is being populated; they are ignored for end-users.  Again,
to re-initialize everything, just run C<perl Makefile.PL> as the author.

Scripts (usually one-liners in F<Makefile>) that wish to dispatch
B<AUTOLOAD> functions into administrative extensions (instead of
standard extensions) should use the B<Module::Install::Admin> module
directly.  See L<Module::Install::Admin> for details.

=back

B<Module::Install> comes with several standard extensions:

=over 4

=item Module::Install::AutoInstall

Provides C<auto_install()> to automatically fetch and install
prerequisites via B<CPANPLUS> or B<CPAN>, specified either by
the C<features> metadata or by method arguments. 

You may wish to add a C<include('ExtUtils::AutoInstall');> before
C<auto_install()> to include B<ExtUtils::AutoInstall> with your
distribution.  Otherwise, this extension will attempt to automatically
install it from CPAN.

=item Module::Install::Base

The base class of all extensions, providing C<new>, C<initialized>,
C<admin>, C<load> and the C<AUTOLOAD> dispatcher.

=item Module::Install::Build

Provides C<&Build-E<gt>write> to generate a B<Module::Build> compliant
F<Build> file, as well as other B<Module::Build> support functions.

=item Module::Install::Bundle

Provides C<bundle>, C<bundle_deps> and C<bundle_all>, allowing you
to bundle a CPAN distribution within your distribution.  When your
end-users install your distribution, the bundled distribution will be
installed along with yours, unless a newer version of the bundled
distribution already exists on their local filesystem.

=item Module::Install::Fetch

Handles fetching files from remote servers via FTP.

=item Module::Install::Include

Provides the C<include($pkg)> function to include pod-stripped
package(s) from C<@INC> to F<inc/>, and the C<auto_include()>
function to include all modules specified in C<build_requires>,

Also provides the C<include_deps($pkg)> function to include every
non-core modules needed by C<$pkg>, and the C<auto_include_deps()>
function that does the same thing as C<auto_include()>, plus all
recursive dependencies that are subsequently required by modules in
C<build_requires>.

=item Module::Install::Inline

Provides C<&Inline-E<gt>write> to replace B<Inline::MakeMaker>'s
functionality of making (and cleaning after) B<Inline>-based modules.

However, you should invoke this with C<WriteAll( inline => 1 )> instead.

=item Module::Install::MakeMaker

Simple wrapper class for C<ExtUtils::MakeMaker::WriteMakefile>.

=item Module::Install::Makefile

Provides C<&Makefile-E<gt>write> to generate a B<ExtUtils::MakeMaker>
compliant F<Makefile>; preferred over B<Module::Install::MakeMaker>.
It adds several extra C<make> targets, as well as being more intelligent
at guessing unspecified arguments.

=item Module::Install::Makefile::Name

Guess the distribution name.

=item Module::Install::Makefile::Version

Guess the distribution version.

=item Module::Install::Metadata

Provides C<&Meta-E<gt>write> to generate a B<YAML>-compliant F<META.yml>
file, and C<&Meta-E<gt>read> to parse it for C<&Makefile>, C<&Build> and
C<&AutoInstall> to use.

=item Module::Install::PAR

Makes pre-compiled module binary packages from F<blib>, and download
existing ones to save the user from recompiling.

=item Module::Install::Run

Determines if a command is available on the user's machine, and run
external commands via B<IPC::Run3>.

=item Module::Install::Scripts

Handles packaging and installation of scripts, instead of modules.

=item Module::Install::Win32

Functions related for installing modules on Win32, e.g. automatically
fetching and installing F<nmake.exe> for users that need it.

=item Module::Install::WriteAll

This extension offers C<WriteAll>, which writes F<META.yml> and
either F<Makefile> or F<Build> depending on how the program was
invoked.

C<WriteAll> takes four optional named parameters:

=over 4

=item C<check_nmake> (defaults to true)
    
If true, invokes functions with the same name.

=item C<inline> (defaults to false)

If true, invokes C<&Inline-E<gt>write> instead of C<&Makefile-E<gt>write>.

=item C<meta> (defaults to true)

If true, writes a C<META.yml> file.

=item C<sign> (defaults to false)

If true, invokes functions with the same name.

=back

=back

B<Module::Install> also comes with several administrative extensions:

=over

=item Module::Install::Admin::Find

Functions for finding extensions, installed packages and files in
subdirectories.

=item Module::Install::Admin::Manifest

Functions for manipulating and updating the F<MANIFEST> file.

=item Module::Install::Admin::Metadata

Functions for manipulating and updating the F<META.yml> file.

=item Module::Install::Admin::ScanDeps

Handles scanning for non-core dependencies via B<Module::ScanDeps> and
B<Module::CoreList>.

=back

Please consult their own POD documentations for detailed information.

=head1 FAQ

=head2 What are the benefits of using B<Module::Install>?

Here is a brief overview of the reasons:

    Does everything ExtUtils::MakeMaker does.
    Requires no installation for end-users.
    Generate stock Makefile.PL for Module::Build users.
    Guaranteed forward-compatibility.
    Automatically updates your MANIFEST.
    Distributing scripts is easy.
    Include prerequisite modules (even the entire dependency tree).
    Auto-installation of prerequisites.
    Support for Inline-based modules.
    Support for precompiled PAR binaries.

Besides, if you maintain more than one CPAN modules, chances are there
are duplications in their F<Makefile.PL>, and also with other CPAN module
you copied the code from.  B<Module::Install> makes it really easy for you
to abstract away such codes; see the next question.

=head2 How is this different from its predecessor, B<CPAN::MakeMaker>?

According to Brian Ingerson, the author of B<CPAN::MakeMaker>,
their difference is that I<Module::Install is sane>.

Also, this module is not self-modifying, and offers a clear separation
between standard, private and administrative extensions.  Therefore
writing extensions for B<Module::Install> is easier -- instead of
tweaking your local copy of C<CPAN/MakeMaker.pm>, just make your own
B<Modula::Install::PRIVATE> module, or a new B<Module::Install::*>
extension.

=head1 SEE ALSO

L<Module::Install-Cookbook>,
L<Module::Install-Philosophy>,
L<inc::Module::Install>

L<Module::Install::AutoInstall>,
L<Module::Install::Base>,
L<Module::Install::Bundle>,
L<Module::Install::Build>,
L<Module::Install::Directives>,
L<Module::Install::Fetch>,
L<Module::Install::Include>,
L<Module::Install::MakeMaker>,
L<Module::Install::Makefile>,
L<Module::Install::Makefile::CleanFiles>,
L<Module::Install::Makefile::Name>,
L<Module::Install::Makefile::Version>,
L<Module::Install::Metadata>,
L<Module::Install::PAR>,
L<Module::Install::Run>,
L<Module::Install::Scripts>,
L<Module::Install::Win32>
L<Module::Install::WriteAll>

L<Module::Install::Admin>,
L<Module::Install::Admin::Bundle>,
L<Module::Install::Admin::Find>,
L<Module::Install::Admin::Include>,
L<Module::Install::Admin::Makefile>,
L<Module::Install::Admin::Manifest>,
L<Module::Install::Admin::Metadata>,
L<Module::Install::Admin::ScanDeps>
L<Module::Install::Admin::WriteAll>

L<CPAN::MakeMaker>,
L<Inline::MakeMaker>,
L<ExtUtils::MakeMaker>,
L<Module::Build>

=head1 AUTHORS

Brian Ingerson E<lt>INGY@cpan.orgE<gt>,
Autrijus Tang E<lt>autrijus@autrijus.orgE<gt>

=head1 COPYRIGHT

Copyright 2002, 2003, 2004 by
Autrijus Tang E<lt>autrijus@autrijus.orgE<gt>,
Brian Ingerson E<lt>INGY@cpan.orgE<gt>.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

See L<http://www.perl.com/perl/misc/Artistic.html>

=cut
