home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / BuildMM.pm < prev    next >
Encoding:
Perl POD Document  |  2004-09-17  |  11.7 KB  |  407 lines

  1. # Copyright 2003-2004 The Apache Software Foundation
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. #     http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. #
  15. package ModPerl::BuildMM;
  16.  
  17. use strict;
  18. use warnings;
  19.  
  20. use ExtUtils::MakeMaker ();
  21. use Cwd ();
  22. use File::Spec::Functions qw(catdir catfile splitdir);
  23. use File::Basename;
  24. use File::Find;
  25.  
  26. use Apache::Build ();
  27. use ModPerl::MM;
  28.  
  29. our %PM; #add files to installation
  30.  
  31. # MM methods that this package overrides
  32. no strict 'refs';
  33. my $stash = \%{__PACKAGE__ . '::MY::'};
  34. my @methods = grep *{$stash->{$_}}{CODE}, keys %$stash;
  35. ModPerl::MM::override_eu_mm_mv_all_methods(@methods);
  36. use strict 'refs';
  37.  
  38. my $apache_test_dir = catdir Cwd::getcwd(), "Apache-Test", "lib";
  39.  
  40. #to override MakeMaker MOD_INSTALL macro
  41. sub mod_install {
  42.     q{$(PERL) -I$(INST_LIB) -I$(PERL_LIB) \\}."\n" .
  43.     qq{-I$apache_test_dir -MModPerl::BuildMM \\}."\n" .
  44.     q{-e "ModPerl::MM::install({@ARGV},'$(VERBINST)',0,'$(UNINST)');"}."\n";
  45. }
  46.  
  47. sub build_config {
  48.     my $key = shift;
  49.     my $build = Apache::Build->build_config;
  50.     return $build unless $key;
  51.     $build->{$key};
  52. }
  53.  
  54. #the parent WriteMakefile moves MY:: methods into a different class
  55. #so alias them each time WriteMakefile is called in a subdir
  56.  
  57. sub my_import {
  58.     no strict 'refs';
  59.     my $stash = \%{__PACKAGE__ . '::MY::'};
  60.     for my $sym (keys %$stash) {
  61.         next unless *{$stash->{$sym}}{CODE};
  62.         my $name = "MY::$sym";
  63.         undef &$name if defined &$name;
  64.         *$name = *{$stash->{$sym}}{CODE};
  65.     }
  66. }
  67.  
  68. sub WriteMakefile {
  69.     my %args = @_;
  70.  
  71.     my $build = build_config();
  72.     ModPerl::MM::my_import(__PACKAGE__);
  73.  
  74.     my $inc = $build->inc;
  75.     if (my $glue_inc = $build->{MP_XS_GLUE_DIR}) {
  76.         for (split /\s+/, $glue_inc) {
  77.             $inc .= " -I$_";
  78.         }
  79.     }
  80.  
  81.     my $libs;
  82.     my @libs = ();
  83.     if (Apache::Build::BUILD_APREXT) {
  84.         # in order to decouple APR/APR::* from mod_perl.so,
  85.         # link these modules against the static MP_APR_LIB lib,
  86.         # rather than the mod_perl lib (which would demand mod_perl.so
  87.         # be available). For other modules, use mod_perl.lib as
  88.         # usual. This is done for APR in xs/APR/APR/Makefile.PL.
  89.         my $name = $args{NAME};
  90.         if ($name =~ /^APR::\w+$/) {
  91.             @libs = ($build->apache_libs, $build->mp_apr_lib);
  92.         }
  93.         else {
  94.             @libs = ($build->apache_libs, $build->modperl_libs);
  95.         }
  96.     }
  97.     else {
  98.         @libs = ($build->apache_libs, $build->modperl_libs);
  99.     }
  100.     $libs = join ' ', @libs;
  101.  
  102.     my $ccflags = $build->perl_ccopts . $build->ap_ccopts;
  103.  
  104.     my @opts = (
  105.         INC       => $inc,
  106.         CCFLAGS   => $ccflags,
  107.         OPTIMIZE  => $build->perl_config('optimize'),
  108.         LDDLFLAGS => $build->perl_config('lddlflags'),
  109.         LIBS      => $libs,
  110.         dynamic_lib => { OTHERLDFLAGS => $build->otherldflags },
  111.     );
  112.  
  113.     my @typemaps;
  114.     my $pwd = Cwd::fastcwd();
  115.     for ('xs', $pwd, "$pwd/..") {
  116.         my $typemap = $build->file_path("$_/typemap");
  117.         if (-e $typemap) {
  118.             push @typemaps, $typemap;
  119.         }
  120.     }
  121.     push @opts, TYPEMAPS => \@typemaps if @typemaps;
  122.  
  123.     my $clean_files = (exists $args{clean} && exists $args{clean}{FILES}) ?
  124.         $args{clean}{FILES} : '';
  125.     $clean_files .= " glue_pods"; # cleanup the dependency target
  126.     $args{clean}{FILES} = $clean_files;
  127.  
  128.     ExtUtils::MakeMaker::WriteMakefile(@opts, %args);
  129. }
  130.  
  131. my %always_dynamic = map { $_, 1 }
  132.   qw(ModPerl::Const Apache::Const APR::Const APR APR::PerlIO);
  133.  
  134. sub ModPerl::BuildMM::MY::constants {
  135.     my $self = shift;
  136.     my $build = build_config();
  137.  
  138.     #install everything relative to the Apache2/ subdir
  139.     if ($build->{MP_INST_APACHE2}) {
  140.         $self->{INST_ARCHLIB} = catdir $self->{INST_ARCHLIB}, 'Apache2';
  141.         $self->{INST_LIB} = catdir $self->{INST_LIB}, 'Apache2';
  142.     }
  143.  
  144.     #"discover" xs modules.  since there is no list hardwired
  145.     #any module can be unpacked in the mod_perl-2.xx directory
  146.     #and built static
  147.  
  148.     #this stunt also make it possible to leave .xs files where
  149.     #they are, unlike 1.xx where *.xs live in src/modules/perl
  150.     #and are copied to subdir/ if DYNAMIC=1
  151.  
  152.     if ($build->{MP_STATIC_EXTS}) {
  153.         #skip .xs -> .so if we are linking static
  154.         my $name = $self->{NAME};
  155.         unless ($always_dynamic{$name}) {
  156.             if (my($xs) = keys %{ $self->{XS} }) {
  157.                 $self->{HAS_LINK_CODE} = 0;
  158.                 print "$name will be linked static\n";
  159.                 #propagate static xs module to src/modules/perl/Makefile
  160.                 $build->{XS}->{$name} =
  161.                   join '/', Cwd::fastcwd(), $xs;
  162.                 $build->save;
  163.             }
  164.         }
  165.     }
  166.  
  167.     $self->MM::constants;
  168. }
  169.  
  170. sub ModPerl::BuildMM::MY::top_targets {
  171.     my $self = shift;
  172.     my $string = $self->MM::top_targets;
  173.  
  174.     return $string;
  175. }
  176.  
  177. sub ModPerl::BuildMM::MY::postamble {
  178.     my $self = shift;
  179.  
  180.     my $doc_root = catdir Cwd::getcwd(), "docs", "api";
  181.  
  182.     my @targets = ();
  183.  
  184.     # reasons for glueing pods to the respective .pm files:
  185.     # - manpages will get installed over the mp1 manpages and vice
  186.     #   versa. glueing pods avoids creation of manpages, but may be we
  187.     #   could just tell make to skip manpages creation?
  188.     # if pods are installed directly they need to be also redirected,
  189.     # some into Apache2/ others (e.g. Apache2) not
  190.  
  191.     # add the code to glue the existing pods to the .pm files in blib.
  192.     # create a dependency on pm_to_blib subdirs linkext targets to
  193.     # allow 'make -j'
  194.     my @target = ('glue_pods: pm_to_blib subdirs linkext');
  195.  
  196.     if (-d $doc_root) {
  197.         my $build = build_config();
  198.  
  199.         # those living in modperl-2.0/lib are already nicely mapped
  200.         my %pms = %{ $self->{PM} };
  201.  
  202.         my $cwd = Cwd::getcwd();
  203.         my $blib_dir = catdir qw(blib lib);
  204.         $blib_dir = catdir $blib_dir, "Apache2"
  205.             if $build->{MP_INST_APACHE2};
  206.  
  207.         # those autogenerated under WrapXS/
  208.         # those living under xs/
  209.         # those living under ModPerl-Registry/lib/
  210.         my @src = ('WrapXS', 'xs', catdir(qw(ModPerl-Registry lib)));
  211.  
  212.         for my $base (@src) {
  213.             chdir $base;
  214.             my @files = ();
  215.             find({ no_chdir => 1,
  216.                    wanted => sub { push @files, $_ if /.pm$/ },
  217.                  }, ".");
  218.             chdir $cwd;
  219.  
  220.             for (@files) {
  221.                 my $pm = catfile $base, $_;
  222.                 my $blib;
  223.                 if ($base =~ /^(xs|WrapXS)/) {
  224.                     my @segm = splitdir $_;
  225.                     splice @segm, -2, 1; # xs/APR/Const/Const.pm
  226.                     splice @segm, -2, 1 if /APR.pm/; # odd case
  227.                     $blib = catfile $blib_dir, @segm;
  228.                 }
  229.                 else {
  230.                     $blib = catfile $blib_dir, $_;
  231.                 }
  232.                 $pms{$pm} = $blib;
  233.             }
  234.         }
  235.  
  236.         while (my($pm, $blib) = each %pms) {
  237.             my @segm = splitdir $blib;
  238.             for my $i (1..2) {
  239.                 # try APR.pm and APR/Bucket.pm
  240.                 my $pod = catdir(@segm[-$i .. -1]);
  241.                 $pod =~ s/\.pm/\.pod/;
  242.                 my $podpath = catfile $doc_root, $pod;
  243.                 next unless -r $podpath;
  244.  
  245.                 push @target, 
  246.                     '$(FULLPERL) -I$(INST_LIB) ' .
  247.                     "-I$apache_test_dir -MModPerl::BuildMM " .
  248.                     "-e ModPerl::BuildMM::glue_pod $pm $podpath $blib";
  249.             }
  250.         }
  251.  
  252.         push @target, $self->{NOECHO} . '$(TOUCH) $@';
  253.     }
  254.     else {
  255.         # we don't have the docs sub-cvs repository extracted, skip
  256.         # the docs gluing
  257.         push @target, $self->{NOECHO} . '$(NOOP)';
  258.     }
  259.     push @targets, join "\n\t", @target;
  260.  
  261. #    # next target: cleanup the dependency file
  262. #    @target = ('glue_pods_clean:');
  263. #    push @target, '$(RM_F) glue_pods';
  264. #    push @targets, join "\n\t", @target;
  265.  
  266.     return join "\n\n", @targets, '';
  267. }
  268.  
  269. sub glue_pod {
  270.  
  271.     die "expecting 3 arguments: pm, pod, dst" unless @ARGV == 3;
  272.     my($pm, $pod, $dst) = @ARGV;
  273.  
  274.     die "glue_pod: can't find $pm"  unless -e $pm;
  275.     die "glue_pod: can't find $dst" unless -e $dst;
  276.  
  277.     # have we already glued the doc?
  278.     exit 0 unless -s $pm == -s $dst;
  279.  
  280.     # ExtUtils::Install::pm_to_blib removes the 'w' perms, so we can't
  281.     # just append the doc there
  282.     my $orig_mode = (stat $dst)[2];
  283.     my $rw_mode   = 0666;
  284.  
  285.     chmod $rw_mode, $dst      or die "Can't chmod $rw_mode $dst: $!";
  286.     open my $pod_fh, "<$pod"  or die "Can't open $pod: $!";
  287.     open my $dst_fh, ">>$dst" or die "Can't open $dst: $!";
  288.     print $dst_fh "\n"; # must add one line separation
  289.     print $dst_fh (<$pod_fh>);
  290.     close $pod_fh;
  291.     close $dst_fh;
  292.     # restore the perms
  293.     chmod $orig_mode, $dst    or die "Can't chmod $orig_mode $dst: $!";
  294. }
  295.  
  296. sub ModPerl::BuildMM::MY::post_initialize {
  297.     my $self = shift;
  298.     my $build = build_config();
  299.     my $pm = $self->{PM};
  300.  
  301.     while (my($k, $v) = each %PM) {
  302.         if (-e $k) {
  303.             $pm->{$k} = $v;
  304.         }
  305.     }
  306.  
  307.     # prefix typemap with Apache/ so when installed in the
  308.     # perl-lib-tree it won't be picked by non-mod_perl modules
  309.     if (exists $pm->{'lib/typemap'} ) {
  310.         $pm->{'lib/typemap'} = '$(INST_ARCHLIB)/auto/Apache/typemap';
  311.     }
  312.  
  313.     #not everything in MakeMaker uses INST_LIB
  314.     #so we have do fixup a few PMs to make sure *everything*
  315.     #gets installed into Apache2/
  316.     if ($build->{MP_INST_APACHE2}) {
  317.         while (my($k, $v) = each %$pm) {
  318.             #up one from the Apache2/ subdir
  319.             #so it can be found for 'use Apache2 ()'
  320.             next if $v =~ /Apache2\.pm$/;
  321.  
  322.             # another module generated by A-T that needs to go to the
  323.             # normal @INC
  324.             next if $v =~ /TestConfigData\.pm$/;
  325.  
  326.             #move everything else to the Apache2/ subdir
  327.             #unless already specified with \$(INST_LIB)
  328.             #or already in Apache2/
  329.             unless ($v =~ /Apache2/) {
  330.                 $v =~ s{ (blib[/\\:]lib) }{ catdir $1, 'Apache2'}xe;
  331.             }
  332.  
  333.             $pm->{$k} = $v;
  334.         }
  335.     }
  336.  
  337.     '';
  338. }
  339.  
  340. sub ModPerl::BuildMM::MY::libscan {
  341.     my($self, $path) = @_;
  342.  
  343.     my $apr_config = build_config()->get_apr_config();
  344.  
  345.     if ($path =~ m/(Thread|Global)Mutex/) {
  346.         return unless $apr_config->{HAS_THREADS};
  347.     }
  348.  
  349.     return '' if $path =~ m/\.(pl|cvsignore)$/;
  350.     return '' if (basename dirname $path) eq 'CVS';
  351.     return '' if $path =~ m/~$/;
  352.  
  353.     $path;
  354. }
  355.  
  356. 1;
  357.  
  358. =head1 NAME
  359.  
  360. ModPerl::BuildMM -- A "subclass" of ModPerl::MM used for building mod_perl 2.0
  361.  
  362. =head1 SYNOPSIS
  363.  
  364.   use ModPerl::BuildMM;
  365.   
  366.   # ModPerl::BuildMM takes care of doing all the dirty job of overriding 
  367.   ModPerl::BuildMM::WriteMakefile(...);
  368.  
  369.   # if there is a need to extend the methods 
  370.   sub MY::postamble {
  371.       my $self = shift;
  372.   
  373.       my $string = $self->ModPerl::BuildMM::MY::postamble;
  374.   
  375.       $string .= "\nmydist : manifest tardist\n";
  376.   
  377.       return $string;
  378.   }
  379.  
  380.  
  381. =head1 DESCRIPTION
  382.  
  383. C<ModPerl::BuildMM> is a "subclass" of C<ModPerl::MM> used for
  384. building mod_perl 2.0. Refer to
  385. C<L<ModPerl::MM|docs::2.0::api::ModPerl::MM>> manpage.
  386.  
  387. =head1 OVERRIDEN METHODS
  388.  
  389. C<ModPerl::BuildMM> overrides the following methods:
  390.  
  391. =head2 C<ModPerl::BuildMM::MY::constants>
  392.  
  393.  
  394. =head2 C<ModPerl::BuildMM::MY::top_targets>
  395.  
  396.  
  397. =head2 C<ModPerl::BuildMM::MY::postamble>
  398.  
  399.  
  400. =head2 C<ModPerl::BuildMM::MY::post_initialize>
  401.  
  402.  
  403. =head2 C<ModPerl::BuildMM::MY::libscan>
  404.  
  405.  
  406. =cut
  407.