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 / TestBuild.pm < prev    next >
Encoding:
Perl POD Document  |  2004-08-06  |  14.4 KB  |  699 lines

  1. # Copyright 2002-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 Apache::TestBuild;
  16.  
  17. use strict;
  18. use warnings FATAL => 'all';
  19.  
  20. use subs qw(system chdir
  21.             info warning);
  22.  
  23. use Config;
  24. use File::Spec::Functions;
  25. use File::Path ();
  26. use Cwd ();
  27.  
  28. use constant DRYRUN => 0;
  29.  
  30. my @min_modules = qw(access auth log-config env mime setenvif
  31.                      mime autoindex dir alias);
  32.  
  33. my %shared_modules = (
  34.     min  => join(' ', @min_modules),
  35. );
  36.  
  37. my %configs = (
  38.     all => {
  39.         'apache-1.3' => [],
  40.         'httpd-2.0' => enable20(qw(modules=all proxy)),
  41.     },
  42.     most => {
  43.         'apache-1.3' => [],
  44.         'httpd-2.0' => enable20(qw(modules=most)),
  45.     },
  46.     min => {
  47.         'apache-1.3' => [],
  48.         'httpd-2.0' => enable20(@min_modules),
  49.     },
  50.     exp => {
  51.         'apache-1.3' => [],
  52.         'httpd-2.0' => enable20(qw(example case_filter
  53.                                    case_filter_in cache
  54.                                    echo deflate bucketeer)),
  55.     },
  56. );
  57.  
  58. my %builds = (
  59.      default => {
  60.          cflags => '-Wall',
  61.          config => {
  62.              'apache-1.3' => [],
  63.              'httpd-2.0'  => [],
  64.          },
  65.      },
  66.      debug => {
  67.          cflags => '-g',
  68.          config => {
  69.              'apache-1.3' => [],
  70.              'httpd-2.0'  => [qw(--enable-maintainer-mode)],
  71.          },
  72.      },
  73.      prof => {
  74.          cflags => '-pg -DGPROF',
  75.      },
  76.      shared => {
  77.          config =>  {
  78.              'apache-1.3' => [],
  79.              'httpd-2.0'  => enable20_shared('all'),
  80.          },
  81.      },
  82.      mostshared => {
  83.          config =>  {
  84.              'apache-1.3' => [],
  85.              'httpd-2.0'  => enable20_shared('most'),
  86.          },
  87.      },
  88.      minshared => {
  89.          config =>  {
  90.              'apache-1.3' => [],
  91.              'httpd-2.0'  => enable20_shared('min'),
  92.          },
  93.      },
  94.      static => {
  95.      },
  96. );
  97.  
  98. my %mpms = (
  99.     default => [qw(prefork worker)],
  100.     MSWin32 => [qw(winnt)],
  101. );
  102.  
  103. my @cvs = qw(httpd-2.0 apache-1.3);
  104.  
  105. my @dirs = qw(build tar src install);
  106.  
  107. sub enable20 {
  108.     [ map { "--enable-$_" } @_ ];
  109. }
  110.  
  111. sub enable20_shared {
  112.     my $name = shift;
  113.     my $modules = $shared_modules{$name} || $name;
  114.     enable20(qq(mods-shared="$modules"));
  115. }
  116.  
  117. sub default_mpms {
  118.     $mpms{ $^O } || $mpms{'default'};
  119. }
  120.  
  121. sub default_dir {
  122.     my($self, $dir) = @_;
  123.     $self->{$dir} ||= catdir $self->{prefix}, $dir,
  124. }
  125.  
  126. sub new {
  127.     my $class = shift;
  128.  
  129.     #XXX: not generating a BUILD script yet
  130.     #this way we can run:
  131.     #perl Apache-Test/lib/Apache/TestBuild.pm --cvsroot=anon --foo=...
  132.  
  133.     require Apache::TestConfig;
  134.     require Apache::TestTrace;
  135.     Apache::TestTrace->import;
  136.  
  137.     my $self = bless {
  138.         prefix => '/usr/local/apache',
  139.         cwd => Cwd::cwd(),
  140.         cvsroot => 'cvs.apache.org:/home/cvs',
  141.         cvs => \@cvs,
  142.         cvstag => "",
  143.         ssldir => "",
  144.         mpms => default_mpms(),
  145.         make => $Config{make},
  146.         builds => {},
  147.         name => "",
  148.         extra_config => {
  149.             'httpd-2.0' => [],
  150.         },
  151.         @_,
  152.     }, $class;
  153.  
  154.     #XXX
  155.     if (my $c = $self->{extra_config}->{'2.0'}) {
  156.         $self->{extra_config}->{'httpd-2.0'} = $c;
  157.     }
  158.  
  159.     for my $dir (@dirs) {
  160.         $self->default_dir($dir);
  161.     }
  162.  
  163.     if ($self->{ssldir}) {
  164.         push @{ $self->{extra_config}->{'httpd-2.0'} },
  165.           '--enable-ssl', "--with-ssl=$self->{ssldir}";
  166.     }
  167.  
  168.     $self;
  169. }
  170.  
  171. sub init {
  172.     my $self = shift;
  173.  
  174.     for my $dir (@dirs) {
  175.         mkpath($self->{$dir});
  176.     }
  177. }
  178.  
  179. use subs qw(symlink unlink);
  180. use File::Basename;
  181. use File::Find;
  182.  
  183. sub symlink_tree {
  184.     my $self = shift;
  185.  
  186.     my $httpd = 'httpd';
  187.     my $install = "$self->{install}/bin/$httpd";
  188.     my $source  = "$self->{build}/.libs/$httpd";
  189.  
  190.     unlink $install;
  191.     symlink $source, $install;
  192.  
  193.     my %dir = (apr => 'apr',
  194.                aprutil => 'apr-util');
  195.  
  196.     for my $libname (qw(apr aprutil)) {
  197.         my $lib = "lib$libname.so.0.0.0";
  198.         my $install = "$self->{install}/lib/$lib";
  199.         my $source  = "$self->{build}/srclib/$dir{$libname}/.libs/$lib";
  200.  
  201.         unlink $install;
  202.         symlink $source, $install;
  203.     }
  204.  
  205.     $install = "$self->{install}/modules";
  206.     $source  = "$self->{build}/modules";
  207.  
  208.     for (<$install/*.so>) {
  209.         unlink $_;
  210.     }
  211.  
  212.     finddepth(sub {
  213.         return unless /\.so$/;
  214.         my $file = "$File::Find::dir/$_";
  215.         symlink $file, "$install/$_";
  216.     }, $source);
  217. }
  218.  
  219. sub unlink {
  220.     my $file = shift;
  221.  
  222.     if (-e $file) {
  223.         print "unlink $file\n";
  224.     }
  225.     else {
  226.         print "$file does not exist\n";
  227.     }
  228.     CORE::unlink($file);
  229. }
  230.  
  231. sub symlink {
  232.     my($from, $to) = @_;
  233.     print "symlink $from => $to\n";
  234.     unless (-e $from) {
  235.         print "source $from does not exist\n";
  236.     }
  237.     my $base = dirname $to;
  238.     unless (-e $base) {
  239.         print "target dir $base does not exist\n";
  240.     }
  241.     CORE::symlink($from, $to) or die $!;
  242. }
  243.  
  244. sub cvs {
  245.     my $self = shift;
  246.  
  247.     my $cmd = "cvs -d $self->{cvsroot} @_";
  248.  
  249.     if (DRYRUN) {
  250.         info "$cmd";
  251.     }
  252.     else {
  253.         system $cmd;
  254.     }
  255. }
  256.  
  257. my %cvs_names = (
  258.     '2.0' => 'httpd-2.0',
  259.     '1.3' => 'apache-1.3',
  260. );
  261.  
  262. my %cvs_snames = (
  263.     '2.0' => 'httpd',
  264.     '1.3' => 'apache',
  265. );
  266.  
  267. sub cvs_up {
  268.     my($self, $version) = @_;
  269.  
  270.     my $name = $cvs_names{$version};
  271.  
  272.     my $dir = $self->srcdir($version);
  273.  
  274.     if ($self->{cvsroot} eq 'anon') {
  275.         $self->{cvsroot} = ':pserver:anoncvs@cvs.apache.org:/home/cvspublic';
  276.         unless (-d $dir) {
  277.             #XXX do something better than doesn't require prompt if
  278.             #we already have an entry in ~/.cvspass
  279.             #$self->cvs('login');
  280.  
  281.             warning "may need to run the following command ",
  282.                     "(password is 'anoncvs')";
  283.             warning "cvs -d $self->{cvsroot} login";
  284.         }
  285.     }
  286.  
  287.     if (-d $dir) {
  288.         chdir $dir;
  289.         $self->cvs(up => "-dP $self->{cvstag}");
  290.         return;
  291.     }
  292.  
  293.     my $co = checkout($name);
  294.     $self->$co($name, $dir);
  295.  
  296.     my $post = post_checkout($name);
  297.     $self->$post($name, $dir);
  298. }
  299.  
  300. sub checkout_httpd_2_0 {
  301.     my($self, $name, $dir) = @_;
  302.  
  303.     my $tag = $self->{cvstag};
  304.  
  305.     $self->cvs(co => "-d $dir $tag $name");
  306.     chdir "$dir/srclib";
  307.     $self->cvs(co => "$tag apr apr-util");
  308. }
  309.  
  310. sub checkout_apache_1_3 {
  311.     my($self, $name, $dir) = @_;
  312.  
  313.     $self->cvs(co => "-d $dir $self->{cvstag} $name");
  314. }
  315.  
  316. sub post_checkout_httpd_2_0 {
  317.     my($self, $name, $dir) = @_;
  318. }
  319.  
  320. sub post_checkout_apache_1_3 {
  321. }
  322.  
  323. sub canon {
  324.     my $name = shift;
  325.     return $name unless $name;
  326.     $name =~ s/[.-]/_/g;
  327.     $name;
  328. }
  329.  
  330. sub checkout {
  331.     my $name = canon(shift);
  332.     \&{"checkout_$name"};
  333. }
  334.  
  335. sub post_checkout {
  336.     my $name = canon(shift);
  337.     \&{"post_checkout_$name"};
  338. }
  339.  
  340. sub cvs_update {
  341.     my $self = shift;
  342.  
  343.     my $cvs = shift || $self->{cvs};
  344.  
  345.     chdir $self->{src};
  346.  
  347.     for my $name (@$cvs) {
  348.         $self->cvs_up($name);
  349.     }
  350. }
  351.  
  352. sub merge_build {
  353.     my($self, $version, $builds, $configs) = @_;
  354.  
  355.     my $b = {
  356.         cflags => $builds{default}->{cflags},
  357.         config => [ @{ $builds{default}->{config}->{$version} } ],
  358.     };
  359.  
  360.     for my $name (@$builds) {
  361.         next if $name eq 'default'; #already have this
  362.  
  363.         if (my $flags = $builds{$name}->{cflags}) {
  364.             $b->{cflags} .= " $flags";
  365.         }
  366.         if (my $cfg = $builds{$name}->{config}) {
  367.             if (my $vcfg = $cfg->{$version}) {
  368.                 push @{ $b->{config} }, @$vcfg;
  369.             }
  370.         }
  371.     }
  372.  
  373.     for my $name (@$configs) {
  374.         my $cfg = $configs{$name}->{$version};
  375.         next unless $cfg;
  376.         push @{ $b->{config} }, @$cfg;
  377.     }
  378.  
  379.     if (my $ex = $self->{extra_config}->{$version}) {
  380.         push @{ $b->{config} }, @$ex;
  381.     }
  382.  
  383.     if (my $ex = $self->{extra_cflags}->{$version}) {
  384.         $b->{config} .= " $ex";
  385.     }
  386.  
  387.     $b;
  388. }
  389.  
  390. my @srclib_dirs = qw(
  391.     apr apr-util apr-util/xml/expat pcre
  392. );
  393.  
  394. sub install_name {
  395.     my($self, $builds, $configs, $mpm) = @_;
  396.  
  397.     return $self->{name} if $self->{name};
  398.  
  399.     my $name = join '-', $mpm, @$builds, @$configs;
  400.  
  401.     if (my $tag = $self->cvs_name) {
  402.         $name .= "-$tag";
  403.     }
  404.  
  405.     $name;
  406. }
  407.  
  408. #currently the httpd-2.0 build does not properly support static linking
  409. #of ssl libs, force the issue
  410. sub add_ssl_libs {
  411.     my $self = shift;
  412.  
  413.     my $ssldir = $self->{ssldir};
  414.  
  415.     return unless $ssldir and -d $ssldir;
  416.  
  417.     my $name = $self->{current_install_name};
  418.  
  419.     my $ssl_mod = "$name/modules/ssl";
  420.     info "editing $ssl_mod/modules.mk";
  421.  
  422.     if (DRYRUN) {
  423.         return;
  424.     }
  425.  
  426.     my $ssl_mk = "$self->{build}/$ssl_mod/modules.mk";
  427.  
  428.     open my $fh, $ssl_mk or die "open $ssl_mk: $!";
  429.     my @lines = <$fh>;
  430.     close $fh;
  431.  
  432.     for (@lines) {
  433.         next unless /SH_LINK/;
  434.         chomp;
  435.         $_ .= " -L$ssldir -lssl -lcrypto\n";
  436.         info 'added ssl libs';
  437.         last;
  438.     }
  439.  
  440.     open $fh, '>', $ssl_mk or die $!;
  441.     print $fh join "\n", @lines;
  442.     close $fh;
  443. }
  444.  
  445. sub cvs_name {
  446.     my $self = shift;
  447.  
  448.     if (my $tag = $self->{cvstag}) {
  449.         $tag =~ s/^-[DAr]//;
  450.         $tag =~ s/\"//g;
  451.         $tag =~ s,[/ :],_,g; #-D"03/29/02 07:00pm"
  452.         return $tag;
  453.     }
  454.  
  455.     return "";
  456. }
  457.  
  458. sub srcdir {
  459.     my($self, $src) = @_;
  460.  
  461.     my $prefix = "";
  462.     if ($src =~ s/^(apache|httpd)-//) {
  463.         $prefix = $1;
  464.     }
  465.     else {
  466.         $prefix = $cvs_snames{$src};
  467.     }
  468.  
  469.     if ($src =~ /^\d\.\d$/) {
  470.         #release version will be \d\.\d\.\d+
  471.         if (my $tag = $self->cvs_name) {
  472.             $src .= "-$tag";
  473.         }
  474.         $src .= '-cvs';
  475.     }
  476.  
  477.     join '-', $prefix, $src;
  478. }
  479.  
  480. sub configure_httpd_2_0 {
  481.     my($self, $src, $builds, $configs, $mpm) = @_;
  482.  
  483.     $src = $self->srcdir($src);
  484.  
  485.     chdir $self->{build};
  486.  
  487.     my $name = $self->install_name($builds, $configs, $mpm);
  488.  
  489.     $self->{current_install_name} = $name;
  490.  
  491.     $self->{builds}->{$name} = 1;
  492.  
  493.     if ($self->{fresh}) {
  494.         rmtree($name);
  495.     }
  496.     else {
  497.         if (-e "$name/.DONE") {
  498.             warning "$name already configured";
  499.             warning "rm $name/.DONE to force";
  500.             return;
  501.         }
  502.     }
  503.  
  504.     my $build = $self->merge_build('httpd-2.0', $builds, $configs);
  505.  
  506.     $ENV{CFLAGS} = $build->{cflags};
  507.     info "CFLAGS=$ENV{CFLAGS}";
  508.  
  509.     my $prefix = "$self->{install}/$name";
  510.  
  511.     rmtree($prefix) if $self->{fresh};
  512.  
  513.     my $source = "$self->{src}/$src";
  514.  
  515.     my @args = ("--prefix=$prefix",
  516.                 "--with-mpm=$mpm",
  517.                 "--srcdir=$source",
  518.                 @{ $build->{config} });
  519.  
  520.     chdir $source;
  521.     system "./buildconf";
  522.  
  523.     my $cmd = "$source/configure @args";
  524.  
  525.     chdir $self->{build};
  526.  
  527.     mkpath($name);
  528.     chdir $name;
  529.  
  530.     for my $dir (@srclib_dirs) {
  531.         mkpath("srclib/$dir");
  532.     }
  533.  
  534.     for my $dir (qw(build docs/conf)) {
  535.         mkpath($dir);
  536.     }
  537.  
  538.     system $cmd;
  539.  
  540.     open FH, ">.DONE" or die "open .DONE: $!";
  541.     print FH scalar localtime;
  542.     close FH;
  543.  
  544.     chdir $self->{prefix};
  545.  
  546.     $self->add_ssl_libs;
  547. }
  548.  
  549. sub make {
  550.     my($self, @cmds) = @_;
  551.  
  552.     push @cmds, 'all' unless @cmds;
  553.  
  554.     for my $name (keys %{ $self->{builds} }) {
  555.         chdir "$self->{build}/$name";
  556.         for my $cmd (@cmds) {
  557.             system "$self->{make} $cmd";
  558.         }
  559.     }
  560. }
  561.  
  562. sub system {
  563.     my $cmd = "@_";
  564.  
  565.     info $cmd;
  566.     return if DRYRUN;
  567.  
  568.     unless (CORE::system($cmd) == 0) {
  569.         my $status = $? >> 8;
  570.         die "system $cmd failed (exit status=$status)";
  571.     }
  572. }
  573.  
  574. sub chdir {
  575.     my $dir = shift;
  576.     info "chdir $dir";
  577.     CORE::chdir $dir;
  578. }
  579.  
  580. sub mkpath {
  581.     my $dir = shift;
  582.  
  583.     return if -d $dir;
  584.     info "mkpath $dir";
  585.  
  586.     return if DRYRUN;
  587.     File::Path::mkpath([$dir], 1, 0755);
  588. }
  589.  
  590. sub rmtree {
  591.     my $dir = shift;
  592.  
  593.     return unless -d $dir;
  594.     info "rmtree $dir";
  595.  
  596.     return if DRYRUN;
  597.     File::Path::rmtree([$dir], 1, 1);
  598. }
  599.  
  600. sub generate_script {
  601.     my($class, $file) = @_;
  602.  
  603.     $file ||= catfile 't', 'BUILD';
  604.  
  605.     my $content = join '', <DATA>;
  606.  
  607.     Apache::Test::basic_config()->write_perlscript($file, $content);
  608. }
  609.  
  610. unless (caller) {
  611.     $INC{'Apache/TestBuild.pm'} = __FILE__;
  612.     eval join '', <DATA>;
  613.     die $@ if $@;
  614. }
  615.  
  616. 1;
  617. __DATA__
  618. use strict;
  619. use warnings FATAL => 'all';
  620.  
  621. use lib qw(Apache-Test/lib);
  622. use Apache::TestBuild ();
  623. use Getopt::Long qw(GetOptions);
  624. use Cwd ();
  625.  
  626. my %options = (
  627.     prefix  => "checkout/build/install prefix",
  628.     ssldir  => "enable ssl with given directory",
  629.     cvstag  => "checkout with given cvs tag",
  630.     cvsroot => "use 'anon' for anonymous cvs",
  631.     version => "apache version (e.g. '2.0')",
  632.     mpms    => "MPMs to build (e.g. 'prefork')",
  633.     flavor  => "build flavor (e.g. 'debug shared')",
  634.     modules => "enable modules (e.g. 'all exp')",
  635.     name    => "change name of the build/install directory",
  636. );
  637.  
  638. my %opts;
  639.  
  640. Getopt::Long::Configure(qw(pass_through));
  641. #XXX: could be smarter here, being lazy for the moment
  642. GetOptions(\%opts, map "$_=s", sort keys %options);
  643.  
  644. if (@ARGV) {
  645.     print "passing extra args to configure: @ARGV\n";
  646. }
  647.  
  648. my $home = $ENV{HOME};
  649.  
  650. $opts{prefix}  ||= join '/', Cwd::cwd(), 'farm';
  651. #$opts{ssldir}  ||= '';
  652. #$opts{cvstag}  ||= '';
  653. #$opts{cvsroot} ||= '';
  654. $opts{version} ||= '2.0';
  655. $opts{mpms}    ||= 'prefork';
  656. $opts{flavor}  ||= 'debug-shared';
  657. $opts{modules} ||= 'all-exp';
  658.  
  659. #my @versions = qw(2.0);
  660.  
  661. #my @mpms = qw(prefork worker perchild);
  662.  
  663. #my @flavors  = ([qw(debug shared)], [qw(prof shared)],
  664. #                [qw(debug static)], [qw(prof static)]);
  665.  
  666. #my @modules = ([qw(all exp)]);
  667.  
  668. my $split = sub { split '-', delete $opts{ $_[0] } };
  669.  
  670. my @versions = $opts{version};
  671.  
  672. my @mpms = $split->('mpms');
  673.  
  674. my @flavors  = ([ $split->('flavor') ]);
  675.  
  676. my @modules  = ([ $split->('modules') ]);
  677.  
  678. my $tb = Apache::TestBuild->new(fresh => 1,
  679.                                 %opts,
  680.                                 extra_config => {
  681.                                     $opts{version} => \@ARGV,
  682.                                 });
  683.  
  684. $tb->init;
  685.  
  686. for my $version (@versions) {
  687.     $tb->cvs_update([ $version ]);
  688.  
  689.     for my $mpm (@mpms) {
  690.         for my $flavor (@flavors) {
  691.             for my $mods (@modules) {
  692.                 $tb->configure_httpd_2_0($version, $flavor,
  693.                                          $mods, $mpm);
  694.                 $tb->make(qw(all install));
  695.             }
  696.         }
  697.     }
  698. }
  699.