You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by Stas Bekman <st...@stason.org> on 2003/12/12 05:34:25 UTC

rfc: ModPerl::ModuleSetup

So now I have several modules that leave in the same package, work with both 
mod_perl generations, though they need to know which version to build for at 
the 'perl Makefile.PL' time. I've mentioned this issue several times already 
and I have some code, that it'd be nice to have in the core of mp2, that can 
tremendously simplify Makefile.PL, remove a lot of duplicated code and effort 
and unify the way all 3rd party modules select between mp1 and mp2.

This module will need to be installed to the normal @INC, just like Apache2.pm 
and not into Apache2/ subdir.

Here is Makefile.PL from Apache-Peek, most of which should be moved to that 
module. I'm talking about functions:

satisfy_mp_generation;
satisfy_perl_generation;
wanted_mp_generation;

they all are documented below. If we can stick to the same API it'll make 
users lives much easier. Please excuse me for lack of the real spec, I'll do 
that later, meanwhile just take a look at the code and see if it sounds good 
and whether you have other demands (and code that could be moved to that module).

use strict;

use Cwd;
use File::Spec::Functions;
use File::Path ();
use Config;
use Symbol;

use constant DEVEL => getpwuid($>) eq 'stas';

my $VERSION = '1.01';

my @clean_files = ();

my $mp_gen = satisfy_mp_generation();
my $perl_gen = satisfy_perl_generation();

#warn "using mp gen: $mp_gen, perl gen: $perl_gen\n";

# currently we support only 5.8-perlio
if ($perl_gen eq '5.8') {
     die "Perl must be built with PerlIO support in order to use this module"
         unless $Config{useperlio};
}

build_prepare($mp_gen, $perl_gen);
warn "Goind to build against mod_perl/$mod_perl::VERSION Perl/$]\n";

test_configure($mp_gen);

my %prereq = (
     'Apache::Test' => 1.01,
     'Devel::Peek'  => 0.96,
);

my %common_opts = (
     NAME         => "Apache::Peek",
     VERSION_FROM => "Peek.pm",
     XSPROTOARG   => '-noprototypes',
     DEFINE       => '-DMOD_PERL',
     clean        => { FILES => "@clean_files", },
     PREREQ_PM    => \%prereq,
);

if ($mp_gen == 1) {
     require Apache::src;
     my $inc = Apache::src->new->inc;
     die "Can't find mod_perl header files installed" unless $inc;

     require ExtUtils::MakeMaker;
     ExtUtils::MakeMaker::WriteMakefile(
         INC	     => $inc,
         LIBS         => [''],
         %common_opts,
     );

}
else {
     require ModPerl::MM;
     ModPerl::MM::WriteMakefile(
         %common_opts,
     );
}

sub build_prepare {
     my($mp_gen, $perl_gen) = @_;

     my $xs = "Peek.xs";
     my $pm = "Peek.pm";
     push @clean_files, ($pm, $xs);

     # now put together the build
     my %files = map { $_ => join '.', $_, "mp$mp_gen", "perl$perl_gen" }
         ($pm, $xs);

     unlink $xs if -e $xs;
     if (DEVEL and eval { symlink("", ""); 1 }) {
         # so that it's easier to modify/rebuild w/o re-running Makefile.PL
         symlink $files{$xs}, $xs
             or die "Couldn't symlink $files{$xs} => $xs: $!";
     } else {
         # copy the xs file as is
         require File::Copy;
         File::Copy::copy($files{$xs}, $xs);
     }

     # adjust the version and glue the doc (open() for 5.005_03 support)
     my ($in, $out) = ($files{$pm}, $pm);
     my ($ifh, $ofh) = (Symbol::gensym(), Symbol::gensym());
     open $ifh,  "<$in"  or die "can't open $in: $!";
     open $ofh, ">$out" or die "can't open $out: $!";
     print $ofh "# WARNING: DO NOT EDIT THIS FILE, EDIT $in instead\n\n";
     while (<$ifh>) {
         s/(.*\$VERSION\s*=).*/$1 $VERSION;/;
         print $ofh $_;
     }
     print $ofh <DATA>;
     close $ifh;
     close $ofh;
}

sub test_configure {
     my $mp_gen = shift;

     if (eval { require Apache::TestMM }) {
         Apache::TestMM->import(qw(test clean));
         my @scripts = qw(t/TEST);
         # accept the configs from command line
         Apache::TestMM::filter_args();

         Apache::TestMM::generate_script($_) for @scripts;

         push @clean_files, @scripts;

         my $httpd;
         # mp2 already knows its
         if ($mp_gen == 1) {
#        require Apache::test;
#        # can't really use get_test_params, since it may pick the wrong httpd
#        # must explicitly ask for the path to httpd
#        my %params = Apache::test->get_test_params;
#        $common_opts{macro}{APACHE} = $httpd;
         }
     } else {
         warn "***: You should install Apache::Test to do real testing\n";
         # META: soon on CPAN
         *MY::test = sub {
             return <<'EOF';
test : pure_all
	@echo \*** This test suite requires Apache::Test available from the
	@echo \*** mod_perl 2.0 sources or the httpd-test distribution.
EOF
         }
     }
}

