1# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*- 2# Licensed to the Apache Software Foundation (ASF) under one or more 3# contributor license agreements. See the NOTICE file distributed with 4# this work for additional information regarding copyright ownership. 5# The ASF licenses this file to You under the Apache License, Version 2.0 6# (the "License"); you may not use this file except in compliance with 7# the License. You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17package Apache2::Build; 18 19use 5.006; 20use strict; 21use warnings; 22 23use Config; 24use Cwd (); 25use File::Spec::Functions qw(catfile catdir canonpath rel2abs devnull 26 catpath splitpath); 27use File::Basename; 28use ExtUtils::Embed (); 29use File::Copy (); 30 31BEGIN { # check for a sane ExtUtils::Embed 32 unless ($ENV{MP_USE_MY_EXTUTILS_EMBED}) { 33 my ($version, $path)=(ExtUtils::Embed->VERSION, 34 $INC{q{ExtUtils/Embed.pm}}); 35 my $msg=<<"EOF"; 36I have found ExtUtils::Embed $version at 37 38 $path 39 40This is probably not the right one for this perl version. Please make sure 41there is only one version of this module installed and that it is the one 42that comes with this perl version. 43 44If you insist on using the ExtUtils::Embed as is set the environment 45variable MP_USE_MY_EXTUTILS_EMBED=1 and try again. 46 47EOF 48 if (eval {require Module::CoreList}) { 49 my $req=$Module::CoreList::version{$]}->{q/ExtUtils::Embed/}; 50 die "Please repair your Module::CoreList" unless $req; 51 unless ($version eq $req) { 52 $msg.=("Details: expecting ExtUtils::Embed $req ". 53 "(according to Module::CoreList)\n\n"); 54 die $msg; 55 } 56 } 57 else { 58 my $req=$Config{privlib}.'/ExtUtils/Embed.pm'; 59 unless ($path eq $req) { 60 $msg.="Details: expecting ExtUtils::Embed at $req\n\n"; 61 die $msg; 62 } 63 } 64 } 65} 66 67use constant IS_MOD_PERL_BUILD => grep 68 { -e "$_/Makefile.PL" && -e "$_/lib/mod_perl2.pm" } qw(. ..); 69 70use constant AIX => $^O eq 'aix'; 71use constant DARWIN => $^O eq 'darwin'; 72use constant CYGWIN => $^O eq 'cygwin'; 73use constant IRIX => $^O eq 'irix'; 74use constant HPUX => $^O eq 'hpux'; 75use constant OPENBSD => $^O eq 'openbsd'; 76use constant WIN32 => $^O eq 'MSWin32'; 77 78use constant MSVC => WIN32() && ($Config{cc} eq 'cl'); 79use constant DMAKE => WIN32() && ($Config{make} eq 'dmake'); 80 81use constant REQUIRE_ITHREADS => grep { $^O eq $_ } qw(MSWin32); 82use constant PERL_HAS_ITHREADS => 83 $Config{useithreads} && ($Config{useithreads} eq 'define'); 84use constant BUILD_APREXT => WIN32() || CYGWIN(); 85 86use ModPerl::Code (); 87use ModPerl::BuildOptions (); 88use Apache::TestTrace; 89use Apache::TestConfig (); 90 91our $VERSION = '0.01'; 92our $AUTOLOAD; 93 94sub AUTOLOAD { 95 my $self = shift; 96 my $name = uc ((split '::', $AUTOLOAD)[-1]); 97 unless ($name =~ /^MP_/) { 98 die "no such method: $AUTOLOAD"; 99 } 100 unless ($self->{$name}) { 101 return wantarray ? () : undef; 102 } 103 return wantarray ? (split /\s+/, $self->{$name}) : $self->{$name}; 104} 105 106#--- apxs stuff --- 107 108our $APXS; 109 110my %apxs_query = ( 111 INCLUDEDIR => 'include', 112 LIBEXECDIR => 'modules', 113 CFLAGS => undef, 114 PREFIX => '', 115); 116 117sub ap_prefix_invalid { 118 my $self = shift; 119 120 my $prefix = $self->{MP_AP_PREFIX}; 121 122 unless (-d $prefix) { 123 return "$prefix: No such file or directory"; 124 } 125 126 my $include_dir = $self->apxs(-q => 'INCLUDEDIR'); 127 128 unless (-d $include_dir) { 129 return "include/ directory not found in $prefix"; 130 } 131 132 return ''; 133} 134 135sub httpd_is_source_tree { 136 my $self = shift; 137 138 return $self->{httpd_is_source_tree} 139 if exists $self->{httpd_is_source_tree}; 140 141 my $prefix = $self->dir; 142 $self->{httpd_is_source_tree} = 143 defined $prefix && -d $prefix && -e "$prefix/CHANGES"; 144} 145 146# try to find the apxs utility, set $self->{MP_APXS} to the path if found, 147# otherwise to '' 148sub find_apxs_util { 149 my $self = shift; 150 151 if (not defined $self->{MP_APXS}) { 152 $self->{MP_APXS} = ''; # not found 153 } 154 155 my @trys = ($Apache2::Build::APXS, 156 $self->{MP_APXS}, 157 $ENV{MP_APXS}); 158 159 push @trys, catfile $self->{MP_AP_PREFIX}, 'sbin', 'apxs' 160 if exists $self->{MP_AP_PREFIX}; 161 162 if (WIN32) { 163 my $ext = '.bat'; 164 for (@trys) { 165 $_ .= $ext if ($_ and $_ !~ /$ext$/); 166 } 167 } 168 169 unless (IS_MOD_PERL_BUILD) { 170 #if we are building mod_perl via apxs, apxs should already be known 171 #these extra tries are for things built outside of mod_perl 172 #e.g. libapreq 173 # XXX: this may pick a wrong apxs version! 174 push @trys, 175 Apache::TestConfig::which('apxs'), 176 '/usr/local/sbin/apxs'; 177 } 178 179 my $apxs_try; 180 for (@trys) { 181 next unless ($apxs_try = $_); 182 chomp $apxs_try; 183 if (-x $apxs_try) { 184 $self->{MP_APXS} = $apxs_try; 185 last; 186 } 187 } 188} 189 190# if MP_AP_DESTDIR was specified this sub will prepend this path to 191# any Apache-specific installation path (that option is used only by 192# package maintainers). 193sub ap_destdir { 194 my $self = shift; 195 my $path = shift || ''; 196 return $path unless $self->{MP_AP_DESTDIR}; 197 198 if (WIN32) { 199 my ($dest_vol, $dest_dir) = splitpath $self->{MP_AP_DESTDIR}, 1; 200 my $real_dir = (splitpath $path)[1]; 201 202 $path = catpath $dest_vol, catdir($dest_dir, $real_dir), ''; 203 } 204 else { 205 $path = catdir $self->{MP_AP_DESTDIR}, $path; 206 } 207 208 return canonpath $path; 209} 210 211sub apxs { 212 my $self = shift; 213 214 $self->find_apxs_util() unless defined $self->{MP_APXS}; 215 216 my $is_query = (@_ == 2) && ($_[0] eq '-q'); 217 218 $self = $self->build_config unless ref $self; 219 220 my $query_key; 221 if ($is_query) { 222 $query_key = 'APXS_' . uc $_[1]; 223 if (exists $self->{$query_key}) { 224 return $self->{$query_key}; 225 } 226 } 227 228 unless ($self->{MP_APXS}) { 229 my $prefix = $self->{MP_AP_PREFIX} || ""; 230 return '' unless -d $prefix and $is_query; 231 my $val = $apxs_query{$_[1]}; 232 return defined $val ? ($val ? "$prefix/$val" : $prefix) : ""; 233 } 234 235 my $devnull = devnull(); 236 my $val = qx($self->{MP_APXS} @_ 2>$devnull); 237 chomp $val if defined $val; 238 239 unless ($val) { 240 # do we have an error or is it just an empty value? 241 my $error = qx($self->{MP_APXS} @_ 2>&1); 242 chomp $error if defined $error; 243 if ($error) { 244 error "'$self->{MP_APXS} @_' failed:"; 245 error $error; 246 } 247 else { 248 $val = ''; 249 } 250 } 251 252 $self->{$query_key} = $val; 253} 254 255sub apxs_cflags { 256 my $who = caller_package(shift); 257 my $cflags = $who->apxs('-q' => 'CFLAGS'); 258 $cflags =~ s/\"/\\\"/g; 259 $cflags; 260} 261 262sub apxs_extra_cflags { 263 my $who = caller_package(shift); 264 my $flags = $who->apxs('-q' => 'EXTRA_CFLAGS'); 265 $flags =~ s/\"/\\\"/g; 266 $flags; 267} 268 269sub apxs_extra_cppflags { 270 my $who = caller_package(shift); 271 my $flags = $who->apxs('-q' => 'EXTRA_CPPFLAGS') ." ". 272 $who->apxs('-q' => 'NOTEST_CPPFLAGS'); 273 $flags =~ s/\"/\\\"/g; 274 $flags; 275} 276 277sub caller_package { 278 my $arg = shift; 279 return ($arg and ref($arg) eq __PACKAGE__) ? $arg : __PACKAGE__; 280} 281 282my %threaded_mpms = map { $_ => 1 } 283 qw(worker winnt beos mpmt_os2 netware leader perchild threadpool 284 dynamic); 285sub mpm_is_threaded { 286 my $self = shift; 287 my $mpm_name = $self->mpm_name(); 288 return exists $threaded_mpms{$mpm_name} ? 1 : 0; 289} 290 291sub mpm_name { 292 my $self = shift; 293 294 return $self->{mpm_name} if $self->{mpm_name}; 295 296 if ($self->httpd_version =~ /^(\d+)\.(\d+)\.(\d+)/) { 297 delete $threaded_mpms{dynamic} if $self->mp_nonthreaded_ok; 298 return $self->{mpm_name} = 'dynamic' if ($1*1000+$2)*1000+$3>=2003000; 299 } 300 301 # XXX: hopefully apxs will work on win32 one day 302 return $self->{mpm_name} = 'winnt' if WIN32; 303 304 my $mpm_name; 305 306 # httpd >= 2.3 307 if ($self->httpd_version_as_int =~ m/^2[3-9]\d+/) { 308 $mpm_name = 'dynamic'; 309 } 310 else { 311 $mpm_name = $self->apxs('-q' => 'MPM_NAME'); 312 } 313 314 # building against the httpd source dir 315 unless (($mpm_name and $self->httpd_is_source_tree)) { 316 if ($self->dir) { 317 my $config_vars_file = catfile $self->dir, 318 "build", "config_vars.mk"; 319 if (open my $fh, $config_vars_file) { 320 while (<$fh>) { 321 if (/MPM_NAME = (\w+)/) { 322 $mpm_name = $1; 323 last; 324 } 325 } 326 close $fh; 327 } 328 } 329 } 330 331 unless ($mpm_name) { 332 my $msg = 'Failed to obtain the MPM name.'; 333 $msg .= " Please specify MP_APXS=/full/path/to/apxs to solve " . 334 "this problem." unless exists $self->{MP_APXS}; 335 error $msg; 336 die "\n"; 337 } 338 339 return $self->{mpm_name} = $mpm_name; 340} 341 342sub should_build_apache { 343 my ($self) = @_; 344 return $self->{MP_USE_STATIC} ? 1 : 0; 345} 346 347sub configure_apache { 348 my ($self) = @_; 349 350 unless ($self->{MP_AP_CONFIGURE}) { 351 error "You specified MP_USE_STATIC but did not specify the " . 352 "arguments to httpd's ./configure with MP_AP_CONFIGURE"; 353 exit 1; 354 } 355 356 unless ($self->{MP_AP_PREFIX}) { 357 error "You specified MP_USE_STATIC but did not speficy the " . 358 "location of httpd's source tree with MP_AP_PREFIX"; 359 exit 1; 360 } 361 362 debug "Configuring httpd in $self->{MP_AP_PREFIX}"; 363 364 my $httpd = File::Spec->catfile($self->{MP_AP_PREFIX}, 'httpd'); 365 $self->{'httpd'} ||= $httpd; 366 push @Apache::TestMM::Argv, ('httpd' => $self->{'httpd'}); 367 368 my $mplibpath = ''; 369 my $ldopts = $self->ldopts; 370 371 if (CYGWIN) { 372 # Cygwin's httpd port links its modules into httpd2core.dll, 373 # instead of httpd.exe. In this case, we have a problem, 374 # because libtool doesn't want to include static libs (.a) 375 # into a dynamic lib (.dll). Workaround this by setting 376 # mod_perl.a as a linker argument (including all other flags 377 # and libs). 378 my $mplib = "$self->{MP_LIBNAME}$Config{lib_ext}"; 379 380 $ldopts = join ' ', 381 '--export-all-symbols', 382 '--enable-auto-image-base', 383 "$self->{cwd}/src/modules/perl/$mplib", 384 $ldopts; 385 386 $ldopts =~ s/(\S+)/-Wl,$1/g; 387 388 } else { 389 my $mplib = "$self->{MP_LIBNAME}$Config{lib_ext}"; 390 $mplibpath = catfile($self->{cwd}, qw(src modules perl), $mplib); 391 } 392 393 local $ENV{BUILTIN_LIBS} = $mplibpath; 394 local $ENV{AP_LIBS} = $ldopts; 395 local $ENV{MODLIST} = 'perl'; 396 397 # XXX: -Wall and/or -Werror at httpd configure time breaks things 398 local $ENV{CFLAGS} = join ' ', grep { ! /\-Wall|\-Werror/ } 399 split /\s+/, $ENV{CFLAGS} || ''; 400 401 my $cd = qq(cd $self->{MP_AP_PREFIX}); 402 403 # We need to clean the httpd tree before configuring it 404 if (-f File::Spec->catfile($self->{MP_AP_PREFIX}, 'Makefile')) { 405 my $cmd = qq(make clean); 406 debug "Running $cmd"; 407 system("$cd && $cmd") == 0 or die "httpd: $cmd failed"; 408 } 409 410 my $cmd = qq(./configure $self->{MP_AP_CONFIGURE}); 411 debug "Running $cmd"; 412 system("$cd && $cmd") == 0 or die "httpd: $cmd failed"; 413 414 # Got to build in srclib/* early to have generated files present. 415 my $srclib = File::Spec->catfile($self->{MP_AP_PREFIX}, 'srclib'); 416 $cd = qq(cd $srclib); 417 $cmd = qq(make); 418 debug "Building srclib in $srclib"; 419 system("$cd && $cmd") == 0 or die "srclib: $cmd failed"; 420} 421 422#--- Perl Config stuff --- 423 424my %gtop_config = (); 425sub find_gtop { 426 my $self = shift; 427 428 return %gtop_config if %gtop_config; 429 430 if (%gtop_config = find_gtop_config()) { 431 return %gtop_config; 432 } 433 434 if ($self->find_dlfile('gtop')) { 435 $gtop_config{ldopts} = $self->gtop_ldopts_old(); 436 $gtop_config{ccopts} = ''; 437 return %gtop_config; 438 } 439 440 return (); 441} 442 443sub find_gtop_config { 444 my %c = (); 445 446 my $ver_2_5_plus = 0; 447 if (system('pkg-config --exists libgtop-2.0') == 0) { 448 # 2.x 449 chomp($c{ccopts} = qx|pkg-config --cflags libgtop-2.0|); 450 chomp($c{ldopts} = qx|pkg-config --libs libgtop-2.0|); 451 452 # 2.0.0 bugfix 453 chomp(my $libdir = qx|pkg-config --variable=libdir libgtop-2.0|); 454 $c{ldopts} =~ s|\$\(libdir\)|$libdir|; 455 456 chomp($c{ver} = qx|pkg-config --modversion libgtop-2.0|); 457 ($c{ver_maj}, $c{ver_min}) = split /\./, $c{ver}; 458 $ver_2_5_plus++ if $c{ver_maj} == 2 && $c{ver_min} >= 5; 459 460 if ($ver_2_5_plus) { 461 # some headers were removed in libgtop 2.5.0 so we need to 462 # be able to exclude them at compile time 463 $c{ccopts} .= ' -DGTOP_2_5_PLUS'; 464 } 465 466 } 467 elsif (system('gnome-config --libs libgtop') == 0) { 468 chomp($c{ccopts} = qx|gnome-config --cflags libgtop|); 469 chomp($c{ldopts} = qx|gnome-config --libs libgtop|); 470 471 # buggy ( < 1.0.9?) versions fixup 472 $c{ccopts} =~ s|^/|-I/|; 473 $c{ldopts} =~ s|^/|-L/|; 474 } 475 476 # starting from 2.5.0 'pkg-config --cflags libgtop-2.0' already 477 # gives us all the cflags that are needed 478 if ($c{ccopts} && !$ver_2_5_plus) { 479 chomp(my $ginc = `glib-config --cflags`); 480 $c{ccopts} .= " $ginc"; 481 } 482 483 if (%c) { 484 $c{ccopts} = " $c{ccopts}"; 485 $c{ldopts} = " $c{ldopts}"; 486 } 487 488 return %c; 489} 490 491my @Xlib = qw(/usr/X11/lib /usr/X11R6/lib); 492 493sub gtop_ldopts_old { 494 my $self = shift; 495 my $xlibs = ""; 496 497 my ($path) = $self->find_dlfile('Xau', @Xlib); 498 if ($path) { 499 $xlibs = "-L$path -lXau"; 500 } 501 502 if ($self->find_dlfile('intl')) { 503 $xlibs .= ' -lintl'; 504 } 505 506 return " -lgtop -lgtop_sysdeps -lgtop_common $xlibs"; 507} 508 509sub gtop_ldopts { 510 exists $gtop_config{ldopts} ? $gtop_config{ldopts} : ''; 511} 512 513sub gtop_ccopts { 514 exists $gtop_config{ccopts} ? $gtop_config{ccopts} : ''; 515} 516 517sub ldopts { 518 my ($self) = @_; 519 520 my $config = tied %Config; 521 my $ldflags = $config->{ldflags}; 522 523 if (WIN32) { 524 $config->{ldflags} = ''; #same as lddlflags 525 } 526 elsif (DARWIN) { 527 #not sure how this can happen, but it shouldn't 528 my @bogus_flags = ('flat_namespace', 'bundle', 'undefined suppress'); 529 for my $flag (@bogus_flags) { 530 $config->{ldflags} =~ s/-$flag\s*//; 531 } 532 } 533 534 my $ldopts = ExtUtils::Embed::ldopts(); 535 chomp $ldopts; 536 537 my $ld = $self->perl_config('ld'); 538 539 if (HPUX && $ld eq 'ld') { 540 while ($ldopts =~ s/-Wl,(\S+)/$1/) { 541 my $cp = $1; 542 (my $repl = $cp) =~ s/,/ /g; 543 $ldopts =~ s/\Q$cp/$repl/; 544 } 545 } 546 547 if ($self->{MP_USE_GTOP}) { 548 $ldopts .= $self->gtop_ldopts; 549 } 550 551 $config->{ldflags} = $ldflags; #reset 552 553 # on Irix mod_perl.so needs to see the libperl.so symbols, which 554 # requires the -exports option immediately before -lperl. 555 if (IRIX) { 556 ($ldopts =~ s/-lperl\b/-exports -lperl/) 557 or warn "Failed to fix Irix symbol exporting\n"; 558 } 559 560 $ldopts; 561} 562 563my $Wall = 564 "-Wall -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations"; 565 566# perl v5.6.1 and earlier produces lots of warnings, so we can't use 567# -Werror with those versions. 568$Wall .= " -Werror" if $] >= 5.006002; 569 570sub ap_ccopts { 571 my ($self) = @_; 572 my $ccopts = "-DMOD_PERL"; 573 574 if ($self->{MP_USE_GTOP}) { 575 $ccopts .= " -DMP_USE_GTOP"; 576 $ccopts .= $self->gtop_ccopts; 577 } 578 579 if ($self->{MP_MAINTAINER}) { 580 $self->{MP_DEBUG} = 1; 581 if ($self->perl_config('gccversion')) { 582 #same as --with-maintainter-mode 583 $ccopts .= " $Wall"; 584 } 585 586 if (!OPENBSD && 587 $self->has_gcc_version('3.3.2') && 588 $ccopts !~ /declaration-after-statement/) { 589 debug "Adding -Wdeclaration-after-statement to ccopts"; 590 $ccopts .= " -Wdeclaration-after-statement"; 591 } 592 } 593 594 if ($self->{MP_COMPAT_1X}) { 595 $ccopts .= " -DMP_COMPAT_1X"; 596 } 597 598 if ($self->{MP_DEBUG}) { 599 $self->{MP_TRACE} = 1; 600 my $win32_flags = MSVC ? '-Od -MD -Zi' : ''; 601 my $debug_flags = WIN32 ? $win32_flags : '-g'; 602 $ccopts .= " $debug_flags" unless $Config{optimize} =~ /$debug_flags/; 603 $ccopts .= ' -DMP_DEBUG'; 604 } 605 606 if ($self->{MP_CCOPTS}) { 607 $ccopts .= " $self->{MP_CCOPTS}"; 608 } 609 610 if ($self->{MP_TRACE}) { 611 $ccopts .= " -DMP_TRACE"; 612 } 613 614 if ($self->has_gcc_version('5.0.0') && $ccopts !~ /-fgnu89-inline/) { 615 $ccopts .= " -fgnu89-inline"; 616 } 617 618 if ($self->has_clang && $ccopts !~ /-std=gnu89/) { 619 $ccopts .= " -std=gnu89"; 620 } 621 622 # make sure apr.h can be safely included 623 # for example Perl's included -D_GNU_SOURCE implies 624 # -D_LARGEFILE64_SOURCE on linux, but this won't happen on 625 # Solaris, so we need apr flags living in apxs' EXTRA_CPPFLAGS 626 my $extra_cppflags = $self->apxs_extra_cppflags; 627 $ccopts .= " " . $extra_cppflags; 628 629 # Make sure the evil AP_DEBUG is not defined when building mod_perl 630 $ccopts =~ s/ ?-DAP_DEBUG\b//; 631 632 $ccopts; 633} 634 635sub has_gcc_version { 636 my $self = shift; 637 my $requested_version = shift; 638 639 my $has_version = $self->perl_config('gccversion'); 640 641 return 0 unless $has_version; 642 643 #Only interested in leading version digits 644 $has_version =~ s/^([0-9.]+).*/$1/; 645 646 my @tuples = split /\./, $has_version, 3; 647 my @r_tuples = split /\./, $requested_version, 3; 648 649 return cmp_tuples(\@tuples, \@r_tuples) == 1; 650} 651 652sub has_clang { 653 my $self = shift; 654 655 my $has_version = $self->perl_config('gccversion'); 656 657 return 0 unless $has_version; 658 659 return $has_version =~ m/Clang/; 660} 661 662sub cmp_tuples { 663 my ($num_a, $num_b) = @_; 664 665 while (@$num_a && @$num_b) { 666 my $cmp = shift @$num_a <=> shift @$num_b; 667 return $cmp if $cmp; 668 } 669 670 return @$num_a <=> @$num_b; 671} 672 673sub perl_ccopts { 674 my $self = shift; 675 676 my $cflags = $self->strip_lfs(" $Config{ccflags} "); 677 678 my $fixup = \&{"ccopts_$^O"}; 679 if (defined &$fixup) { 680 $fixup->(\$cflags); 681 } 682 683 if (WIN32 and $self->{MP_DEBUG}) { 684 #only win32 has -DDEBUGGING in both optimize and ccflags 685 my $optim = $Config{optimize}; 686 687 unless ($optim =~ /-DDEBUGGING/) { 688 $cflags =~ s/$optim//; 689 } 690 } 691 692 if (CYGWIN) { 693 $cflags .= " -DCYGWIN "; 694 } 695 696 $cflags; 697} 698 699sub ccopts_hpux { 700 my $cflags = shift; 701 return if $Config{cc} eq 'gcc'; #XXX? 702 return if $$cflags =~ /(-Ae|\+e)/; 703 $$cflags .= " -Ae "; 704} 705 706# XXX: there could be more, but this is just for cosmetics 707my %cflags_dups = map { $_ => 1 } qw(-D_GNU_SOURCE -D_REENTRANT); 708sub ccopts { 709 my ($self) = @_; 710 711 my $cflags = $self->perl_ccopts . ExtUtils::Embed::perl_inc() . 712 $self->ap_ccopts; 713 714 # remove duplicates of certain cflags coming from perl and ap/apr 715 my @cflags = (); 716 my %dups = (); 717 for (split /\s+/, $cflags) { 718 if ($cflags_dups{$_}) { 719 next if $dups{$_}; 720 $dups{$_}++; 721 } 722 push @cflags, $_; 723 } 724 $cflags = "@cflags"; 725 726 $cflags; 727} 728 729sub ldopts_prefix { 730 my $self = shift; 731 $self->perl_config('ld') eq 'ld' ? '' : "-Wl,"; 732} 733 734sub perl_config_optimize { 735 my ($self, $val) = @_; 736 737 $val ||= $Config{optimize}; 738 739 if ($self->{MP_DEBUG}) { 740 return ' ' unless $Config{ccflags} =~ /-DDEBUGGING/; 741 } 742 743 $val; 744} 745 746sub perl_config_ld { 747 my ($self, $val) = @_; 748 749 $val ||= $Config{ld}; 750 751 basename $val; #bleedperl hpux value is /usr/bin/ld ! 752} 753 754sub perl_config_lddlflags { 755 my ($self, $val) = @_; 756 757 if ($self->{MP_DEBUG}) { 758 if (MSVC) { 759 unless ($val =~ s/-release/-debug/) { 760 $val .= ' -debug'; 761 } 762 } 763 } 764 765 if (AIX) { 766 my $Wl = $self->ldopts_prefix; 767 768 # it's useless to import symbols from libperl.so this way, 769 # because perl.exp is incomplete. a better way is to link 770 # against -lperl which has all the symbols 771 $val =~ s|${Wl}-bI:\$\(PERL_INC\)/perl\.exp||; 772 # also in the case of Makefile.modperl PERL_INC is defined 773 774 # this works with at least ld(1) on powerpc-ibm-aix5.1.0.0: 775 # -berok ignores symbols resolution problems (they will be 776 # resolved at run-time 777 # -brtl prepares the object for run-time loading 778 # LDFLAGS already inserts -brtl 779 $val .= " ${Wl}-berok"; 780 # XXX: instead of -berok, could make sure that we have: 781 # -Lpath/to/CORE -lperl 782 # -bI:$path/apr.exp -bI:$path/aprutil.exp -bI:$path/httpd.exp 783 # -bI:$path/modperl_*.exp 784 # - don't import modperl_*.exp in Makefile.modperl which 785 # exports -bE:$path/modperl_*.exp 786 # - can't rely on -bI:$path/perl.exp, because it's incomplete, 787 # use -lperl instead 788 # - the issue with using apr/aprutil/httpd.exp is to pick the 789 # right path if httpd wasn't yet installed 790 } 791 792 $val; 793} 794 795sub perl_config { 796 my ($self, $key) = @_; 797 798 my $val = $Config{$key} || ''; 799 800 my $method = \&{"perl_config_$key"}; 801 if (defined &$method) { 802 return $method->($self, $val); 803 } 804 805 return $val; 806} 807 808sub find_in_inc { 809 my $name = shift; 810 for (@INC) { 811 my $file; 812 if (-e ($file = "$_/auto/Apache2/$name")) { 813 return $file; 814 } 815 } 816} 817 818sub libpth { 819 my $self = shift; 820 $self->{libpth} ||= [split /\s+/, $Config{libpth}]; 821 return wantarray ? @{ $self->{libpth} } : $self->{libpth}; 822} 823 824sub find_dlfile { 825 my ($self, $name) = (shift, shift); 826 827 require DynaLoader; 828 require AutoLoader; #eek 829 830 my $found = 0; 831 my $loc = ""; 832 my (@path) = ($self->libpth, @_); 833 834 for (@path) { 835 if ($found = DynaLoader::dl_findfile($_, "-l$name")) { 836 $loc = $_; 837 last; 838 } 839 } 840 841 return wantarray ? ($loc, $found) : $found; 842} 843 844sub find_dlfile_maybe { 845 my ($self, $name) = @_; 846 847 my $path = $self->libpth; 848 849 my @maybe; 850 my $lib = 'lib' . $name; 851 852 for (@$path) { 853 push @maybe, grep { ! -l $_ } <$_/$lib.*>; 854 } 855 856 return \@maybe; 857} 858 859sub lib_check { 860 my ($self, $name) = @_; 861 return unless $self->perl_config('libs') =~ /$name/; 862 863 return if $self->find_dlfile($name); 864 865 my $maybe = $self->find_dlfile_maybe($name); 866 my $suggest = @$maybe ? 867 "You could just symlink it to $maybe->[0]" : 868 'You might need to install Perl from source'; 869 $self->phat_warn(<<EOF); 870Your Perl is configured to link against lib$name, 871 but lib$name.so was not found. 872 $suggest 873EOF 874} 875 876#--- user interaction --- 877 878sub prompt { 879 my ($self, $q, $default) = @_; 880 return $default if $self->{MP_PROMPT_DEFAULT}; 881 require ExtUtils::MakeMaker; 882 ExtUtils::MakeMaker::prompt($q, $default); 883} 884 885sub prompt_y { 886 my ($self, $q) = @_; 887 $self->prompt($q, 'y') =~ /^y/i; 888} 889 890sub prompt_n { 891 my ($self, $q) = @_; 892 $self->prompt($q, 'n') =~ /^n/i; 893} 894 895sub phat_warn { 896 my ($self, $msg, $abort) = @_; 897 my $level = $abort ? 'ERROR' : 'WARNING'; 898 warn <<EOF; 899************* $level ************* 900 901 $msg 902 903************* $level ************* 904EOF 905 if ($abort) { 906 exit 1; 907 } 908 else { 909 sleep 5; 910 } 911} 912 913#--- constructors --- 914 915my $bpm = 'Apache2/BuildConfig.pm'; 916 917sub build_config { 918 my $self = shift; 919 my $bpm_mtime = 0; 920 921 $bpm_mtime = (stat _)[9] if $INC{$bpm} && -e $INC{$bpm}; 922 923 if (-e "lib/$bpm" and (stat _)[9] > $bpm_mtime) { 924 #reload if Makefile.PL has regenerated 925 unshift @INC, 'lib'; 926 delete $INC{$bpm}; 927 eval { require Apache2::BuildConfig; }; 928 shift @INC; 929 } 930 else { 931 eval { require Apache2::BuildConfig; }; 932 } 933 934 return bless {}, (ref($self) || $self) if $@; 935 return Apache2::BuildConfig->new; 936} 937 938sub new { 939 my $class = shift; 940 941 my $self = bless { 942 cwd => Cwd::fastcwd(), 943 MP_LIBNAME => 'mod_perl', 944 MP_APXS => undef, # so we know we haven't tried to set it yet 945 @_, 946 }, $class; 947 948 $self->{MP_APR_LIB} = 'aprext'; 949 950 ModPerl::BuildOptions->init($self) if delete $self->{init}; 951 952 $self; 953} 954 955sub DESTROY {} 956 957my %default_files = ( 958 'build_config' => 'lib/Apache2/BuildConfig.pm', 959 'ldopts' => 'src/modules/perl/ldopts', 960 'makefile' => 'src/modules/perl/Makefile', 961); 962 963sub clean_files { 964 my $self = shift; 965 [sort map { $self->default_file($_) } keys %default_files]; 966} 967 968sub default_file { 969 my ($self, $name, $override) = @_; 970 my $key = join '_', 'file', $name; 971 $self->{$key} ||= ($override || $default_files{$name}); 972} 973 974sub file_path { 975 my $self = shift; 976 977 # work around when Apache2::BuildConfig has not been created yet 978 return unless $self && $self->{cwd}; 979 980 my @files = map { m:^/: ? $_ : join('/', $self->{cwd}, $_) } @_; 981 return wantarray ? @files : $files[0]; 982} 983 984sub freeze { 985 require Data::Dumper; 986 local $Data::Dumper::Terse = 1; 987 local $Data::Dumper::Sortkeys = 1; 988 my $data = Data::Dumper::Dumper(shift); 989 chomp $data; 990 $data; 991} 992 993sub save_ldopts { 994 my ($self, $file) = @_; 995 996 $file ||= $self->default_file('ldopts', $file); 997 my $ldopts = $self->ldopts; 998 999 open my $fh, '>', $file or die "open $file: $!"; 1000 print $fh "#!/bin/sh\n\necho $ldopts\n"; 1001 close $fh; 1002 chmod 0755, $file; 1003} 1004 1005sub noedit_warning_hash { 1006 ModPerl::Code::noedit_warning_hash(__PACKAGE__); 1007} 1008 1009sub save { 1010 my ($self, $file) = @_; 1011 1012 delete $INC{$bpm}; 1013 1014 $file ||= $self->default_file('build_config'); 1015 $file = $self->file_path($file); 1016 1017 my $obj = $self->freeze; 1018 $obj =~ s/^\s{9}//mg; 1019 $obj =~ s/^/ /; 1020 1021 open my $fh, '>', $file or die "open $file: $!"; 1022 1023 #work around autosplit braindeadness 1024 my $package = 'package Apache2::BuildConfig'; 1025 1026 print $fh noedit_warning_hash(); 1027 1028 print $fh <<EOF; 1029$package; 1030 1031use Apache2::Build (); 1032 1033sub new { 1034$obj; 1035} 1036 10371; 1038EOF 1039 1040 close $fh or die "failed to write $file: $!"; 1041} 1042 1043sub rebuild { 1044 my $self = __PACKAGE__->build_config; 1045 my @opts = map { qq[$_='$self->{$_}'] } sort grep /^MP_/, keys %$self; 1046 my $command = "perl Makefile.PL @opts"; 1047 print "Running: $command\n"; 1048 system $command; 1049} 1050# % perl -MApache2::Build -e rebuild 1051*main::rebuild = \&rebuild if $0 eq '-e'; 1052 1053#--- attribute access --- 1054 1055sub is_dynamic { shift->{MP_USE_DSO} } 1056 1057sub default_dir { 1058 my $build = shift->build_config; 1059 1060 return $build->dir || '../apache_x.x/src'; 1061} 1062 1063sub dir { 1064 my ($self, $dir) = @_; 1065 1066 if ($dir) { 1067 for (qw(ap_includedir)) { 1068 delete $self->{$_}; 1069 } 1070 if ($dir =~ m:^\.\.[/\\]:) { 1071 $dir = "$self->{cwd}/$dir"; 1072 } 1073 $self->{dir} = $dir; 1074 } 1075 1076 return $self->{dir} if $self->{dir}; 1077 1078 # be careful with the guesswork, or may pick up some wrong headers 1079 if (IS_MOD_PERL_BUILD && $self->{MP_AP_PREFIX}) { 1080 my $build = $self->build_config; 1081 1082 if (my $bdir = $build->{'dir'}) { 1083 for ($bdir, "../$bdir", "../../$bdir") { 1084 if (-d $_) { 1085 $dir = $_; 1086 last; 1087 } 1088 } 1089 } 1090 } 1091 1092 $dir ||= $self->{MP_AP_PREFIX}; 1093 1094# we no longer install Apache headers, so don't bother looking in @INC 1095# might end up finding 1.x headers anyhow 1096# unless ($dir and -d $dir) { 1097# for (@INC) { 1098# last if -d ($dir = "$_/auto/Apache2/include"); 1099# } 1100# } 1101 return $self->{dir} = $dir ? canonpath(rel2abs $dir) : undef; 1102} 1103 1104#--- finding apache *.h files --- 1105 1106sub find { 1107 my $self = shift; 1108 my %seen = (); 1109 my @dirs = (); 1110 1111 for my $src_dir ($self->dir, 1112 $self->default_dir, 1113 '../httpd-2.0') 1114 { 1115 next unless $src_dir; 1116 next unless (-d $src_dir || -l $src_dir); 1117 next if $seen{$src_dir}++; 1118 push @dirs, $src_dir; 1119 #$modified{$src_dir} = (stat($src_dir))[9]; 1120 } 1121 1122 return @dirs; 1123} 1124 1125sub ap_includedir { 1126 my ($self, $d) = @_; 1127 1128 return $self->{ap_includedir} 1129 if $self->{ap_includedir} and -d $self->{ap_includedir}; 1130 1131 return unless $d ||= $self->apxs('-q' => 'INCLUDEDIR') || $self->dir; 1132 1133 if (-e "$d/include/ap_release.h") { 1134 return $self->{ap_includedir} = "$d/include"; 1135 } 1136 1137 $self->{ap_includedir} = $d; 1138} 1139 1140# This is necessary for static builds that needs to make a 1141# difference between where the apache headers are (to build 1142# against) and where they will be installed (to install our 1143# own headers alongside) 1144# 1145# ap_exp_includedir is where apache is going to install its 1146# headers to 1147sub ap_exp_includedir { 1148 my ($self) = @_; 1149 1150 return $self->{ap_exp_includedir} if $self->{ap_exp_includedir}; 1151 1152 my $build_vars = File::Spec->catfile($self->{MP_AP_PREFIX}, 1153 qw(build config_vars.mk)); 1154 open my $vars, "<$build_vars" or die "Couldn't open $build_vars $!"; 1155 my $ap_exp_includedir; 1156 while (<$vars>) { 1157 if (/exp_includedir\s*=\s*(.*)/) { 1158 $ap_exp_includedir = $1; 1159 last; 1160 } 1161 } 1162 1163 $self->{ap_exp_includedir} = $ap_exp_includedir; 1164} 1165 1166sub install_headers_dir { 1167 my ($self) = @_; 1168 if ($self->should_build_apache) { 1169 return $self->ap_exp_includedir(); 1170 } 1171 else { 1172 return $self->ap_includedir(); 1173 } 1174} 1175 1176 1177# where apr-config and apu-config reside 1178sub apr_bindir { 1179 my ($self) = @_; 1180 1181 $self->apr_config_path unless $self->{apr_bindir}; 1182 $self->{apr_bindir}; 1183} 1184 1185sub apr_generation { 1186 my ($self) = @_; 1187 return $self->httpd_version_as_int =~ m/2[1-9]\d+/ ? 1 : 0; 1188} 1189 1190# returns an array of apr/apu linking flags (--link-ld --libs) if found 1191# an empty array otherwise 1192my @apru_link_flags = (); 1193sub apru_link_flags { 1194 my ($self) = @_; 1195 1196 return @apru_link_flags if @apru_link_flags; 1197 1198 # first use apu_config_path and then apr_config_path in order to 1199 # resolve the symbols right during linking 1200 for ($self->apu_config_path, $self->apr_config_path) { 1201 my $flags = '--link-ld --libs'; 1202 $flags .= ' --ldflags' unless (WIN32); 1203 if (my $link = $_ && -x $_ && qx{$_ $flags}) { 1204 chomp $link; 1205 1206 # Change '/path/to/libanything.la' to '-L/path/to -lanything' 1207 if (CYGWIN) { 1208 $link =~ s|(\S*)/lib([^.\s]+)\.\S+|-L$1 -l$2|g; 1209 } 1210 1211 if ($self->httpd_is_source_tree) { 1212 my @libs; 1213 while ($link =~ m/-L(\S+)/g) { 1214 my $dir = File::Spec->catfile($1, '.libs'); 1215 push @libs, $dir if -d $dir; 1216 } 1217 push @apru_link_flags, join ' ', map { "-L$_" } @libs; 1218 } 1219 push @apru_link_flags, $link; 1220 } 1221 } 1222 1223 return @apru_link_flags; 1224} 1225 1226sub apr_config_path { 1227 shift->apru_config_path("apr"); 1228} 1229 1230sub apu_config_path { 1231 shift->apru_config_path("apu"); 1232} 1233 1234sub apru_config_path { 1235 my ($self, $what) = @_; 1236 1237 my $key = "${what}_config_path"; # apr_config_path 1238 my $mp_key = "MP_" . uc($what) . "_CONFIG"; # MP_APR_CONFIG 1239 my $bindir = uc($what) . "_BINDIR"; # APR_BINDIR 1240 1241 return $self->{$key} if $self->{$key} and -x $self->{$key}; 1242 1243 if (exists $self->{$mp_key} and -x $self->{$mp_key}) { 1244 $self->{$key} = $self->{$mp_key}; 1245 } 1246 1247 my $config = $self->apr_generation ? "$what-1-config" : "$what-config"; 1248 1249 if (!$self->{$key}) { 1250 my @tries = (); 1251 if ($self->httpd_is_source_tree) { 1252 for my $base (grep defined $_, $self->dir) { 1253 push @tries, grep -d $_, 1254 map catdir($base, "srclib", $_), qw(apr apr-util); 1255 } 1256 1257 # Check for MP_AP_CONFIGURE="--with-apr[-util]=DIR|FILE" 1258 my $what_long = ($what eq 'apu') ? 'apr-util' : 'apr'; 1259 if ($self->{MP_AP_CONFIGURE} && 1260 $self->{MP_AP_CONFIGURE} =~ /--with-${what_long}=(\S+)/) { 1261 my $dir = $1; 1262 $dir = dirname $dir if -f $dir; 1263 push @tries, grep -d $_, $dir, catdir $dir, 'bin'; 1264 } 1265 } 1266 else { 1267 push @tries, grep length, 1268 map $self->apxs(-q => $_), $bindir, "BINDIR"; 1269 push @tries, catdir $self->{MP_AP_PREFIX}, "bin" 1270 if exists $self->{MP_AP_PREFIX} and -d $self->{MP_AP_PREFIX}; 1271 } 1272 1273 @tries = map { catfile $_, $config } @tries; 1274 if (WIN32) { 1275 my $ext = '.bat'; 1276 for (@tries) { 1277 $_ .= $ext if ($_ and $_ !~ /$ext$/); 1278 } 1279 } 1280 1281 for my $try (@tries) { 1282 next unless -x $try; 1283 $self->{$key} = $try; 1284 } 1285 } 1286 1287 $self->{$key} ||= Apache::TestConfig::which($config); 1288 1289 # apr_bindir makes sense only if httpd/apr is installed, if we are 1290 # building against the source tree we can't link against 1291 # apr/aprutil libs 1292 unless ($self->httpd_is_source_tree) { 1293 $self->{apr_bindir} = $self->{$key} 1294 ? dirname $self->{$key} 1295 : ''; 1296 } 1297 1298 $self->{$key}; 1299} 1300 1301sub apr_includedir { 1302 my ($self) = @_; 1303 1304 return $self->{apr_includedir} 1305 if $self->{apr_includedir} and -d $self->{apr_includedir}; 1306 1307 my $incdir; 1308 my $apr_config_path = $self->apr_config_path; 1309 1310 if ($apr_config_path) { 1311 my $httpd_version = $self->httpd_version; 1312 chomp($incdir = `$apr_config_path --includedir`); 1313 } 1314 1315 unless ($incdir and -d $incdir) { 1316 # falling back to the default when apr header files are in the 1317 # same location as the httpd header files 1318 $incdir = $self->ap_includedir; 1319 } 1320 1321 my @tries = ($incdir); 1322 if ($self->httpd_is_source_tree) { 1323 my $path = catdir $self->dir, "srclib", "apr", "include"; 1324 push @tries, $path if -d $path; 1325 } 1326 1327 1328 for (@tries) { 1329 next unless $_ && -e catfile $_, "apr.h"; 1330 $self->{apr_includedir} = $_; 1331 last; 1332 } 1333 1334 unless ($self->{apr_includedir}) { 1335 error "Can't find apr include/ directory,", 1336 "use MP_APR_CONFIG=/path/to/apr-config"; 1337 exit 1; 1338 } 1339 1340 $self->{apr_includedir}; 1341} 1342 1343#--- parsing apache *.h files --- 1344 1345sub mmn_eq { 1346 my ($class, $dir) = @_; 1347 1348 return 1 if WIN32; #just assume, till Apache2::Build works under win32 1349 1350 my $instsrc; 1351 { 1352 local @INC = grep { !/blib/ } @INC; 1353 my $instdir; 1354 for (@INC) { 1355 last if -d ($instdir = "$_/auto/Apache2/include"); 1356 } 1357 $instsrc = $class->new(dir => $instdir); 1358 } 1359 my $targsrc = $class->new($dir ? (dir => $dir) : ()); 1360 1361 my $inst_mmn = $instsrc->module_magic_number; 1362 my $targ_mmn = $targsrc->module_magic_number; 1363 1364 unless ($inst_mmn && $targ_mmn) { 1365 return 0; 1366 } 1367 if ($inst_mmn == $targ_mmn) { 1368 return 1; 1369 } 1370 print "Installed MMN $inst_mmn does not match target $targ_mmn\n"; 1371 1372 return 0; 1373} 1374 1375sub module_magic_number { 1376 my $self = shift; 1377 1378 return $self->{mmn} if $self->{mmn}; 1379 1380 my $d = $self->ap_includedir; 1381 1382 return 0 unless $d; 1383 1384 #return $mcache{$d} if $mcache{$d}; 1385 my $fh; 1386 for (qw(ap_mmn.h http_config.h)) { 1387 last if open $fh, "$d/$_"; 1388 } 1389 return 0 unless $fh; 1390 1391 my $n; 1392 my $mmn_pat = join '|', qw(MODULE_MAGIC_NUMBER_MAJOR MODULE_MAGIC_NUMBER); 1393 while(<$fh>) { 1394 if(s/^\#define\s+($mmn_pat)\s+(\d+).*/$2/) { 1395 chomp($n = $_); 1396 last; 1397 } 1398 } 1399 close $fh; 1400 1401 $self->{mmn} = $n 1402} 1403 1404sub fold_dots { 1405 my $v = shift; 1406 $v =~ s/\.//g; 1407 $v .= '0' if length $v < 3; 1408 $v; 1409} 1410 1411sub httpd_version_as_int { 1412 my ($self, $dir) = @_; 1413 my $v = $self->httpd_version($dir); 1414 fold_dots($v); 1415} 1416 1417sub httpd_version_cache { 1418 my ($self, $dir, $v) = @_; 1419 return '' unless $dir; 1420 $self->{httpd_version}->{$dir} = $v if $v; 1421 $self->{httpd_version}->{$dir}; 1422} 1423 1424sub httpd_version { 1425 my ($self, $dir) = @_; 1426 1427 return unless $dir = $self->ap_includedir($dir); 1428 1429 if (my $v = $self->httpd_version_cache($dir)) { 1430 return $v; 1431 } 1432 1433 my $header = "$dir/ap_release.h"; 1434 open my $fh, $header or do { 1435 error "Unable to open $header: $!"; 1436 return undef; 1437 }; 1438 1439 my $version; 1440 1441 while (<$fh>) { 1442 #now taking bets on how many friggin times this will change 1443 #over the course of apache 2.0. 1.3 changed it at least a half 1444 #dozen times. hopefully it'll stay in the same file at least. 1445 if (/^\#define\s+AP_SERVER_MAJORVERSION\s+\"(\d+)\"/) { 1446 #XXX could be more careful here. whatever. see above. 1447 my $major = $1; 1448 my $minor = (split /\s+/, scalar(<$fh>))[-1]; 1449 my $patch = (split /\s+/, scalar(<$fh>))[-1]; 1450 $version = join '.', $major, $minor, $patch; 1451 $version =~ s/\"//g; 1452 last; 1453 } 1454 elsif (/^\#define\s+AP_SERVER_BASEREVISION\s+\"(.*)\"/) { 1455 $version = $1; 1456 last; 1457 } 1458 elsif(/^\#define\s+AP_SERVER_MAJORVERSION_NUMBER\s+(\d+)/) { 1459 # new 2.1 config 1460 my $major = $1; 1461 my $minor = (split /\s+/, scalar(<$fh>))[-1]; 1462 my $patch = (split /\s+/, scalar(<$fh>))[-1]; 1463 1464 my ($define, $macro, $dev) = (split /\s+/, scalar(<$fh>)); 1465 1466 if ($macro =~ /AP_SERVER_DEVBUILD_BOOLEAN/ && $dev eq '1') { 1467 $dev = "-dev"; 1468 } 1469 else { 1470 $dev = ""; 1471 } 1472 1473 $version = join '.', $major, $minor, "$patch$dev"; 1474 $version =~ s/\"//g; 1475 last; 1476 } 1477 } 1478 1479 close $fh; 1480 1481 debug "parsed version $version from ap_release.h"; 1482 1483 $self->httpd_version_cache($dir, $version); 1484} 1485 1486my %wanted_apr_config = map { $_, 1} qw( 1487 HAS_THREADS HAS_DSO HAS_MMAP HAS_RANDOM HAS_SENDFILE 1488 HAS_LARGE_FILES HAS_INLINE HAS_FORK 1489); 1490 1491sub get_apr_config { 1492 my $self = shift; 1493 1494 return $self->{apr_config} if $self->{apr_config}; 1495 1496 my $header = catfile $self->apr_includedir, "apr.h"; 1497 open my $fh, $header or do { 1498 error "Unable to open $header: $!"; 1499 return undef; 1500 }; 1501 1502 my %cfg; 1503 while (<$fh>) { 1504 next unless s/^\#define\s+APR_((HAVE|HAS|USE)_\w+)/$1/; 1505 chomp; 1506 my ($name, $val) = split /\s+/, $_, 2; 1507 next unless $wanted_apr_config{$name}; 1508 $val =~ s/\s+$//; 1509 next unless $val =~ /^\d+$/; 1510 $cfg{$name} = $val; 1511 } 1512 1513 $self->{apr_config} = \%cfg; 1514} 1515 1516#--- generate Makefile --- 1517 1518sub canon_make_attr { 1519 my ($self, $name) = (shift, shift); 1520 1521 my $attr = join '_', 'MODPERL', uc $name; 1522 $self->{$attr} = "@_"; 1523 "$attr = $self->{$attr}\n\n"; 1524} 1525 1526sub xsubpp { 1527 my $self = shift; 1528 my $xsubpp = join ' ', '$(MODPERL_PERLPATH)', 1529 '$(MODPERL_PRIVLIBEXP)/ExtUtils/xsubpp', 1530 '-typemap', '$(MODPERL_PRIVLIBEXP)/ExtUtils/typemap'; 1531 1532 my $typemap = $self->file_path('lib/typemap'); 1533 if (-e $typemap) { 1534 $xsubpp .= join ' ', 1535 ' -typemap', $typemap; 1536 } 1537 1538 $xsubpp; 1539} 1540 1541sub make_xs { 1542 my ($self, $fh) = @_; 1543 1544 print $fh $self->canon_make_attr(xsubpp => $self->xsubpp); 1545 1546 return [] unless $self->{XS}; 1547 1548 my @files; 1549 my @xs_targ; 1550 1551 foreach my $name (sort keys %{ $self->{XS} }) { 1552 my $xs = $self->{XS}->{$name}; 1553 #Foo/Bar.xs => Foo_Bar.c 1554 (my $c = $xs) =~ s:.*?WrapXS/::; 1555 $c =~ s:/:_:g; 1556 $c =~ s:\.xs$:.c:; 1557 1558 push @files, $c; 1559 1560 push @xs_targ, <<EOF; 1561$c: $xs 1562\t\$(MODPERL_XSUBPP) $xs > \$*.xsc && \$(MODPERL_MV) \$*.xsc \$@ 1563 1564EOF 1565 } 1566 1567 my %o = (xs_o_files => 'o', xs_o_pic_files => 'lo'); 1568 1569 for my $ext (qw(xs_o_files xs_o_pic_files)) { 1570 print $fh $self->canon_make_attr($ext, map { 1571 (my $file = $_) =~ s/c$/$o{$ext}/; $file; 1572 } @files); 1573 } 1574 1575 print $fh $self->canon_make_attr(xs_clean_files => @files); 1576 1577 \@xs_targ; 1578} 1579 1580#when we use a bit of MakeMaker, make it use our values for these vars 1581my %perl_config_pm_alias = ( 1582 ABSPERL => 'perlpath', 1583 ABSPERLRUN => 'perlpath', 1584 PERL => 'perlpath', 1585 PERLRUN => 'perlpath', 1586 PERL_LIB => 'privlibexp', 1587 PERL_ARCHLIB => 'archlibexp', 1588); 1589 1590my $mm_replace = join '|', keys %perl_config_pm_alias; 1591 1592# get rid of dups 1593my %perl_config_pm_alias_values = reverse %perl_config_pm_alias; 1594my @perl_config_pm_alias_values = keys %perl_config_pm_alias_values; 1595 1596my @perl_config_pm = sort(@perl_config_pm_alias_values, qw(cc cpprun 1597 rm ranlib lib_ext obj_ext cccdlflags lddlflags optimize)); 1598 1599sub mm_replace { 1600 my $val = shift; 1601 $$val =~ s/\(($mm_replace)\)/(MODPERL_\U$perl_config_pm_alias{$1})/g; 1602} 1603 1604#help prevent warnings 1605my @mm_init_vars = (BASEEXT => ''); 1606 1607sub make_tools { 1608 my ($self, $fh) = @_; 1609 1610 for (@perl_config_pm) { 1611 print $fh $self->canon_make_attr($_, $self->perl_config($_)); 1612 } 1613 1614 require ExtUtils::MakeMaker; 1615 my $mm = bless { @mm_init_vars }, 'MM'; 1616 1617 # Fake initialize MakeMaker 1618 foreach my $m (qw(init_main init_others init_tools)) { 1619 $mm->$m() if $mm->can($m); 1620 } 1621 1622 for (qw(rm_f mv ld ar cp test_f)) { 1623 my $val = $mm->{"\U$_"}; 1624 if ($val) { 1625 mm_replace(\$val); 1626 } 1627 else { 1628 $val = $Config{$_}; 1629 } 1630 print $fh $self->canon_make_attr($_ => $val); 1631 } 1632} 1633 1634sub export_files_MSWin32 { 1635 my $self = shift; 1636 my $xs_dir = $self->file_path("xs"); 1637 "-def:$xs_dir/modperl.def"; 1638} 1639 1640sub export_files_aix { 1641 my $self = shift; 1642 1643 my $Wl = $self->ldopts_prefix; 1644 # there are several modperl_*.exp, not just $(BASEEXT).exp 1645 # $(BASEEXT).exp resolves to modperl_global.exp 1646 my $xs_dir = $self->file_path("xs"); 1647 join " ", map "${Wl}-bE:$xs_dir/modperl_$_.exp", qw(inline ithreads); 1648} 1649 1650sub dynamic_link_header_default { 1651 return <<'EOF'; 1652$(MODPERL_LIBNAME).$(MODPERL_DLEXT): $(MODPERL_PIC_OBJS) 1653 $(MODPERL_RM_F) $@ 1654 $(MODPERL_LD) $(MODPERL_LDDLFLAGS) \ 1655 $(MODPERL_AP_LIBS) \ 1656 $(MODPERL_PIC_OBJS) $(MODPERL_LDOPTS) \ 1657EOF 1658} 1659 1660sub dynamic_link_default { 1661 my $self = shift; 1662 1663 my $link = $self->dynamic_link_header_default . "\t" . '-o $@'; 1664 1665 my $ranlib = "\t" . '$(MODPERL_RANLIB) $@' . "\n"; 1666 1667 $link .= "\n" . $ranlib unless (DARWIN or OPENBSD); 1668 1669 $link; 1670} 1671 1672sub dynamic_link_MSWin32 { 1673 my $self = shift; 1674 my $defs = $self->export_files_MSWin32; 1675 my $symbols = $self->modperl_symbols_MSWin32; 1676 return $self->dynamic_link_header_default . 1677 "\t$defs" . 1678 ($symbols ? ' \\' . "\n\t-pdb:$symbols" : '') . 1679 ' -out:$@' . "\n\t" . 1680 'if exist $(MODPERL_MANIFEST_LOCATION)' . " \\\n\t" . 1681 'mt /nologo /manifest $(MODPERL_MANIFEST_LOCATION)' . " \\\n\t" . 1682 '/outputresource:$@;2' . "\n\n"; 1683} 1684 1685sub dynamic_link_aix { 1686 my $self = shift; 1687 my $link = $self->dynamic_link_header_default . 1688 "\t" . $self->export_files_aix . " \\\n" . 1689 "\t" . '-o $@' . " \n" . 1690 "\t" . '$(MODPERL_RANLIB) $@'; 1691} 1692 1693sub dynamic_link_cygwin { 1694 my $self = shift; 1695 return <<'EOF'; 1696$(MODPERL_LIBNAME).$(MODPERL_DLEXT): $(MODPERL_PIC_OBJS) 1697 $(MODPERL_RM_F) $@ 1698 $(MODPERL_CC) -shared -o $@ \ 1699 -Wl,--out-implib=$(MODPERL_LIBNAME).dll.a \ 1700 -Wl,--export-all-symbols -Wl,--enable-auto-import \ 1701 -Wl,--enable-auto-image-base -Wl,--stack,8388608 \ 1702 $(MODPERL_PIC_OBJS) \ 1703 $(MODPERL_LDDLFLAGS) $(MODPERL_LDOPTS) \ 1704 $(MODPERL_AP_LIBS) 1705 $(MODPERL_RANLIB) $@ 1706EOF 1707} 1708 1709sub dynamic_link { 1710 my $self = shift; 1711 my $link = \&{"dynamic_link_$^O"}; 1712 $link = \&dynamic_link_default unless defined &$link; 1713 $link->($self); 1714} 1715 1716# Returns the link flags for the apache shared core library 1717my $apache_corelib_cygwin; 1718sub apache_corelib_cygwin { 1719 return $apache_corelib_cygwin if $apache_corelib_cygwin; 1720 1721 my $self = shift; 1722 my $mp_src = "$self->{cwd}/src/modules/perl"; 1723 my $core = 'httpd2core'; 1724 1725 # There's a problem with user-installed perl on cygwin. 1726 # MakeMaker doesn't know about the .dll.a libs and warns 1727 # about missing -lhttpd2core. "Fix" it by copying 1728 # the lib and adding .a suffix. 1729 # For the static build create a soft link, because libhttpd2core.dll.a 1730 # doesn't exist at this time. 1731 if ($self->is_dynamic) { 1732 my $libpath = $self->apxs(-q => 'exp_libdir'); 1733 File::Copy::copy("$libpath/lib$core.dll.a", "$mp_src/lib$core.a"); 1734 } else { 1735 my $libpath = catdir($self->{MP_AP_PREFIX}, '.libs'); 1736 mkdir $libpath unless -d $libpath; 1737 qx{touch $libpath/lib$core.dll.a && \ 1738 ln -fs $libpath/lib$core.dll.a $mp_src/lib$core.a}; 1739 } 1740 1741 $apache_corelib_cygwin = "-L$mp_src -l$core"; 1742} 1743 1744sub apache_libs_MSWin32 { 1745 my $self = shift; 1746 my $prefix = $self->apxs(-q => 'PREFIX') || $self->dir; 1747 my $lib = catdir $prefix, 'lib'; 1748 opendir(my $dir, $lib) or die qq{Cannot opendir $lib: $!}; 1749 my @libs = map {catfile($lib, $_)} 1750 grep /^lib(apr|aprutil|httpd)\b\S*?\.lib$/, readdir $dir; 1751 closedir $dir; 1752 "@libs"; 1753} 1754 1755sub apache_libs_cygwin { 1756 my $self = shift; 1757 join ' ', $self->apache_corelib_cygwin, $self->apru_link_flags; 1758} 1759 1760sub apache_libs { 1761 my $self = shift; 1762 my $libs = \&{"apache_libs_$^O"}; 1763 return "" unless defined &$libs; 1764 $libs->($self); 1765} 1766 1767sub modperl_libs_MSWin32 { 1768 my $self = shift; 1769 "$self->{cwd}/src/modules/perl/$self->{MP_LIBNAME}.lib"; 1770} 1771 1772sub modperl_libs_cygwin { 1773 my $self = shift; 1774 return '' unless $self->is_dynamic; 1775 return "-L$self->{cwd}/src/modules/perl -l$self->{MP_LIBNAME}"; 1776} 1777 1778sub modperl_libs { 1779 my $self = shift; 1780 my $libs = \&{"modperl_libs_$^O"}; 1781 return "" unless defined &$libs; 1782 $libs->($self); 1783} 1784 1785sub modperl_libpath_MSWin32 { 1786 my $self = shift; 1787 # mod_perl.lib will be installed into MP_AP_PREFIX/lib 1788 # for use by 3rd party xs modules 1789 "$self->{cwd}/src/modules/perl/$self->{MP_LIBNAME}.lib"; 1790} 1791 1792sub modperl_libpath_cygwin { 1793 my $self = shift; 1794 "$self->{cwd}/src/modules/perl/$self->{MP_LIBNAME}.dll.a"; 1795} 1796 1797sub modperl_libpath { 1798 my $self = shift; 1799 my $libpath = \&{"modperl_libpath_$^O"}; 1800 return "" unless defined &$libpath; 1801 $libpath->($self); 1802} 1803 1804# returns the directory and name of the aprext lib built under blib/ 1805sub mp_apr_blib { 1806 my $self = shift; 1807 return unless (my $mp_apr_lib = $self->{MP_APR_LIB}); 1808 my $lib_mp_apr_lib = 'lib' . $mp_apr_lib; 1809 my @dirs = qw(blib arch auto); 1810 my $apr_blib = catdir $self->{cwd}, @dirs, $lib_mp_apr_lib; 1811 my $full_libname = $lib_mp_apr_lib . $Config{lib_ext}; 1812 return ($apr_blib, $full_libname); 1813} 1814 1815sub mp_apr_lib_MSWin32 { 1816 my $self = shift; 1817 # The MP_APR_LIB will be installed into MP_AP_PREFIX/lib 1818 # for use by 3rd party xs modules 1819 my ($dir, $lib) = $self->mp_apr_blib(); 1820 $lib =~ s[^lib(\w+)$Config{lib_ext}$][$1]; 1821 $dir = Win32::GetShortPathName($dir); 1822 return qq{ -L$dir -l$lib }; 1823} 1824 1825sub mp_apr_lib_cygwin { 1826 my $self = shift; 1827 my ($dir, $lib) = $self->mp_apr_blib(); 1828 $lib =~ s[^lib(\w+)$Config{lib_ext}$][$1]; 1829 my $libs = "-L$dir -l$lib"; 1830 1831 # This is ugly, but is the only way to prevent the "undefined 1832 # symbols" error 1833 $libs .= join ' ', '', 1834 '-L' . catdir($self->perl_config('archlibexp'), 'CORE'), '-lperl'; 1835 1836 $libs; 1837} 1838 1839# linking used for the aprext lib used to build APR/APR::* 1840sub mp_apr_lib { 1841 my $self = shift; 1842 my $libs = \&{"mp_apr_lib_$^O"}; 1843 return "" unless defined &$libs; 1844 $libs->($self); 1845} 1846 1847sub modperl_symbols_MSWin32 { 1848 my $self = shift; 1849 return "" unless $self->{MP_DEBUG}; 1850 "$self->{cwd}/src/modules/perl/$self->{MP_LIBNAME}.pdb"; 1851} 1852 1853sub modperl_symbols { 1854 my $self = shift; 1855 my $symbols = \&{"modperl_symbols_$^O"}; 1856 return "" unless defined &$symbols; 1857 $symbols->($self); 1858} 1859 1860sub write_src_makefile { 1861 my $self = shift; 1862 my $code = ModPerl::Code->new; 1863 my $path = $code->path; 1864 1865 my $install = <<'EOI'; 1866install: 1867EOI 1868 if (!$self->should_build_apache) { 1869 $install .= <<'EOI'; 1870# install mod_perl.so 1871 @$(MKPATH) $(DESTDIR)$(MODPERL_AP_LIBEXECDIR) 1872 $(MODPERL_TEST_F) $(MODPERL_LIB_DSO) && \ 1873 $(MODPERL_CP) $(MODPERL_LIB_DSO) $(DESTDIR)$(MODPERL_AP_LIBEXECDIR) 1874EOI 1875 } 1876 1877 $install .= <<'EOI'; 1878# install mod_perl .h files 1879 @$(MKPATH) $(DESTDIR)$(MODPERL_AP_INCLUDEDIR) 1880 $(MODPERL_CP) $(MODPERL_H_FILES) $(DESTDIR)$(MODPERL_AP_INCLUDEDIR) 1881EOI 1882 1883 my $mf = $self->default_file('makefile'); 1884 1885 open my $fh, '>', $mf or die "open $mf: $!"; 1886 1887 print $fh noedit_warning_hash(); 1888 1889 print $fh $self->canon_make_attr('makefile', basename $mf); 1890 1891 $self->make_tools($fh); 1892 1893 print $fh $self->canon_make_attr('ap_libs', $self->apache_libs); 1894 1895 print $fh $self->canon_make_attr('libname', $self->{MP_LIBNAME}); 1896 print $fh $self->canon_make_attr('dlext', 'so'); #always use .so 1897 1898 if (AIX) { 1899 my $xs_dir = $self->file_path("xs"); 1900 print $fh "BASEEXT = $xs_dir/modperl_global\n\n"; 1901 } 1902 1903 my %libs = ( 1904 dso => "$self->{MP_LIBNAME}.$self->{MODPERL_DLEXT}", 1905 static => "$self->{MP_LIBNAME}$self->{MODPERL_LIB_EXT}", 1906 ); 1907 1908 #XXX short-term compat for Apache::TestConfigPerl 1909 $libs{shared} = $libs{dso}; 1910 1911 foreach my $type (sort keys %libs) { 1912 my $lib = $libs{$type}; 1913 print $fh $self->canon_make_attr("lib_$type", $libs{$type}); 1914 } 1915 1916 if (my $symbols = $self->modperl_symbols) { 1917 print $fh $self->canon_make_attr('lib_symbols', $symbols); 1918 $install .= <<'EOI'; 1919# install mod_perl symbol file 1920 @$(MKPATH) $(MODPERL_AP_LIBEXECDIR) 1921 $(MODPERL_TEST_F) $(MODPERL_LIB_SYMBOLS) && \ 1922 $(MODPERL_CP) $(MODPERL_LIB_SYMBOLS) $(MODPERL_AP_LIBEXECDIR) 1923EOI 1924 } 1925 1926 if ($self->is_dynamic && (my $libs = $self->modperl_libpath)) { 1927 print $fh $self->canon_make_attr('lib_location', $libs); 1928 1929 # Visual Studio 8 on Win32 uses manifest files 1930 if (WIN32) { 1931 (my $manifest = $libs) =~ s/\.lib$/.so.manifest/; 1932 print $fh $self->canon_make_attr('manifest_location', $manifest); 1933 } 1934 1935 print $fh $self->canon_make_attr('ap_libdir', 1936 $self->ap_destdir(catdir $self->{MP_AP_PREFIX}, 'lib') 1937 ); 1938 1939 $install .= <<'EOI'; 1940# install mod_perl.lib 1941 @$(MKPATH) $(MODPERL_AP_LIBDIR) 1942 $(MODPERL_TEST_F) $(MODPERL_LIB_LOCATION) && \ 1943 $(MODPERL_CP) $(MODPERL_LIB_LOCATION) $(MODPERL_AP_LIBDIR) 1944EOI 1945 } 1946 1947 my $libperl = join '/', 1948 $self->perl_config('archlibexp'), 'CORE', $self->perl_config('libperl'); 1949 1950 #this is only used for deps, if libperl has changed, relink mod_perl.so 1951 #not all perl dists put libperl where it should be, so just leave this 1952 #out if it isn't in the proper place 1953 if (-e $libperl) { 1954 print $fh $self->canon_make_attr('libperl', $libperl); 1955 } 1956 1957 for my $method (qw(ccopts ldopts inc)) { 1958 print $fh $self->canon_make_attr($method, $self->$method()); 1959 } 1960 1961 for my $method (qw(c_files o_files o_pic_files h_files)) { 1962 print $fh $self->canon_make_attr($method, @{ $code->$method() }); 1963 } 1964 1965 my @libs; 1966 for my $type (sort map { uc } keys %libs) { 1967 next unless $self->{"MP_USE_$type"}; 1968 # on win32 mod_perl.lib must come after mod_perl.so 1969 $type eq 'STATIC' 1970 ? push @libs, $self->{"MODPERL_LIB_$type"} 1971 : unshift @libs, $self->{"MODPERL_LIB_$type"}; 1972 } 1973 1974 print $fh $self->canon_make_attr('lib', "@libs"); 1975 1976 print $fh $self->canon_make_attr('AP_INCLUDEDIR', 1977 $self->ap_destdir($self->install_headers_dir)); 1978 1979 print $fh $self->canon_make_attr('AP_LIBEXECDIR', 1980 $self->ap_destdir($self->apxs(-q => 'LIBEXECDIR'))); 1981 1982 my $xs_targ = $self->make_xs($fh); 1983 1984 print $fh <<'EOF'; 1985MODPERL_CCFLAGS = $(MODPERL_INC) $(MODPERL_CCOPTS) $(MODPERL_OPTIMIZE) 1986 1987MODPERL_CCFLAGS_SHLIB = $(MODPERL_CCFLAGS) $(MODPERL_CCCDLFLAGS) 1988 1989MODPERL_OBJS = $(MODPERL_O_FILES) $(MODPERL_XS_O_FILES) 1990 1991MODPERL_PIC_OBJS = $(MODPERL_O_PIC_FILES) $(MODPERL_XS_O_PIC_FILES) 1992 1993MKPATH = $(MODPERL_PERLPATH) "-MExtUtils::Command" -e mkpath 1994 1995all: lib 1996 1997lib: $(MODPERL_LIB) 1998 1999EOF 2000 2001 print $fh $install; 2002 2003 print $fh <<'EOF' if DMAKE; 2004 2005.USESHELL : 2006EOF 2007 2008 print $fh <<'EOF'; 2009 2010.SUFFIXES: .xs .c $(MODPERL_OBJ_EXT) .lo .i .s 2011 2012.c.lo: 2013 $(MODPERL_CC) $(MODPERL_CCFLAGS_SHLIB) \ 2014 -c $< && $(MODPERL_MV) $*$(MODPERL_OBJ_EXT) $*.lo 2015 2016.c$(MODPERL_OBJ_EXT): 2017 $(MODPERL_CC) $(MODPERL_CCFLAGS) -c $< 2018 2019.c.i: 2020 $(MODPERL_CPPRUN) $(MODPERL_CCFLAGS) -c $< > $*.i 2021 2022.c.s: 2023 $(MODPERL_CC) -O -S $(MODPERL_CCFLAGS) -c $< 2024 2025.xs.c: 2026 $(MODPERL_XSUBPP) $*.xs >$@ 2027 2028.xs$(MODPERL_OBJ_EXT): 2029 $(MODPERL_XSUBPP) $*.xs >$*.c 2030 $(MODPERL_CC) $(MODPERL_CCFLAGS) -c $*.c 2031 2032.xs.lo: 2033 $(MODPERL_XSUBPP) $*.xs >$*.c 2034 $(MODPERL_CC) $(MODPERL_CCFLAGS_SHLIB) \ 2035 -c $*.c && $(MODPERL_MV) $*$(MODPERL_OBJ_EXT) $*.lo 2036 2037clean: 2038 $(MODPERL_RM_F) *.a *.so *.xsc \ 2039 $(MODPERL_LIBNAME).exp $(MODPERL_LIBNAME).lib \ 2040 *$(MODPERL_OBJ_EXT) *.lo *.i *.s *.pdb *.manifest \ 2041 $(MODPERL_CLEAN_FILES) \ 2042 $(MODPERL_XS_CLEAN_FILES) 2043 2044$(MODPERL_OBJS): $(MODPERL_H_FILES) $(MODPERL_MAKEFILE) 2045$(MODPERL_PIC_OBJS): $(MODPERL_H_FILES) $(MODPERL_MAKEFILE) 2046$(MODPERL_LIB): $(MODPERL_LIBPERL) 2047 2048$(MODPERL_LIBNAME)$(MODPERL_LIB_EXT): $(MODPERL_OBJS) 2049 $(MODPERL_RM_F) $@ 2050 $(MODPERL_AR) crv $@ $(MODPERL_OBJS) 2051 $(MODPERL_RANLIB) $@ 2052 2053EOF 2054 2055 print $fh $self->dynamic_link; 2056 2057 print $fh @$xs_targ; 2058 2059 print $fh "\n"; # Makefile must end with \n to avoid warnings 2060 2061 close $fh; 2062} 2063 2064#--- generate MakeMaker parameter values --- 2065 2066sub otherldflags_default { 2067 my $self = shift; 2068 # e.g. aix's V:ldflags feeds -brtl and other flags 2069 $self->perl_config('ldflags'); 2070} 2071 2072sub otherldflags { 2073 my $self = shift; 2074 my $flags = \&{"otherldflags_$^O"}; 2075 return $self->otherldflags_default unless defined &$flags; 2076 $flags->($self); 2077} 2078 2079sub otherldflags_MSWin32 { 2080 my $self = shift; 2081 my $flags = $self->otherldflags_default; 2082 $flags .= ' -pdb:$(INST_ARCHAUTODIR)\$(BASEEXT).pdb' if $self->{MP_DEBUG}; 2083 $flags; 2084} 2085 2086sub typemaps { 2087 my $self = shift; 2088 my @typemaps = (); 2089 2090 # XXX: could move here the code from ModPerl::BuildMM 2091 return [] if IS_MOD_PERL_BUILD; 2092 2093 # for post install use 2094 for (@INC) { 2095 # make sure not to pick mod_perl 1.0 typemap 2096 my $file = "$_/auto/Apache2/typemap"; 2097 push @typemaps, $file if -e $file; 2098 } 2099 2100 return \@typemaps; 2101} 2102 2103sub includes { 2104 my $self = shift; 2105 2106 my @inc = (); 2107 2108 unless (IS_MOD_PERL_BUILD) { 2109 # XXX: what if apxs is not available? win32? 2110 my $ap_inc = $self->apxs('-q' => 'INCLUDEDIR'); 2111 if ($ap_inc && -d $ap_inc) { 2112 push @inc, $ap_inc; 2113 return \@inc; 2114 } 2115 2116 # this is fatal 2117 my $reason = $ap_inc 2118 ? "path $ap_inc doesn't exist" 2119 : "apxs -q INCLUDEDIR didn't return a value"; 2120 die "Can't find the mod_perl include dir (reason: $reason)"; 2121 } 2122 2123 my $os = WIN32 ? 'win32' : 'unix'; 2124 push @inc, $self->file_path("src/modules/perl", "xs"); 2125 2126 push @inc, $self->mp_include_dir; 2127 2128 unless ($self->httpd_is_source_tree) { 2129 push @inc, $self->apr_includedir; 2130 2131 my $apuc = $self->apu_config_path; 2132 if ($apuc && -x $apuc) { 2133 chomp(my $apuincs = qx($apuc --includes)); 2134 # win32: /Ipath, elsewhere -Ipath 2135 $apuincs =~ s{^\s*(-|/)I}{}; 2136 push @inc, $apuincs; 2137 } 2138 2139 my $ainc = $self->apxs('-q' => 'INCLUDEDIR'); 2140 if (-d $ainc) { 2141 push @inc, $ainc; 2142 return \@inc; 2143 } 2144 } 2145 2146 if ($self->{MP_AP_PREFIX}) { 2147 my $src = $self->dir; 2148 for ("$src/modules/perl", "$src/include", 2149 "$src/srclib/apr/include", 2150 "$src/srclib/apr-util/include", 2151 "$src/os/$os") 2152 { 2153 push @inc, $_ if -d $_; 2154 } 2155 } 2156 2157 return \@inc; 2158} 2159 2160sub inc { 2161 local $_; 2162 my @includes = map { "-I$_" } @{ shift->includes }; 2163 "@includes"; 2164} 2165 2166### Picking the right LFS support flags for mod_perl, by Joe Orton ### 2167# 2168# on Unix systems where by default off_t is a "long", a 32-bit integer, 2169# there are two different ways to get "large file" support, i.e. the 2170# ability to manipulate files bigger than 2Gb: 2171# 2172# 1) you compile using -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64. This 2173# makes sys/types.h expose off_t as a "long long", a 64-bit integer, and 2174# changes the size of a few other types too. The C library headers 2175# automatically arrange to expose a correct implementation of functions 2176# like lseek() which take off_t parameters. 2177# 2178# 2) you compile using -D_LARGEFILE64_SOURCE, and use what is called the 2179# "transitional" interface. This means that the system headers expose a 2180# new type, "off64_t", which is a long long, but the size of off_t is not 2181# changed. A bunch of new functions like lseek64() are exposed by the C 2182# library headers, which take off64_t parameters in place of off_t. 2183# 2184# Perl built with -Duselargefiles uses approach (1). 2185# 2186# APR HEAD uses (2) by default. APR 0.9 does not by default use either 2187# approach, but random users can take a httpd-2.0.49 tarball, and do: 2188# 2189# export CPPFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" 2190# ./configure 2191# 2192# to build a copy of apr/httpd which uses approach (1), though this 2193# isn't really a supported configuration. 2194# 2195# The problem that mod_perl has to work around is when you take a 2196# package built with approach (1), i.e. Perl, and any package which was 2197# *not* built with (1), i.e. APR, and want to interface between 2198# them. [1] 2199# 2200# So what you want to know is whether APR was built using approach (1) 2201# or not. APR_HAS_LARGE_FILES in HEAD just tells you whether APR was 2202# built using approach (2) or not, which isn't useful in solving this 2203# problem. 2204# 2205# [1]: In some cases, it may be OK to interface between packages which 2206# use (1) and packages which use (2). APR HEAD is currently not such a 2207# case, since the size of apr_ino_t is still changing when 2208# _FILE_OFFSET_BITS is defined. 2209# 2210# If you want to see how this matters, get some httpd function to do at 2211# the very beginning of main(): 2212# 2213# printf("sizeof(request_rec) = %lu, sizeof(apr_finfo_t) = %ul", 2214# sizeof(request_rec), sizeof(apr_finfo_t)); 2215# 2216# and then put the same printf in mod_perl somewhere, and see the 2217# differences. This is why it is a really terribly silly idea to ever 2218# use approach (1) in anything other than an entirely self-contained 2219# application. 2220# 2221# there is no conflict if both libraries either have or don't have 2222# large files support enabled 2223sub has_large_files_conflict { 2224 my $self = shift; 2225 2226 my $apxs_flags = join $self->apxs_extra_cflags, $self->apxs_extra_cppflags; 2227 my $apr_lfs64 = $apxs_flags =~ /-D_FILE_OFFSET_BITS=64/; 2228 my $perl_lfs64 = $Config{ccflags} =~ /-D_FILE_OFFSET_BITS=64/; 2229 2230 # XXX: we don't really deal with the case where APR was built with 2231 # -D_FILE_OFFSET_BITS=64 but perl wasn't, since currently we strip 2232 # only perl's ccflags, not apr's flags. the reason we don't deal 2233 # with it is that we didn't have such a case yet, but may need to 2234 # deal with it later 2235 2236 return 0; 2237 # $perl_lfs64 ^ $apr_lfs64; 2238} 2239 2240# if perl is built with uselargefiles, but apr not, the build won't 2241# work together as it uses two binary incompatible libraries, so 2242# reduce the functionality to the greatest common denominator (C code 2243# will have to make sure to prevent any operations that may rely on 2244# effects created by uselargefiles, e.g. Off_t=8 instead of Off_t=4) 2245sub strip_lfs { 2246 my ($self, $cflags) = @_; 2247 return $cflags unless $self->has_large_files_conflict(); 2248 2249 my $lf = $Config{ccflags_uselargefiles} 2250 || '-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'; 2251 $cflags =~ s/$lf//; 2252 $cflags; 2253} 2254 2255sub define { 2256 my $self = shift; 2257 2258 return ""; 2259} 2260 22611; 2262 2263__END__ 2264 2265=head1 NAME 2266 2267Apache2::Build - Methods for locating and parsing bits of Apache source code 2268 2269=head1 SYNOPSIS 2270 2271 use Apache2::Build (); 2272 my $build = Apache2::Build->new; 2273 2274 # rebuild mod_perl with build opts from the previous build 2275 % cd modperl-2.0 2276 % perl -MApache2::Build -e rebuild 2277 2278=head1 DESCRIPTION 2279 2280This module provides methods for locating and parsing bits of Apache 2281source code. 2282 2283Since mod_perl remembers what build options were used to build it, you 2284can use this knowledge to rebuild it using the same options. Simply 2285chdir to the mod_perl source directory and run: 2286 2287 % cd modperl-2.0 2288 % perl -MApache2::Build -e rebuild 2289 2290If you want to rebuild not yet installed, but already built mod_perl, 2291run from its root directory: 2292 2293 % perl -Ilib -MApache2::Build -e rebuild 2294 2295=head1 METHODS 2296 2297=over 4 2298 2299=item new 2300 2301Create an object blessed into the B<Apache2::Build> class. 2302 2303 my $build = Apache2::Build->new; 2304 2305=item dir 2306 2307Top level directory where source files are located. 2308 2309 my $dir = $build->dir; 2310 -d $dir or die "can't stat $dir $!\n"; 2311 2312=item find 2313 2314Searches for apache source directories, return a list of those found. 2315 2316Example: 2317 2318 for my $dir ($build->find) { 2319 my $yn = prompt "Configure with $dir ?", "y"; 2320 ... 2321 } 2322 2323=item inc 2324 2325Print include paths for MakeMaker's B<INC> argument to 2326C<WriteMakefile>. 2327 2328Example: 2329 2330 use ExtUtils::MakeMaker; 2331 2332 use Apache2::Build (); 2333 2334 WriteMakefile( 2335 'NAME' => 'Apache2::Module', 2336 'VERSION' => '0.01', 2337 'INC' => Apache2::Build->new->inc, 2338 ); 2339 2340 2341=item module_magic_number 2342 2343Return the B<MODULE_MAGIC_NUMBER> defined in the apache source. 2344 2345Example: 2346 2347 my $mmn = $build->module_magic_number; 2348 2349=item httpd_version 2350 2351Return the server version. 2352 2353Example: 2354 2355 my $v = $build->httpd_version; 2356 2357=item otherldflags 2358 2359Return other ld flags for MakeMaker's B<dynamic_lib> argument to 2360C<WriteMakefile>. This might be needed on systems like AIX that need 2361special flags to the linker to be able to reference mod_perl or httpd 2362symbols. 2363 2364Example: 2365 2366 use ExtUtils::MakeMaker; 2367 2368 use Apache2::Build (); 2369 2370 WriteMakefile( 2371 'NAME' => 'Apache2::Module', 2372 'VERSION' => '0.01', 2373 'INC' => Apache2::Build->new->inc, 2374 'dynamic_lib' => { 2375 'OTHERLDFLAGS' => Apache2::Build->new->otherldflags, 2376 }, 2377 ); 2378 2379=back 2380 2381 2382=head1 AUTHOR 2383 2384Doug MacEachern 2385 2386=cut 2387