1#!C:/Perl/bin/perl 2use strict; 3use warnings; 4use FindBin; 5use Getopt::Long; 6use File::Spec::Functions qw(devnull catfile catdir path); 7use Cwd; 8require Win32; 9use ExtUtils::MakeMaker; 10use File::Basename; 11use File::Path; 12my ($apache, $apxs, $debug, $help, $no_perl, $perl, $with_perl); 13my $VERSION = "2.09"; 14my $result = GetOptions( 'with-apache2=s' => \$apache, 15 'with-apache2-apxs=s' => \$apxs, 16 'debug' => \$debug, 17 'help' => \$help, 18 'with-perl=s' => \$perl, 19 'disable-perl-glue' => \$no_perl, 20 'enable-perl-glue' => \$with_perl, 21 ); 22usage() if $help; 23 24my @path_ext; 25path_ext(); 26$apache ||= search(); 27my $apreq_home = Win32::GetShortPathName($FindBin::Bin); 28$apreq_home =~ s!/?win32$!!; 29$apreq_home =~ s!/!\\!g; 30 31my $doxygen = which('doxygen'); 32my $doxysearch = which('doxysearch'); 33my $cfg = $debug ? 'Debug' : 'Release'; 34 35my @tests = qw(cookie parsers params version); 36my @test_files = map {catfile('library', 't', "$_.t")} @tests; 37generate_tests($apreq_home, \@tests); 38 39my %apr_libs; 40my $prog = apache_prog_name($apache); 41my @httpd_ver = httpd_version($prog); 42my $devnull = devnull(); 43my %map = ( 44 apr => $httpd_ver[1] == 2 ? 'libapr-1.lib' : 'libapr.lib', 45 apu => $httpd_ver[1] == 2 ? 'libaprutil-1.lib' : 'libaprutil.lib' 46); 47 48foreach my $what (qw(apr apu)) { 49 my $ap = ($httpd_ver[1] == 2) ? 50 "$what-1-config.bat" : "$what-config.bat"; 51 my $cfg = catfile $apache, 'bin', $ap; 52 my $lib; 53 eval {$lib = qx{"$cfg" --$what-lib-file 2>$devnull;}}; 54 if ($@ or not $lib or $lib =~ /usage/i) { 55 $apr_libs{$what} = catfile $apache, 'lib', $map{$what}; 56 } 57 else { 58 chomp $lib; 59 $apr_libs{$what} = $lib; 60 } 61} 62 63my $version_check = catfile $apreq_home, 'build', 'version_check.pl'; 64my $cmd = join ' ', ($^X, $version_check, 'perl_prereqs'); 65chomp(my $prereq_string = qx{$cmd}); 66 67open(my $make, '>Makefile') or die qq{Cannot open Makefile: $!}; 68print $make <<"END"; 69# Microsoft Developer Studio Generated NMAKE File. 70# The following is a trick to get CPAN clients to follow prerequisites: 71# 72# $prereq_string 73# 74 75# --- MakeMaker post_initialize section: 76 77APREQ_HOME=$apreq_home 78APR_LIB=$apr_libs{apr} 79APU_LIB=$apr_libs{apu} 80CFG=$cfg 81APACHE=$apache 82PERL=$^X 83RM_F=\$(PERL) -MExtUtils::Command -e rm_f 84DOXYGEN_CONF=\$(APREQ_HOME)\\build\\doxygen.conf.win32 85TEST_FILES = @test_files 86 87END 88 89print $make $_ while (<DATA>); 90 91unless (-x $apxs) { 92 my $apxs_trial = catfile $apache, 'bin', 'apxs.bat'; 93 $apxs = (-e $apxs_trial) ? $apxs_trial : which('apxs'); 94 unless ($apxs) { 95 $apxs = fetch_apxs() ? which('apxs') : ''; 96 } 97} 98 99my $test = << 'END'; 100TEST : TEST_APREQ2 PERL_TEST 101 102TEST_APREQ2: $(LIBAPREQ) $(MOD) 103 $(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)" 104 set PATH=$(APREQ_HOME)\win32\libs;$(APACHE)\bin;$(PATH) 105 $(PERL) "-MExtUtils::Command::MM" "-e" "test_harness()" $(TEST_FILES) 106 cd $(APREQ_HOME) 107 $(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)" 108 cd $(APREQ_HOME) 109END 110 111my $clean = << 'END'; 112CLEAN: 113 cd $(LIBDIR) 114 $(RM_F) *.pch *.exe *.exp *.lib *.pdb *.ilk *.idb *.so *.dll *.obj *.manifest 115 cd $(TDIR) 116 $(RM_F) *.pch *.exe *.exp *.lib *.pdb *.ilk *.idb *.so *.dll *.obj *.manifest 117 cd $(APREQ_HOME)\module\t\c-modules 118 $(MAKE) clean 119 cd $(APREQ_HOME) 120!IF EXIST("$(PERLGLUE)\Makefile") 121 cd $(PERLGLUE) 122 $(MAKE) /nologo clean 123 cd $(APREQ_HOME) 124!ENDIF 125END 126 127if ($apxs) { 128 $test .= << "END"; 129 cd \$(APREQ_MODULE) 130 \$(PERL) t\\TEST.PL -apxs $apxs 131 cd \$(APREQ_HOME) 132END 133 $clean .= << 'END'; 134 cd $(APREQ_MODULE) 135 $(PERL) t\TEST.PL -clean 136 cd $(APREQ_HOME) 137END 138} 139 140print $make "\n", $test, "\n"; 141print $make "\n", $clean, "\n"; 142 143if ($doxygen and $doxysearch) { 144 print $make <<"END"; 145 146docs: \$(DOXYGEN_CONF) 147 cd \$(APREQ_HOME) 148 "$doxygen" \$(DOXYGEN_CONF) 149 cd \$(APREQ_HOME) 150 151END 152 153 my $bin_abspath = Win32::GetShortPathName(dirname($doxysearch)); 154 open(my $conf, "$apreq_home/build/doxygen.conf.in") 155 or die "Cannot read $apreq_home/build/doxygen.conf.in: $!"; 156 open(my $win32_conf, ">$apreq_home/build/doxygen.conf.win32") 157 or die "Cannot write to $apreq_home/build/doxygen.conf.win32: $!"; 158 while (<$conf>) { 159 s/\@PERL\@/"$^X"/; 160 s/\@PACKAGE\@/libapreq2/; 161 s/\@VERSION\@/$VERSION/; 162 print $win32_conf $_; 163 } 164 close $conf; 165 close $win32_conf; 166} 167 168close $make; 169# generate_defs(); 170 171if (not $no_perl and $] >= 5.008) { 172 my @args = ($^X, "$apreq_home/build/xsbuilder.pl", 'run', 'run'); 173 chdir "$apreq_home/glue/perl"; 174 system(@args) == 0 or die "system @args failed: $?"; 175 chdir $apreq_home; 176} 177 178print << "END"; 179 180A Makefile has been generated in $apreq_home. 181You can now run 182 183 nmake - build the libapreq2 library and perl glue 184 nmake test - run the supplied tests 185 nmake install - install the C libraries and perl glue modules 186 nmake clean - remove intermediate files 187 nmake docs - build documents (requires doxygen) 188 nmake help - list the nmake targets 189END 190 if ($doxygen) { 191print << 'END'; 192 nmake docs - builds documents 193 194END 195} 196 197my @args = ($^X, "$apreq_home/win32/apreq2_win32.pl", 198 "--with-apache2=$apache"); 199system(@args) == 0 or warn "system @args failed: $?"; 200 201sub usage { 202 print <<'END'; 203 204 Usage: perl Configure.pl [--with-apache2=C:\Path\to\Apache2] [--debug] 205 perl Configure.pl --help 206 207Options: 208 209 --with-apache2=C:\Path\to\Apache2 : specify the top-level Apache2 directory 210 --debug : build a debug version 211 --disable-perl-glue : skip building the perl glue 212 --help : print this help message 213 214With no options specified, an attempt will be made to find a suitable 215Apache2 directory, and if found, a non-debug version will be built. 216 217END 218 exit; 219} 220 221sub search { 222 my $apache; 223 if (my $bin = which('Apache')) { 224 (my $candidate = dirname($bin)) =~ s!bin$!!; 225 if (-d $candidate and check($candidate)) { 226 $apache = $candidate; 227 } 228 } 229 unless ($apache and -d $apache) { 230 $apache = prompt("Please give the path to your Apache2 installation:", 231 $apache); 232 } 233 die "Can't find a suitable Apache2 installation!" 234 unless ($apache and -d $apache and check($apache)); 235 236 $apache = Win32::GetShortPathName($apache); 237 $apache =~ s!\\!/!g; 238 $apache =~ s!/$!!; 239 my $ans = prompt(qq{\nUse "$apache" for your Apache2 directory?}, 'yes'); 240 unless ($ans =~ /^y/i) { 241 die <<'END'; 242 243Please run this configuration script again, and give 244the --with-apache2=C:\Path\to\Apache2 option to specify 245the desired top-level Apache2 directory. 246 247END 248 } 249 return $apache; 250} 251 252sub drives { 253 my @drives = (); 254 eval{require Win32API::File;}; 255 return map {"$_:\\"} ('C' .. 'Z') if $@; 256 my @r = Win32API::File::getLogicalDrives(); 257 return unless @r > 0; 258 for (@r) { 259 my $t = Win32API::File::GetDriveType($_); 260 push @drives, $_ if ($t == 3 or $t == 4); 261 } 262 return @drives > 0 ? @drives : undef; 263} 264 265sub check { 266 my $apache = shift; 267 die qq{No libhttpd library found under $apache/lib} 268 unless -e qq{$apache/lib/libhttpd.lib}; 269 die qq{No httpd header found under $apache/include} 270 unless -e qq{$apache/include/httpd.h}; 271 my $prog = apache_prog_name($apache); 272 my $vers = qx{$prog -v}; 273 die qq{"$apache" does not appear to be version 2.x} 274 unless $vers =~ m!Apache/2.\d!; 275 return 1; 276} 277 278sub path_ext { 279 if ($ENV{PATHEXT}) { 280 push @path_ext, split ';', $ENV{PATHEXT}; 281 for my $ext (@path_ext) { 282 $ext =~ s/^\.*(.+)$/$1/; 283 } 284 } 285 else { 286 #Win9X: doesn't have PATHEXT 287 push @path_ext, qw(com exe bat); 288 } 289} 290 291sub which { 292 my $program = shift; 293 return unless $program; 294 my @extras = (); 295 my @drives = drives(); 296 (my $program_files = $ENV{ProgramFiles}) =~ s!^\w+:\\!!; 297 if (@drives > 0) { 298 for my $drive (@drives) { 299 for ('Apache2', "$program_files/Apache2", 300 "$program_files/Apache Group/Apache2") { 301 my $bin = catdir $drive, $_, 'bin'; 302 push @extras, $bin if (-d $bin); 303 } 304 } 305 } 306 my @a = map {catfile $_, $program} 307 (path(), @extras); 308 for my $base(@a) { 309 return $base if -x $base; 310 for my $ext (@path_ext) { 311 return "$base.$ext" if -x "$base.$ext"; 312 } 313 } 314 return; 315} 316 317sub httpd_version { 318 my $prog = shift; 319 my $vers = qx{$prog -v}; 320 die qq{Could not parse "$apache" version} 321 unless $vers =~ m!Apache/2.(\d).(\d)!; 322 return (2, $1, $2); 323} 324 325sub generate_defs { 326 my $preamble =<<'END'; 327LIBRARY 328 329EXPORTS 330 331END 332 chdir "$apreq_home/env"; 333 my $match = qr{^apreq_env}; 334 my %fns = (); 335 open my $fh, "<mod_apreq.c" 336 or die "Cannot open env/mod_apreq.c: $!"; 337 while (<$fh>) { 338 next unless /^APREQ_DECLARE\([^\)]+\)\s*(\w+)/; 339 my $fn = $1; 340 $fns{$fn}++ if $fn =~ /$match/; 341 } 342 close $fh; 343 open my $def, ">../win32/mod_apreq.def" 344 or die "Cannot open win32/mod_apreq.def: $!"; 345 print $def $preamble; 346 print $def $_, "\n" for (sort keys %fns); 347 close $def; 348} 349 350sub generate_tests { 351 my ($top, $test_files) = @_; 352 my $t = catdir $top, 'library', 't'; 353 foreach my $test(@$test_files) { 354 my $file = catfile $t, $test; 355 open my $fh, '>', "$file.t" || die "Cannot open $file.t: $!"; 356 print $fh <<"EOT"; 357#!$^X 358exec '$file'; 359EOT 360 close $fh; 361 } 362} 363 364sub fetch_apxs { 365 eval {require Archive::Tar;}; 366 if ($@) { 367 die "Need Archive::Tar installed in order to install apxs."; 368 } 369 eval {require LWP::Simple; import LWP::Simple qw(getstore is_success)}; 370 if ($@) { 371 die "Need LWP::Simple installed in order to install apxs."; 372 } 373 374 print << 'END'; 375 376I could not find an apxs utility on your system, which is 377needed to run tests in the env/ subdirectory. The apxs 378utiltity (and apr-config and apu-config utilties) have not 379yet been ported to Apache2 on Win32, but a development port 380is available, which I can install for you, if you like. 381 382END 383 384 my $ans = prompt('Install apxs?', 'yes'); 385 return unless $ans =~ /^y/i; 386 my $file = 'apxs_win32.tar.gz'; 387 my $remote = 'http://perl.apache.org/dist/win32-bin/' . $file; 388 print "Fetching $remote ... "; 389 unless (is_success(getstore($remote, $file))) { 390 warn "Download of $remote failed"; 391 return; 392 } 393 print " done!\n"; 394 395 my $arc = Archive::Tar->new($file, 1); 396 $arc->extract($arc->list_files()); 397 my $dir = 'apxs'; 398 unless (-d $dir) { 399 warn "Unpacking $file failed"; 400 return; 401 } 402 print "chdir $dir\n"; 403 chdir $dir or do { 404 warn "chdir to $dir failed: $!"; 405 return; 406 }; 407 408 my $prog = apache_prog_name($apache); 409 my @args = ($^X, 'Configure.pl', 410 "-with-apache2=$apache", 411 "--with-apache-prog=$prog"); 412 print "@args\n\n"; 413 system(@args) == 0 or do { 414 warn "system @args failed: $?"; 415 return; 416 }; 417 chdir '..'; 418 rmtree($dir, 1, 1) or warn "rmtree of $dir failed: $!"; 419 print "unlink $file\n"; 420 unlink $file or warn "unlink of $file failed: $!"; 421 return 1; 422} 423 424sub apache_prog_name { 425 my $apache = shift; 426 my $prog; 427 for my $trial(qw(Apache.exe httpd.exe)) { 428 my $path = catfile($apache, 'bin', $trial); 429 next unless -e $path; 430 $prog = $path; 431 last; 432 } 433 die "Could not determine the Apache2 binary name" unless $prog; 434 return $prog; 435} 436 437__DATA__ 438 439LIBAPREQ=libapreq2 440APREQ2_TEST=apreq2_test 441CGITEST=test_cgi 442MOD=mod_apreq2 443 444!IF "$(CFG)" != "Release" && "$(CFG)" != "Debug" 445!MESSAGE Invalid configuration "$(CFG)" specified. 446!MESSAGE You can specify a configuration when running NMAKE 447!MESSAGE by defining the macro CFG on the command line. For example: 448!MESSAGE 449!MESSAGE NMAKE CFG="Release" 450!MESSAGE 451!MESSAGE Possible choices for configuration are: 452!MESSAGE 453!MESSAGE "Release" (based on "Win32 (x86) Console Application") 454!MESSAGE "Debug" (based on "Win32 (x86) Console Application") 455!MESSAGE 456!ERROR An invalid configuration is specified. 457!ENDIF 458 459!IF "$(APACHE)" == "" 460!MESSAGE No Apache directory was specified. 461!MESSAGE Please run Configure.bat to specify a valid Apache directory. 462!ERROR 463!ENDIF 464 465!IF "$(OS)" == "Windows_NT" 466NULL= 467!ELSE 468NULL=nul 469!ENDIF 470 471CFG_HOME=$(APREQ_HOME)\win32 472LIBDIR=$(CFG_HOME)\libs 473PERLGLUE=$(APREQ_HOME)\glue\perl 474APACHE_LIB=$(APACHE)\lib 475TDIR=$(APREQ_HOME)\library\t 476APREQ_MODULE=$(APREQ_HOME)\module 477 478ALL : MAKE_ALL 479 480MAKE_ALL : $(LIBAPREQ) $(MOD) PERL_GLUE 481 482$(LIBAPREQ): 483 $(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)" 484 485$(MOD): $(LIBAPREQ) 486 $(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)" 487 488PERL_GLUE: $(MOD) 489 cd $(PERLGLUE) 490 $(PERL) Makefile.PL 491 $(MAKE) /nologo 492 cd $(APREQ_HOME) 493 494PERL_TEST: $(MOD) 495 cd $(PERLGLUE) 496!IF !EXIST("$(PERLGLUE)\Makefile") 497 $(PERL) Makefile.PL 498!ENDIF 499 set PATH=$(APREQ_HOME)\win32\libs;$(APACHE)\bin;$(PATH) 500 $(MAKE) /nologo test 501 cd $(APREQ_HOME) 502 503INSTALL : INSTALL_LIBAPREQ2 PERL_INSTALL 504 505INSTALL_LIBAPREQ2: $(LIBAPREQ) 506 cd $(LIBDIR) 507!IF EXIST("$(LIBDIR)\$(MOD).so") 508 copy "$(MOD).so" "$(APACHE)\modules\$(MOD).so" 509 copy "$(MOD).lib" "$(APACHE_LIB)\$(MOD).lib" 510!ENDIF 511!IF EXIST("$(LIBDIR)\$(MOD).pdb") 512 copy "$(MOD).pdb" "$(APACHE)\modules\$(MOD).pdb" 513!ENDIF 514!IF EXIST("$(LIBDIR)\$(LIBAPREQ).lib") 515 copy "$(LIBAPREQ).lib" "$(APACHE_LIB)\$(LIBAPREQ).lib" 516!ENDIF 517!IF EXIST("$(LIBDIR)\$(LIBAPREQ).dll") 518 copy "$(LIBAPREQ).dll" "$(APACHE)\bin\$(LIBAPREQ).dll" 519!ENDIF 520!IF EXIST("$(LIBDIR)\$(LIBAPREQ).pdb") 521 copy "$(LIBAPREQ).pdb" "$(APACHE)\bin\$(LIBAPREQ).pdb" 522!ENDIF 523 cd $(APREQ_HOME) 524 525PERL_INSTALL: $(MOD) 526 cd $(PERLGLUE) 527!IF !EXIST("$(PERLGLUE)\Makefile") 528 $(PERL) Makefile.PL 529!ENDIF 530 $(MAKE) /nologo install 531 cd $(APREQ_HOME) 532 533HELP: 534 @echo nmake - build the libapreq2 library and perl glue 535 @echo nmake test - run the supplied tests 536 @echo nmake clean - clean 537 @echo nmake install - install the C libraries and perl modules 538 @echo nmake docs - build documents (requires doxygen) 539