diff options
Diffstat (limited to 'debian/perl-framework/Apache-Test/lib/Apache/TestBuild.pm')
-rw-r--r-- | debian/perl-framework/Apache-Test/lib/Apache/TestBuild.pm | 699 |
1 files changed, 699 insertions, 0 deletions
diff --git a/debian/perl-framework/Apache-Test/lib/Apache/TestBuild.pm b/debian/perl-framework/Apache-Test/lib/Apache/TestBuild.pm new file mode 100644 index 0000000..f0004e6 --- /dev/null +++ b/debian/perl-framework/Apache-Test/lib/Apache/TestBuild.pm @@ -0,0 +1,699 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +package Apache::TestBuild; + +use strict; +use warnings FATAL => 'all'; + +use subs qw(system chdir + info warning); + +use Config; +use File::Spec::Functions; +use File::Path (); +use Cwd (); + +use constant DRYRUN => 0; + +my @min_modules = qw(access auth log-config env mime setenvif + mime autoindex dir alias); + +my %shared_modules = ( + min => join(' ', @min_modules), +); + +my %configs = ( + all => { + 'apache-1.3' => [], + 'httpd-2.0' => enable20(qw(modules=all proxy)), + }, + most => { + 'apache-1.3' => [], + 'httpd-2.0' => enable20(qw(modules=most)), + }, + min => { + 'apache-1.3' => [], + 'httpd-2.0' => enable20(@min_modules), + }, + exp => { + 'apache-1.3' => [], + 'httpd-2.0' => enable20(qw(example case_filter + case_filter_in cache + echo deflate bucketeer)), + }, +); + +my %builds = ( + default => { + cflags => '-Wall', + config => { + 'apache-1.3' => [], + 'httpd-2.0' => [], + }, + }, + debug => { + cflags => '-g', + config => { + 'apache-1.3' => [], + 'httpd-2.0' => [qw(--enable-maintainer-mode)], + }, + }, + prof => { + cflags => '-pg -DGPROF', + }, + shared => { + config => { + 'apache-1.3' => [], + 'httpd-2.0' => enable20_shared('all'), + }, + }, + mostshared => { + config => { + 'apache-1.3' => [], + 'httpd-2.0' => enable20_shared('most'), + }, + }, + minshared => { + config => { + 'apache-1.3' => [], + 'httpd-2.0' => enable20_shared('min'), + }, + }, + static => { + }, +); + +my %mpms = ( + default => [qw(prefork worker)], + MSWin32 => [qw(winnt)], +); + +my @cvs = qw(httpd-2.0 apache-1.3); + +my @dirs = qw(build tar src install); + +sub enable20 { + [ map { "--enable-$_" } @_ ]; +} + +sub enable20_shared { + my $name = shift; + my $modules = $shared_modules{$name} || $name; + enable20(qq(mods-shared="$modules")); +} + +sub default_mpms { + $mpms{ $^O } || $mpms{'default'}; +} + +sub default_dir { + my($self, $dir) = @_; + $self->{$dir} ||= catdir $self->{prefix}, $dir, +} + +sub new { + my $class = shift; + + #XXX: not generating a BUILD script yet + #this way we can run: + #perl Apache-Test/lib/Apache/TestBuild.pm --cvsroot=anon --foo=... + + require Apache::TestConfig; + require Apache::TestTrace; + Apache::TestTrace->import; + + my $self = bless { + prefix => '/usr/local/apache', + cwd => Cwd::cwd(), + cvsroot => 'cvs.apache.org:/home/cvs', + cvs => \@cvs, + cvstag => "", + ssldir => "", + mpms => default_mpms(), + make => $Config{make}, + builds => {}, + name => "", + extra_config => { + 'httpd-2.0' => [], + }, + @_, + }, $class; + + #XXX + if (my $c = $self->{extra_config}->{'2.0'}) { + $self->{extra_config}->{'httpd-2.0'} = $c; + } + + for my $dir (@dirs) { + $self->default_dir($dir); + } + + if ($self->{ssldir}) { + push @{ $self->{extra_config}->{'httpd-2.0'} }, + '--enable-ssl', "--with-ssl=$self->{ssldir}"; + } + + $self; +} + +sub init { + my $self = shift; + + for my $dir (@dirs) { + mkpath($self->{$dir}); + } +} + +use subs qw(symlink unlink); +use File::Basename; +use File::Find; + +sub symlink_tree { + my $self = shift; + + my $httpd = 'httpd'; + my $install = "$self->{install}/bin/$httpd"; + my $source = "$self->{build}/.libs/$httpd"; + + unlink $install; + symlink $source, $install; + + my %dir = (apr => 'apr', + aprutil => 'apr-util'); + + for my $libname (qw(apr aprutil)) { + my $lib = "lib$libname.so.0.0.0"; + my $install = "$self->{install}/lib/$lib"; + my $source = "$self->{build}/srclib/$dir{$libname}/.libs/$lib"; + + unlink $install; + symlink $source, $install; + } + + $install = "$self->{install}/modules"; + $source = "$self->{build}/modules"; + + for (<$install/*.so>) { + unlink $_; + } + + finddepth(sub { + return unless /\.so$/; + my $file = "$File::Find::dir/$_"; + symlink $file, "$install/$_"; + }, $source); +} + +sub unlink { + my $file = shift; + + if (-e $file) { + print "unlink $file\n"; + } + else { + print "$file does not exist\n"; + } + CORE::unlink($file); +} + +sub symlink { + my($from, $to) = @_; + print "symlink $from => $to\n"; + unless (-e $from) { + print "source $from does not exist\n"; + } + my $base = dirname $to; + unless (-e $base) { + print "target dir $base does not exist\n"; + } + CORE::symlink($from, $to) or die $!; +} + +sub cvs { + my $self = shift; + + my $cmd = "cvs -d $self->{cvsroot} @_"; + + if (DRYRUN) { + info "$cmd"; + } + else { + system $cmd; + } +} + +my %cvs_names = ( + '2.0' => 'httpd-2.0', + '1.3' => 'apache-1.3', +); + +my %cvs_snames = ( + '2.0' => 'httpd', + '1.3' => 'apache', +); + +sub cvs_up { + my($self, $version) = @_; + + my $name = $cvs_names{$version}; + + my $dir = $self->srcdir($version); + + if ($self->{cvsroot} eq 'anon') { + $self->{cvsroot} = ':pserver:anoncvs@cvs.apache.org:/home/cvspublic'; + unless (-d $dir) { + #XXX do something better than doesn't require prompt if + #we already have an entry in ~/.cvspass + #$self->cvs('login'); + + warning "may need to run the following command ", + "(password is 'anoncvs')"; + warning "cvs -d $self->{cvsroot} login"; + } + } + + if (-d $dir) { + chdir $dir; + $self->cvs(up => "-dP $self->{cvstag}"); + return; + } + + my $co = checkout($name); + $self->$co($name, $dir); + + my $post = post_checkout($name); + $self->$post($name, $dir); +} + +sub checkout_httpd_2_0 { + my($self, $name, $dir) = @_; + + my $tag = $self->{cvstag}; + + $self->cvs(co => "-d $dir $tag $name"); + chdir "$dir/srclib"; + $self->cvs(co => "$tag apr apr-util"); +} + +sub checkout_apache_1_3 { + my($self, $name, $dir) = @_; + + $self->cvs(co => "-d $dir $self->{cvstag} $name"); +} + +sub post_checkout_httpd_2_0 { + my($self, $name, $dir) = @_; +} + +sub post_checkout_apache_1_3 { +} + +sub canon { + my $name = shift; + return $name unless $name; + $name =~ s/[.-]/_/g; + $name; +} + +sub checkout { + my $name = canon(shift); + \&{"checkout_$name"}; +} + +sub post_checkout { + my $name = canon(shift); + \&{"post_checkout_$name"}; +} + +sub cvs_update { + my $self = shift; + + my $cvs = shift || $self->{cvs}; + + chdir $self->{src}; + + for my $name (@$cvs) { + $self->cvs_up($name); + } +} + +sub merge_build { + my($self, $version, $builds, $configs) = @_; + + my $b = { + cflags => $builds{default}->{cflags}, + config => [ @{ $builds{default}->{config}->{$version} } ], + }; + + for my $name (@$builds) { + next if $name eq 'default'; #already have this + + if (my $flags = $builds{$name}->{cflags}) { + $b->{cflags} .= " $flags"; + } + if (my $cfg = $builds{$name}->{config}) { + if (my $vcfg = $cfg->{$version}) { + push @{ $b->{config} }, @$vcfg; + } + } + } + + for my $name (@$configs) { + my $cfg = $configs{$name}->{$version}; + next unless $cfg; + push @{ $b->{config} }, @$cfg; + } + + if (my $ex = $self->{extra_config}->{$version}) { + push @{ $b->{config} }, @$ex; + } + + if (my $ex = $self->{extra_cflags}->{$version}) { + $b->{config} .= " $ex"; + } + + $b; +} + +my @srclib_dirs = qw( + apr apr-util apr-util/xml/expat pcre +); + +sub install_name { + my($self, $builds, $configs, $mpm) = @_; + + return $self->{name} if $self->{name}; + + my $name = join '-', $mpm, @$builds, @$configs; + + if (my $tag = $self->cvs_name) { + $name .= "-$tag"; + } + + $name; +} + +#currently the httpd-2.0 build does not properly support static linking +#of ssl libs, force the issue +sub add_ssl_libs { + my $self = shift; + + my $ssldir = $self->{ssldir}; + + return unless $ssldir and -d $ssldir; + + my $name = $self->{current_install_name}; + + my $ssl_mod = "$name/modules/ssl"; + info "editing $ssl_mod/modules.mk"; + + if (DRYRUN) { + return; + } + + my $ssl_mk = "$self->{build}/$ssl_mod/modules.mk"; + + open my $fh, $ssl_mk or die "open $ssl_mk: $!"; + my @lines = <$fh>; + close $fh; + + for (@lines) { + next unless /SH_LINK/; + chomp; + $_ .= " -L$ssldir -lssl -lcrypto\n"; + info 'added ssl libs'; + last; + } + + open $fh, '>', $ssl_mk or die $!; + print $fh join "\n", @lines; + close $fh; +} + +sub cvs_name { + my $self = shift; + + if (my $tag = $self->{cvstag}) { + $tag =~ s/^-[DAr]//; + $tag =~ s/\"//g; + $tag =~ s,[/ :],_,g; #-D"03/29/02 07:00pm" + return $tag; + } + + return ""; +} + +sub srcdir { + my($self, $src) = @_; + + my $prefix = ""; + if ($src =~ s/^(apache|httpd)-//) { + $prefix = $1; + } + else { + $prefix = $cvs_snames{$src}; + } + + if ($src =~ /^\d\.\d$/) { + #release version will be \d\.\d\.\d+ + if (my $tag = $self->cvs_name) { + $src .= "-$tag"; + } + $src .= '-cvs'; + } + + join '-', $prefix, $src; +} + +sub configure_httpd_2_0 { + my($self, $src, $builds, $configs, $mpm) = @_; + + $src = $self->srcdir($src); + + chdir $self->{build}; + + my $name = $self->install_name($builds, $configs, $mpm); + + $self->{current_install_name} = $name; + + $self->{builds}->{$name} = 1; + + if ($self->{fresh}) { + rmtree($name); + } + else { + if (-e "$name/.DONE") { + warning "$name already configured"; + warning "rm $name/.DONE to force"; + return; + } + } + + my $build = $self->merge_build('httpd-2.0', $builds, $configs); + + $ENV{CFLAGS} = $build->{cflags}; + info "CFLAGS=$ENV{CFLAGS}"; + + my $prefix = "$self->{install}/$name"; + + rmtree($prefix) if $self->{fresh}; + + my $source = "$self->{src}/$src"; + + my @args = ("--prefix=$prefix", + "--with-mpm=$mpm", + "--srcdir=$source", + @{ $build->{config} }); + + chdir $source; + system "./buildconf"; + + my $cmd = "$source/configure @args"; + + chdir $self->{build}; + + mkpath($name); + chdir $name; + + for my $dir (@srclib_dirs) { + mkpath("srclib/$dir"); + } + + for my $dir (qw(build docs/conf)) { + mkpath($dir); + } + + system $cmd; + + open FH, ">.DONE" or die "open .DONE: $!"; + print FH scalar localtime; + close FH; + + chdir $self->{prefix}; + + $self->add_ssl_libs; +} + +sub make { + my($self, @cmds) = @_; + + push @cmds, 'all' unless @cmds; + + for my $name (keys %{ $self->{builds} }) { + chdir "$self->{build}/$name"; + for my $cmd (@cmds) { + system "$self->{make} $cmd"; + } + } +} + +sub system { + my $cmd = "@_"; + + info $cmd; + return if DRYRUN; + + unless (CORE::system($cmd) == 0) { + my $status = $? >> 8; + die "system $cmd failed (exit status=$status)"; + } +} + +sub chdir { + my $dir = shift; + info "chdir $dir"; + CORE::chdir $dir; +} + +sub mkpath { + my $dir = shift; + + return if -d $dir; + info "mkpath $dir"; + + return if DRYRUN; + File::Path::mkpath([$dir], 1, 0755); +} + +sub rmtree { + my $dir = shift; + + return unless -d $dir; + info "rmtree $dir"; + + return if DRYRUN; + File::Path::rmtree([$dir], 1, 1); +} + +sub generate_script { + my($class, $file) = @_; + + $file ||= catfile 't', 'BUILD'; + + my $content = join '', <DATA>; + + Apache::Test::basic_config()->write_perlscript($file, $content); +} + +unless (caller) { + $INC{'Apache/TestBuild.pm'} = __FILE__; + eval join '', <DATA>; + die $@ if $@; +} + +1; +__DATA__ +use strict; +use warnings FATAL => 'all'; + +use lib qw(Apache-Test/lib); +use Apache::TestBuild (); +use Getopt::Long qw(GetOptions); +use Cwd (); + +my %options = ( + prefix => "checkout/build/install prefix", + ssldir => "enable ssl with given directory", + cvstag => "checkout with given cvs tag", + cvsroot => "use 'anon' for anonymous cvs", + version => "apache version (e.g. '2.0')", + mpms => "MPMs to build (e.g. 'prefork')", + flavor => "build flavor (e.g. 'debug shared')", + modules => "enable modules (e.g. 'all exp')", + name => "change name of the build/install directory", +); + +my %opts; + +Getopt::Long::Configure(qw(pass_through)); +#XXX: could be smarter here, being lazy for the moment +GetOptions(\%opts, map "$_=s", sort keys %options); + +if (@ARGV) { + print "passing extra args to configure: @ARGV\n"; +} + +my $home = $ENV{HOME}; + +$opts{prefix} ||= join '/', Cwd::cwd(), 'farm'; +#$opts{ssldir} ||= ''; +#$opts{cvstag} ||= ''; +#$opts{cvsroot} ||= ''; +$opts{version} ||= '2.0'; +$opts{mpms} ||= 'prefork'; +$opts{flavor} ||= 'debug-shared'; +$opts{modules} ||= 'all-exp'; + +#my @versions = qw(2.0); + +#my @mpms = qw(prefork worker perchild); + +#my @flavors = ([qw(debug shared)], [qw(prof shared)], +# [qw(debug static)], [qw(prof static)]); + +#my @modules = ([qw(all exp)]); + +my $split = sub { split '-', delete $opts{ $_[0] } }; + +my @versions = $opts{version}; + +my @mpms = $split->('mpms'); + +my @flavors = ([ $split->('flavor') ]); + +my @modules = ([ $split->('modules') ]); + +my $tb = Apache::TestBuild->new(fresh => 1, + %opts, + extra_config => { + $opts{version} => \@ARGV, + }); + +$tb->init; + +for my $version (@versions) { + $tb->cvs_update([ $version ]); + + for my $mpm (@mpms) { + for my $flavor (@flavors) { + for my $mods (@modules) { + $tb->configure_httpd_2_0($version, $flavor, + $mods, $mpm); + $tb->make(qw(all install)); + } + } + } +} |