sub satisfy_perl_generation {
       eval { require 5.8.0 }    ? "5.8"
     : eval { require 5.6.0 }    ? "5.6"
     : eval { require 5.005_03 } ? "5.5"
     : die "Perl version $] is unsupported";
}


# If a specific generation was passed as an argument,
#     if satisfied
#         return the same generation
#     else
#         die
# else @ARGV and %ENV will be checked for specific orders
#     if the specification will be found
#         if satisfied
#             return the specified generation
#         else
#             die
#     else if any mp generation is found
#              return it
#           else
#              die
sub satisfy_mp_generation {
     my $wanted = shift || wanted_mp_generation();

     unless ($wanted == 1 || $wanted == 2) {
         die "don't know anything about mod_perl generation: $wanted\n" .
             "currently supporting only generations 1 and 2";
     }

     my $selected = 0;

     if ($wanted == 1) {
         require_mod_perl();
         if ($mod_perl::VERSION >= 1.99) {
             # so we don't pick 2.0 version if 1.0 is wanted
             die "You don't seem to have mod_perl 1.0 installed";
         }
         $selected = 1;
     }
     elsif ($wanted == 2) {
         #warn "Looking for mod_perl 2.0";
         require Apache2;
         require_mod_perl();
         if ($mod_perl::VERSION < 1.99) {
             die "You don't seem to have mod_perl 2.0 installed";
         }
         $selected = 2;
     }
     else {
         require_mod_perl();
         $selected = $mod_perl::VERSION >= 1.99 ? 2 : 1;
         warn "Using $mod_perl::VERSION\n";
     }

     return $selected;
}

sub require_mod_perl {
     eval { require mod_perl };
     die "Can't find mod_perl installed\nThe error was: $@" if $@;
}

# the function looks at %ENV and Makefile.PL option to figure out
# whether a specific mod_perl generation was requested.
# It uses the following logic:
# via options:
# perl Makefile.PL MOD_PERL=2
# or via %ENV:
# env MOD_PERL=1 perl Makefile.PL
#
# return value is:
# 1 or 2 if the specification was found (mp 1 and mp 2 respectively)
# 0 otherwise
sub wanted_mp_generation {

     # check if we have a command line specification
     # flag: 0: unknown, 1: mp1, 2: mp2
     my $flag = 0;
     my @pass;
     while (@ARGV) {
         my $key = shift @ARGV;
         if ($key =~ /^MOD_PERL=(\d)$/) {
             $flag = $1;
         }
         else {
             push @pass, $key;
         }
     }
     @ARGV = @pass;

     # check %ENV
     my $env = exists $ENV{MOD_PERL} ? $ENV{MOD_PERL} : 0;

     # check for contradicting requirements
     if ($env && $flag && $flag != $env) {
         die <<EOF;
Can\'t decide which mod_perl version should be used, since you have
supplied contradicting requirements:
     enviroment variable MOD_PERL=$env
     Makefile.PL option  MOD_PERL=$flag
EOF
     }

     my $wanted = 0;
     $wanted = 2 if $env == 2 || $flag == 2;
     $wanted = 1 if $env == 1 || $flag == 1;

     unless ($wanted) {
         # if still unknown try to require mod_perl.pm
         eval { require mod_perl };
         unless ($@) {
             $wanted = $mod_perl::VERSION >= 1.99 ? 2 : 1;
         }
     }

     return $wanted;
}

1;


__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: rfc: ModPerl::ModuleSetup

Posted by Stas Bekman <st...@stason.org>.
Geoffrey Young wrote:
>>Here is Makefile.PL from Apache-Peek, most of which should be moved to
>>that module. I'm talking about functions:
>>
>>satisfy_mp_generation;
>>satisfy_perl_generation;
>>wanted_mp_generation;
>>
> 
> the outer functions look ok.  I'd leave satsify_perl_generation for the
> users themselves, at least in it's current state.

Thanks Geoff,

So the remaining issue is where to put this module. As I suggested before it 
shouldn't go into Apache2/ but to the normal @INC. So that Makefile.PL can 
find it without trying to load Apache2, for mod_perl 1.x modules.

Since it'll be distributed with mp2, users who have no mp2 won't have it and I 
think it's fine. So the 3rd party module author can do:

eval { require ModPerl::ModuleSetup }

and if that has failed then the user has only mp1 installed and so should 
Makefile.PL proceed with the build against mp1, otherwise if successful use
satisfy_mp_generation to figure out which version to build against.

We might release it on CPAN too or/and bundle with mp1 as well later on.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: rfc: ModPerl::ModuleSetup

Posted by Geoffrey Young <ge...@modperlcookbook.org>.
> Here is Makefile.PL from Apache-Peek, most of which should be moved to
> that module. I'm talking about functions:
> 
> satisfy_mp_generation;
> satisfy_perl_generation;
> wanted_mp_generation;
> 
the outer functions look ok.  I'd leave satsify_perl_generation for the
users themselves, at least in it's current state.

--Geoff







---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org