#!C:/Perl/bin/perl use strict; use warnings; use FindBin; use Getopt::Long; use File::Spec::Functions qw(devnull catfile catdir path); use Cwd; require Win32; use ExtUtils::MakeMaker; use File::Basename; use File::Path; my ($apache, $apxs, $debug, $help, $no_perl, $perl, $with_perl); my $VERSION = "2.18"; my $result = GetOptions( 'with-apache2=s' => \$apache, 'with-apache2-apxs=s' => \$apxs, 'debug' => \$debug, 'help' => \$help, 'with-perl=s' => \$perl, 'disable-perl-glue' => \$no_perl, 'enable-perl-glue' => \$with_perl, ); usage() if $help; my @path_ext; path_ext(); $apache ||= search(); my $apreq_home = Win32::GetShortPathName($FindBin::Bin); $apreq_home =~ s!/?win32$!!; $apreq_home =~ s!/!\\!g; my $doxygen = which('doxygen'); my $doxysearch = which('doxysearch'); my $cfg = $debug ? 'Debug' : 'Release'; my @tests = qw(cookie parsers params version); my @test_files = map {catfile('library', 't', "$_.t")} @tests; generate_tests($apreq_home, \@tests); my %apr_libs; my $prog = apache_prog_name($apache); my @httpd_ver = httpd_version($prog); my $devnull = devnull(); my %map = ( apr => $httpd_ver[1] >= 2 ? 'libapr-1.lib' : 'libapr.lib', apu => $httpd_ver[1] >= 2 ? 'libaprutil-1.lib' : 'libaprutil.lib' ); foreach my $what (qw(apr apu)) { my $ap = ($httpd_ver[1] >= 2) ? "$what-1-config.bat" : "$what-config.bat"; my $cfg = catfile $apache, 'bin', $ap; my $lib; eval {$lib = qx{"$cfg" --$what-lib-file 2>$devnull;}}; if ($@ or not $lib or $lib =~ /usage/i) { $apr_libs{$what} = catfile $apache, 'lib', $map{$what}; } else { chomp $lib; $apr_libs{$what} = $lib; } } my $version_check = catfile $apreq_home, 'build', 'version_check.pl'; my $cmd = join ' ', ($^X, $version_check, 'perl_prereqs'); chomp(my $prereq_string = qx{$cmd}); open(my $make, '>Makefile') or die qq{Cannot open Makefile: $!}; print $make <<"END"; # Microsoft Developer Studio Generated NMAKE File. # The following is a trick to get CPAN clients to follow prerequisites: # # $prereq_string # # --- MakeMaker post_initialize section: APREQ_HOME=$apreq_home APR_LIB=$apr_libs{apr} APU_LIB=$apr_libs{apu} CFG=$cfg APACHE=$apache PERL=$^X RM_F=\$(PERL) -MExtUtils::Command -e rm_f DOXYGEN_CONF=\$(APREQ_HOME)\\build\\doxygen.conf.win32 TEST_FILES = @test_files END print $make $_ while (); unless (-x $apxs) { my $apxs_trial = catfile $apache, 'bin', 'apxs.bat'; $apxs = (-e $apxs_trial) ? $apxs_trial : which('apxs'); unless ($apxs) { $apxs = fetch_apxs() ? which('apxs') : ''; } } my $test = << 'END'; TEST : TEST_APREQ2 PERL_TEST TEST_APREQ2: $(LIBAPREQ) $(MOD) $(MAKE) /nologo /f $(CFG_HOME)\$(APREQ2_TEST).mak CFG="$(APREQ2_TEST) - Win32 $(CFG)" APACHE="$(APACHE)" APREQ_HOME="$(APREQ_HOME)" APR_LIB="$(APR_LIB)" APU_LIB="$(APU_LIB)" set PATH=$(APREQ_HOME)\win32\libs;$(APACHE)\bin;$(PATH) $(PERL) "-MExtUtils::Command::MM" "-e" "test_harness()" $(TEST_FILES) cd $(APREQ_HOME) $(MAKE) /nologo /f $(CFG_HOME)\$(CGITEST).mak CFG="$(CGITEST) - Win32 $(CFG)" APACHE="$(APACHE)" APREQ_HOME="$(APREQ_HOME)" APR_LIB="$(APR_LIB)" APU_LIB="$(APU_LIB)" cd $(APREQ_HOME) END my $clean = << 'END'; CLEAN: cd $(LIBDIR) $(RM_F) *.pch *.exe *.exp *.lib *.pdb *.ilk *.idb *.so *.dll *.obj *.manifest cd $(TDIR) $(RM_F) *.pch *.exe *.exp *.lib *.pdb *.ilk *.idb *.so *.dll *.obj *.manifest cd $(APREQ_HOME)\module\t\c-modules $(MAKE) clean cd $(APREQ_HOME) !IF EXIST("$(PERLGLUE)\Makefile") cd $(PERLGLUE) $(MAKE) /nologo clean cd $(APREQ_HOME) !ENDIF END if ($apxs) { $test .= << "END"; cd \$(APREQ_MODULE) \$(PERL) t\\TEST.PL -apxs $apxs cd \$(APREQ_HOME) END $clean .= << 'END'; cd $(APREQ_MODULE) $(PERL) t\TEST.PL -clean cd $(APREQ_HOME) END } print $make "\n", $test, "\n"; print $make "\n", $clean, "\n"; if ($doxygen and $doxysearch) { print $make <<"END"; docs: \$(DOXYGEN_CONF) cd \$(APREQ_HOME) "$doxygen" \$(DOXYGEN_CONF) cd \$(APREQ_HOME) END my $bin_abspath = Win32::GetShortPathName(dirname($doxysearch)); open(my $conf, "$apreq_home/build/doxygen.conf.in") or die "Cannot read $apreq_home/build/doxygen.conf.in: $!"; open(my $win32_conf, ">$apreq_home/build/doxygen.conf.win32") or die "Cannot write to $apreq_home/build/doxygen.conf.win32: $!"; while (<$conf>) { s/\@PERL\@/"$^X"/; s/\@PACKAGE\@/libapreq2/; s/\@VERSION\@/$VERSION/; print $win32_conf $_; } close $conf; close $win32_conf; } close $make; # generate_defs(); if (not $no_perl and $] >= 5.008) { my @args = ($^X, "$apreq_home/build/xsbuilder.pl", 'run', 'run'); chdir "$apreq_home/glue/perl"; system(@args) == 0 or die "system @args failed: $?"; chdir $apreq_home; } print << "END"; A Makefile has been generated in $apreq_home. You can now run nmake - build the libapreq2 library and perl glue nmake test - run the supplied tests nmake install - install the C libraries and perl glue modules nmake clean - remove intermediate files nmake docs - build documents (requires doxygen) nmake help - list the nmake targets END if ($doxygen) { print << 'END'; nmake docs - builds documents END } my @args = ($^X, "$apreq_home/win32/apreq2_win32.pl", "--with-apache2=$apache"); system(@args) == 0 or warn "system @args failed: $?"; sub usage { print <<'END'; Usage: perl Configure.pl [--with-apache2=C:\Path\to\Apache2] [--debug] perl Configure.pl --help Options: --with-apache2=C:\Path\to\Apache2 : specify the top-level Apache2 directory --debug : build a debug version --disable-perl-glue : skip building the perl glue --help : print this help message With no options specified, an attempt will be made to find a suitable Apache2 directory, and if found, a non-debug version will be built. END exit; } sub search { my $apache; if (my $bin = which('Apache')) { (my $candidate = dirname($bin)) =~ s!bin$!!; if (-d $candidate and check($candidate)) { $apache = $candidate; } } unless ($apache and -d $apache) { $apache = prompt("Please give the path to your Apache2 installation:", $apache); } die "Can't find a suitable Apache2 installation!" unless ($apache and -d $apache and check($apache)); $apache = Win32::GetShortPathName($apache); $apache =~ s!\\!/!g; $apache =~ s!/$!!; my $ans = prompt(qq{\nUse "$apache" for your Apache2 directory?}, 'yes'); unless ($ans =~ /^y/i) { die <<'END'; Please run this configuration script again, and give the --with-apache2=C:\Path\to\Apache2 option to specify the desired top-level Apache2 directory. END } return $apache; } sub drives { my @drives = (); eval{require Win32API::File;}; return map {"$_:\\"} ('C' .. 'Z') if $@; my @r = Win32API::File::getLogicalDrives(); return unless @r > 0; for (@r) { my $t = Win32API::File::GetDriveType($_); push @drives, $_ if ($t == 3 or $t == 4); } return @drives > 0 ? @drives : undef; } sub check { my $apache = shift; die qq{No libhttpd library found under $apache/lib} unless -e qq{$apache/lib/libhttpd.lib}; die qq{No httpd header found under $apache/include} unless -e qq{$apache/include/httpd.h}; my $prog = apache_prog_name($apache); my $vers = qx{$prog -v}; die qq{"$apache" does not appear to be version 2.x} unless $vers =~ m!Apache/2.\d!; return 1; } sub path_ext { if ($ENV{PATHEXT}) { push @path_ext, split ';', $ENV{PATHEXT}; for my $ext (@path_ext) { $ext =~ s/^\.*(.+)$/$1/; } } else { #Win9X: doesn't have PATHEXT push @path_ext, qw(com exe bat); } } sub which { my $program = shift; return unless $program; my @extras = (); my @drives = drives(); (my $program_files = $ENV{ProgramFiles}) =~ s!^\w+:\\!!; if (@drives > 0) { for my $drive (@drives) { for ('Apache2', "$program_files/Apache2", "$program_files/Apache Group/Apache2") { my $bin = catdir $drive, $_, 'bin'; push @extras, $bin if (-d $bin); } } } my @a = map {catfile $_, $program} (path(), @extras); for my $base(@a) { return $base if -x $base; for my $ext (@path_ext) { return "$base.$ext" if -x "$base.$ext"; } } return; } sub httpd_version { my $prog = shift; my $vers = qx{$prog -v}; die qq{Could not parse "$apache" version} unless $vers =~ m!Apache/2.(\d).(\d)!; return (2, $1, $2); } sub generate_defs { my $preamble =<<'END'; LIBRARY EXPORTS END chdir "$apreq_home/env"; my $match = qr{^apreq_env}; my %fns = (); open my $fh, ") { next unless /^APREQ_DECLARE\([^\)]+\)\s*(\w+)/; my $fn = $1; $fns{$fn}++ if $fn =~ /$match/; } close $fh; open my $def, ">../win32/mod_apreq.def" or die "Cannot open win32/mod_apreq.def: $!"; print $def $preamble; print $def $_, "\n" for (sort keys %fns); close $def; } sub generate_tests { my ($top, $test_files) = @_; my $t = catdir $top, 'library', 't'; foreach my $test(@$test_files) { my $file = catfile $t, $test; open my $fh, '>', "$file.t" || die "Cannot open $file.t: $!"; print $fh <<"EOT"; #!$^X exec '$file'; EOT close $fh; } } sub fetch_apxs { eval {require Archive::Tar;}; if ($@) { die "Need Archive::Tar installed in order to install apxs."; } eval {require LWP::Simple; import LWP::Simple qw(getstore is_success)}; if ($@) { die "Need LWP::Simple installed in order to install apxs."; } print << 'END'; I could not find an apxs utility on your system, which is needed to run tests in the env/ subdirectory. The apxs utiltity (and apr-config and apu-config utilties) have not yet been ported to Apache2 on Win32, but a development port is available, which I can install for you, if you like. END my $ans = prompt('Install apxs?', 'yes'); return unless $ans =~ /^y/i; my $file = 'apxs_win32.tar.gz'; my $remote = 'http://perl.apache.org/dist/win32-bin/' . $file; print "Fetching $remote ... "; unless (is_success(getstore($remote, $file))) { warn "Download of $remote failed"; return; } print " done!\n"; my $arc = Archive::Tar->new($file, 1); $arc->extract($arc->list_files()); my $dir = 'apxs'; unless (-d $dir) { warn "Unpacking $file failed"; return; } print "chdir $dir\n"; chdir $dir or do { warn "chdir to $dir failed: $!"; return; }; my $prog = apache_prog_name($apache); my @args = ($^X, 'Configure.pl', "-with-apache2=$apache", "--with-apache-prog=$prog"); print "@args\n\n"; system(@args) == 0 or do { warn "system @args failed: $?"; return; }; chdir '..'; rmtree($dir, 1, 1) or warn "rmtree of $dir failed: $!"; print "unlink $file\n"; unlink $file or warn "unlink of $file failed: $!"; return 1; } sub apache_prog_name { my $apache = shift; my $prog; for my $trial(qw(Apache.exe httpd.exe)) { my $path = catfile($apache, 'bin', $trial); next unless -e $path; $prog = $path; last; } die "Could not determine the Apache2 binary name" unless $prog; return $prog; } __DATA__ LIBAPREQ=libapreq2 APREQ2_TEST=apreq2_test CGITEST=test_cgi MOD=mod_apreq2 !IF "$(CFG)" != "Release" && "$(CFG)" != "Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE CFG="Release" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Release" (based on "Win32 (x86) Console Application") !MESSAGE "Debug" (based on "Win32 (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(APACHE)" == "" !MESSAGE No Apache directory was specified. !MESSAGE Please run Configure.bat to specify a valid Apache directory. !ERROR !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CFG_HOME=$(APREQ_HOME)\win32 LIBDIR=$(CFG_HOME)\libs PERLGLUE=$(APREQ_HOME)\glue\perl APACHE_LIB=$(APACHE)\lib TDIR=$(APREQ_HOME)\library\t APREQ_MODULE=$(APREQ_HOME)\module ALL : MAKE_ALL MAKE_ALL : $(LIBAPREQ) $(MOD) PERL_GLUE $(LIBAPREQ): $(MAKE) /nologo /f $(CFG_HOME)\$(LIBAPREQ).mak CFG="$(LIBAPREQ) - Win32 $(CFG)" APACHE="$(APACHE)" APREQ_HOME="$(APREQ_HOME)" APR_LIB="$(APR_LIB)" APU_LIB="$(APU_LIB)" $(MOD): $(LIBAPREQ) $(MAKE) /nologo /f $(CFG_HOME)\$(MOD).mak CFG="$(MOD) - Win32 $(CFG)" APACHE="$(APACHE)" APREQ_HOME="$(APREQ_HOME)" APR_LIB="$(APR_LIB)" APU_LIB="$(APU_LIB)" PERL_GLUE: $(MOD) cd $(PERLGLUE) $(PERL) Makefile.PL $(MAKE) /nologo cd $(APREQ_HOME) PERL_TEST: $(MOD) cd $(PERLGLUE) !IF !EXIST("$(PERLGLUE)\Makefile") $(PERL) Makefile.PL !ENDIF set PATH=$(APREQ_HOME)\win32\libs;$(APACHE)\bin;$(PATH) $(MAKE) /nologo test cd $(APREQ_HOME) INSTALL : INSTALL_LIBAPREQ2 PERL_INSTALL INSTALL_LIBAPREQ2: $(LIBAPREQ) cd $(LIBDIR) !IF EXIST("$(LIBDIR)\$(MOD).so") copy "$(MOD).so" "$(APACHE)\modules\$(MOD).so" copy "$(MOD).lib" "$(APACHE_LIB)\$(MOD).lib" !ENDIF !IF EXIST("$(LIBDIR)\$(MOD).pdb") copy "$(MOD).pdb" "$(APACHE)\modules\$(MOD).pdb" !ENDIF !IF EXIST("$(LIBDIR)\$(LIBAPREQ).lib") copy "$(LIBAPREQ).lib" "$(APACHE_LIB)\$(LIBAPREQ).lib" !ENDIF !IF EXIST("$(LIBDIR)\$(LIBAPREQ).dll") copy "$(LIBAPREQ).dll" "$(APACHE)\bin\$(LIBAPREQ).dll" !ENDIF !IF EXIST("$(LIBDIR)\$(LIBAPREQ).pdb") copy "$(LIBAPREQ).pdb" "$(APACHE)\bin\$(LIBAPREQ).pdb" !ENDIF cd $(APREQ_HOME) PERL_INSTALL: $(MOD) cd $(PERLGLUE) !IF !EXIST("$(PERLGLUE)\Makefile") $(PERL) Makefile.PL !ENDIF $(MAKE) /nologo install cd $(APREQ_HOME) HELP: @echo nmake - build the libapreq2 library and perl glue @echo nmake test - run the supplied tests @echo nmake clean - clean @echo nmake install - install the C libraries and perl modules @echo nmake docs - build documents (requires doxygen)