1#!/usr/bin/perl 2# 3# In general we trust %Config, but for nanosleep() this trust 4# may be misplaced (it may be linkable but not really functional). 5# Use $ENV{FORCE_NANOSLEEP_SCAN} to force rescanning whether there 6# really is hope. 7 8{ use 5.006; } 9 10use Config; 11use ExtUtils::MakeMaker; 12use strict; 13 14use File::Spec; 15 16my $VERBOSE = $ENV{VERBOSE}; 17my $DEFINE; 18my $LIBS = []; 19my $XSOPT = ''; 20my $SYSCALL_H; 21 22our $self; # Used in 'sourcing' the hints. 23 24# TBD: Can we just use $Config(exe_ext) here instead of this complex 25# expression? 26my $ld_exeext = ($^O eq 'cygwin' || 27 $^O eq 'os2' && $Config{ldflags} =~ /-Zexe\b/) ? '.exe' : 28 (($^O eq 'vos') ? $Config{exe_ext} : ''); 29 30unless($ENV{PERL_CORE}) { 31 $ENV{PERL_CORE} = 1 if grep { $_ eq 'PERL_CORE=1' } @ARGV; 32} 33 34sub try_compile_and_link { 35 my ($c, %args) = @_; 36 37 my ($ok) = 0; 38 my ($tmp) = "tmp$$"; 39 local(*TMPC); 40 41 my $obj_ext = $Config{obj_ext} || ".o"; 42 unlink("$tmp.c", "$tmp$obj_ext"); 43 44 if (open(TMPC, '>', "$tmp.c")) { 45 print TMPC $c; 46 close(TMPC); 47 48 my $cccmd = $args{cccmd}; 49 50 my $errornull; 51 52 my $COREincdir; 53 54 if ($ENV{PERL_CORE}) { 55 my $updir = File::Spec->updir; 56 $COREincdir = File::Spec->catdir(($updir) x 2); 57 } else { 58 $COREincdir = File::Spec->catdir($Config{'archlibexp'}, 'CORE'); 59 } 60 61 if ($ENV{PERL_CORE}) { 62 unless (-f File::Spec->catfile($COREincdir, "EXTERN.h")) { 63 die <<__EOD__; 64Your environment variable PERL_CORE is '$ENV{PERL_CORE}' but there 65is no EXTERN.h in $COREincdir. 66Cannot continue, aborting. 67__EOD__ 68 } 69 } 70 71 my $ccflags = $Config{'ccflags'} . ' '; 72 my @osvers = split /\./, $Config{osvers}; 73 if ($^O eq "darwin" 74 && $^X eq "/usr/bin/perl" 75 && $osvers[0] >= 18) { 76 $ccflags .= qq(-iwithsysroot "$COREincdir"); 77 } 78 else { 79 $ccflags .= "-I$COREincdir" 80 } 81 $ccflags .= ' -DPERL_NO_INLINE_FUNCTIONS'; 82 83 if ($^O eq 'VMS') { 84 $cccmd = "$Config{'cc'} $Config{'ccflags'} /include=($COREincdir) $tmp.c"; 85 } 86 87 if ($args{silent} || !$VERBOSE) { 88 $errornull = "2>/dev/null" unless defined $errornull; 89 } else { 90 $errornull = ''; 91 } 92 93 $cccmd = "$Config{'cc'} -o $tmp $ccflags $tmp.c @$LIBS $errornull" 94 unless defined $cccmd; 95 96 if ($^O eq 'VMS') { 97 open( CMDFILE, '>', "$tmp.com" ); 98 print CMDFILE "\$ SET MESSAGE/NOFACILITY/NOSEVERITY/NOIDENT/NOTEXT\n"; 99 print CMDFILE "\$ $cccmd\n"; 100 print CMDFILE "\$ IF \$SEVERITY .NE. 1 THEN EXIT 44\n"; # escalate 101 close CMDFILE; 102 system("\@ $tmp.com"); 103 $ok = $?==0; 104 for ("$tmp.c", "$tmp$obj_ext", "$tmp.com", "$tmp$Config{exe_ext}") { 105 1 while unlink $_; 106 } 107 } 108 else 109 { 110 my $tmp_exe = "$tmp$ld_exeext"; 111 printf "cccmd = $cccmd\n" if $VERBOSE; 112 my $res = system($cccmd); 113 $ok = defined($res) && $res == 0 && -s $tmp_exe && -x _; 114 115 if ( $ok && exists $args{run} && $args{run} && !$ENV{TIME_HIRES_DONT_RUN_PROBES} ) { 116 my $tmp_exe = 117 File::Spec->catfile(File::Spec->curdir, $tmp_exe); 118 my @run = $tmp_exe; 119 unshift @run, $Config{run} if $Config{run} && -e $Config{run}; 120 printf "Running $tmp_exe..." if $VERBOSE; 121 if (system(@run) == 0) { 122 $ok = 1; 123 } else { 124 $ok = 0; 125 my $errno = $? >> 8; 126 local $! = $errno; 127 printf <<EOF; 128 129*** The test run of '$tmp_exe' failed: status $? 130*** (the status means: errno = $errno or '$!') 131*** DO NOT PANIC: this just means that *some* functionality will be missing. 132EOF 133 } 134 } 135 unlink("$tmp.c", $tmp_exe); 136 } 137 } 138 139 return $ok; 140} 141 142my $TIME_HEADERS = <<EOH; 143#include "EXTERN.h" 144#include "perl.h" 145#include "XSUB.h" 146#ifdef I_SYS_TYPES 147# include <sys/types.h> 148#endif 149#ifdef I_SYS_TIME 150# include <sys/time.h> 151#endif 152#ifdef I_SYS_SELECT 153# include <sys/select.h> /* struct timeval might be hidden in here */ 154#endif 155EOH 156 157sub has_gettimeofday { 158 # confusing but true (if condition true ==> -DHAS_GETTIMEOFDAY already) 159 return 0 if $Config{d_gettimeod}; 160 return 1 if try_compile_and_link(<<EOM); 161$TIME_HEADERS 162static int foo() 163{ 164 struct timeval tv; 165 gettimeofday(&tv, 0); 166} 167int main(int argc, char** argv) 168{ 169 foo(); 170} 171EOM 172 return 0; 173} 174 175sub has_x { 176 my ($x, %args) = @_; 177 178 return 1 if 179 try_compile_and_link(<<EOM, %args); 180#include "EXTERN.h" 181#include "perl.h" 182#include "XSUB.h" 183 184#ifdef I_UNISTD 185# include <unistd.h> 186#endif 187 188#ifdef I_SYS_TYPES 189# include <sys/types.h> 190#endif 191 192#ifdef I_SYS_TIME 193# include <sys/time.h> 194#endif 195 196int main(int argc, char** argv) 197{ 198 $x; 199} 200EOM 201 return 0; 202} 203 204sub has_nanosleep { 205 print "testing... "; 206 return 1 if 207 try_compile_and_link(<<EOM, run => 1); 208#include <time.h> 209#include <sys/time.h> 210#include <stdio.h> 211#include <stdlib.h> 212#include <errno.h> 213 214/* int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); */ 215 216int main(int argc, char** argv) { 217 struct timespec ts1, ts2; 218 int ret; 219 ts1.tv_sec = 0; 220 ts1.tv_nsec = 750000000; 221 ts2.tv_sec = 0; 222 ts2.tv_nsec = 0; 223 errno = 0; 224 ret = nanosleep(&ts1, &ts2); /* E.g. in AIX nanosleep() fails and sets errno to ENOSYS. */ 225 ret == 0 ? exit(0) : exit(errno ? errno : -1); 226} 227EOM 228} 229 230sub has_include { 231 my ($inc) = @_; 232 return 1 if 233 try_compile_and_link(<<EOM); 234#include "EXTERN.h" 235#include "perl.h" 236#include "XSUB.h" 237 238#include <$inc> 239int main(int argc, char** argv) 240{ 241 return 0; 242} 243EOM 244 return 0; 245} 246 247sub has_clock_xxx_syscall { 248 my $x = shift; 249 return 0 unless defined $SYSCALL_H; 250 return 1 if 251 try_compile_and_link(<<EOM, run => 1); 252#include "EXTERN.h" 253#include "perl.h" 254#include "XSUB.h" 255#include <time.h> 256#include <$SYSCALL_H> 257int main(int argc, char** argv) 258{ 259 struct timespec ts; 260 /* Many Linuxes get ENOSYS even though the syscall exists. */ 261 /* All implementations are supposed to support CLOCK_REALTIME. */ 262 int ret = syscall(SYS_clock_$x, CLOCK_REALTIME, &ts); 263 ret == 0 ? exit(0) : exit(errno ? errno : -1); 264} 265EOM 266} 267 268sub has_clock_xxx { 269 my $xxx = shift; 270 return 1 if 271 try_compile_and_link(<<EOM, run => 1); 272#include "EXTERN.h" 273#include "perl.h" 274#include "XSUB.h" 275#include <time.h> 276int main(int argc, char** argv) 277{ 278 struct timespec ts; 279 int ret = clock_$xxx(CLOCK_REALTIME, &ts); /* Many Linuxes get ENOSYS. */ 280 /* All implementations are supposed to support CLOCK_REALTIME. */ 281 ret == 0 ? exit(0) : exit(errno ? errno : -1); 282} 283EOM 284} 285 286sub has_clock { 287 return 1 if 288 try_compile_and_link(<<EOM, run => 1); 289#include "EXTERN.h" 290#include "perl.h" 291#include "XSUB.h" 292#include <time.h> 293int main(int argc, char** argv) 294{ 295 clock_t tictoc; 296 clock_t ret = clock(); 297 ret == (clock_t)-1 ? exit(errno ? errno : -1) : exit(0); 298} 299EOM 300} 301 302sub has_clock_nanosleep { 303 return 1 if 304 try_compile_and_link(<<EOM, run => 1); 305#include "EXTERN.h" 306#include "perl.h" 307#include "XSUB.h" 308#include <time.h> 309int main(int argc, char** argv) 310{ 311 int ret; 312 struct timespec ts1; 313 struct timespec ts2; 314 ts1.tv_sec = 0; 315 ts1.tv_nsec = 750000000;; 316 /* All implementations are supposed to support CLOCK_REALTIME. */ 317 ret = clock_nanosleep(CLOCK_REALTIME, 0, &ts1, &ts2); 318 ret == 0 ? exit(0) : exit(errno ? errno : -1); 319} 320EOM 321} 322 323sub has_futimens { 324 return 1 if 325 try_compile_and_link(<<EOM); 326#include "EXTERN.h" 327#include "perl.h" 328#include "XSUB.h" 329#include <sys/stat.h> 330int main(int argc, char** argv) 331{ 332 int ret1, ret2; 333 struct timespec ts1[2], ts2[2]; 334 ret1 = futimens(0, ts1); 335 char buf[1]; 336 read(0, buf, 0); /* Assuming reading nothing updates atime (the [0]) */ 337 ret2 = futimens(0, ts2); 338 ret1 == 0 && ret2 == 0 && (ts1[0].tv_nsec != 0 || ts2[0].tv_nsec != 0) ? 339 exit(0) : exit(errno ? errno : -1); 340} 341EOM 342} 343 344sub has_utimensat{ 345 return 1 if 346 try_compile_and_link(<<EOM); 347#include "EXTERN.h" 348#include "perl.h" 349#include "XSUB.h" 350#include <sys/stat.h> 351#include <fcntl.h> 352int main(int argc, char** argv) 353{ 354 int ret1, ret2; 355 struct timespec ts1[2], ts2[2]; 356 /* We make the brave but probably foolish assumption that systems 357 * modern enough to have utimensat also have the /dev/stdin. */ 358 ret1 = utimensat(AT_FDCWD, "/dev/stdin", ts1, 0); 359 char buf[1]; 360 read(0, buf, 0); /* Assuming reading nothing updates atime (the [0]) */ 361 ret2 = utimensat(AT_FDCWD, "/dev/stdin", ts2, 0); 362 ret1 == 0 && ret2 == 0 && (ts1[0].tv_nsec != 0 || ts2[0].tv_nsec != 0) ? 363 exit(0) : exit(errno ? errno : -1); 364} 365EOM 366} 367 368sub has_clockid_t{ 369 return 1 if 370 try_compile_and_link(<<EOM); 371#include "EXTERN.h" 372#include "perl.h" 373#include "XSUB.h" 374#include <time.h> 375int main(int argc, char** argv) 376{ 377 clockid_t id = CLOCK_REALTIME; 378 exit(id == CLOCK_REALTIME ? 1 : 0); 379} 380EOM 381} 382 383sub DEFINE { 384 my ($def, $val) = @_; 385 my $define = defined $val ? "$def=$val" : $def ; 386 unless ($DEFINE =~ /(?:^| )-D\Q$define\E(?: |$)/) { 387 $DEFINE .= " -D$define"; 388 } 389} 390 391sub init { 392 my $hints = File::Spec->catfile("hints", "$^O.pl"); 393 if (-f $hints) { 394 print "Using hints $hints...\n"; 395 local $self; 396 do "./$hints"; 397 if (exists $self->{LIBS}) { 398 $LIBS = $self->{LIBS}; 399 print "Extra libraries: @$LIBS...\n"; 400 } 401 } 402 403 $DEFINE = ''; 404 405 if ($Config{d_syscall}) { 406 print "Have syscall()... looking for syscall.h... "; 407 if (has_include('syscall.h')) { 408 $SYSCALL_H = 'syscall.h'; 409 } elsif (has_include('sys/syscall.h')) { 410 $SYSCALL_H = 'sys/syscall.h'; 411 } 412 } else { 413 print "No syscall()...\n"; 414 } 415 416 if ($Config{d_syscall}) { 417 if (defined $SYSCALL_H) { 418 print "found <$SYSCALL_H>.\n"; 419 } else { 420 print "NOT found.\n"; 421 } 422 } 423 424 print "Looking for gettimeofday()... "; 425 my $has_gettimeofday; 426 if (exists $Config{d_gettimeod}) { 427 $has_gettimeofday++ if $Config{d_gettimeod}; 428 } elsif (has_gettimeofday()) { 429 $DEFINE .= ' -DHAS_GETTIMEOFDAY'; 430 $has_gettimeofday++; 431 } 432 433 if ($has_gettimeofday) { 434 print "found.\n"; 435 } else { 436 die <<EOD 437Your operating system does not seem to have the gettimeofday() function. 438(or, at least, I cannot find it) 439 440There is no way Time::HiRes is going to work. 441 442I am awfully sorry but I cannot go further. 443 444Aborting configuration. 445 446EOD 447 } 448 449 print "Looking for setitimer()... "; 450 my $has_setitimer; 451 if (exists $Config{d_setitimer}) { 452 $has_setitimer++ if $Config{d_setitimer}; 453 } elsif (has_x("setitimer(ITIMER_REAL, 0, 0)")) { 454 $has_setitimer++; 455 $DEFINE .= ' -DHAS_SETITIMER'; 456 } 457 458 if ($has_setitimer) { 459 print "found.\n"; 460 } else { 461 print "NOT found.\n"; 462 } 463 464 print "Looking for getitimer()... "; 465 my $has_getitimer; 466 if (exists $Config{'d_getitimer'}) { 467 $has_getitimer++ if $Config{'d_getitimer'}; 468 } elsif (has_x("getitimer(ITIMER_REAL, 0)")) { 469 $has_getitimer++; 470 $DEFINE .= ' -DHAS_GETITIMER'; 471 } 472 473 if ($has_getitimer) { 474 print "found.\n"; 475 } else { 476 print "NOT found.\n"; 477 } 478 479 if ($has_setitimer && $has_getitimer) { 480 print "You have interval timers (both setitimer and getitimer).\n"; 481 } else { 482 print "You do NOT have interval timers.\n"; 483 } 484 485 print "Looking for ualarm()... "; 486 my $has_ualarm; 487 if (exists $Config{d_ualarm}) { 488 $has_ualarm++ if $Config{d_ualarm}; 489 } elsif (has_x ("ualarm (0, 0)")) { 490 $has_ualarm++; 491 $DEFINE .= ' -DHAS_UALARM'; 492 } 493 494 if ($has_ualarm) { 495 print "found.\n"; 496 } else { 497 print "NOT found.\n"; 498 if ($has_setitimer) { 499 print "But you have setitimer().\n"; 500 print "We can make a Time::HiRes::ualarm().\n"; 501 } 502 } 503 504 print "Looking for usleep()... "; 505 my $has_usleep; 506 if (exists $Config{d_usleep}) { 507 $has_usleep++ if $Config{d_usleep}; 508 } elsif (has_x ("usleep (0)")) { 509 $has_usleep++; 510 $DEFINE .= ' -DHAS_USLEEP'; 511 } 512 513 if ($has_usleep) { 514 print "found.\n"; 515 } else { 516 print "NOT found.\n"; 517 print "Let's see if you have select()... "; 518 if ($Config{'d_select'}) { 519 print "found.\n"; 520 print "We can make a Time::HiRes::usleep().\n"; 521 } else { 522 print "NOT found.\n"; 523 print "You won't have a Time::HiRes::usleep().\n"; 524 } 525 } 526 527 print "Looking for nanosleep()... "; 528 my $has_nanosleep; 529 if ($ENV{FORCE_NANOSLEEP_SCAN}) { 530 print "forced scan... "; 531 if (has_nanosleep()) { 532 $has_nanosleep++; 533 $DEFINE .= ' -DTIME_HIRES_NANOSLEEP'; 534 } 535 } 536 elsif (exists $Config{d_nanosleep}) { 537 print "believing \$Config{d_nanosleep}... "; 538 if ($Config{d_nanosleep}) { 539 $has_nanosleep++; 540 $DEFINE .= ' -DTIME_HIRES_NANOSLEEP'; 541 } 542 } else { 543 if (has_nanosleep()) { 544 $has_nanosleep++; 545 $DEFINE .= ' -DTIME_HIRES_NANOSLEEP'; 546 } 547 } 548 549 if ($has_nanosleep) { 550 print "found.\n"; 551 print "You can mix subsecond sleeps with signals, if you want to.\n"; 552 print "(It's still not portable, though.)\n"; 553 } else { 554 print "NOT found.\n"; 555 my $nt = ($^O eq 'os2' ? '' : 'not'); 556 print "You can$nt mix subsecond sleeps with signals.\n"; 557 print "(It would not be portable anyway.)\n"; 558 } 559 560 print "Looking for clockid_t... "; 561 my $has_clockid_t; 562 if (has_clockid_t()) { 563 print "found.\n"; 564 $has_clockid_t++; 565 $DEFINE .= ' -DTIME_HIRES_CLOCKID_T'; 566 } else { 567 print "NOT found, will use int.\n"; 568 } 569 570 print "Looking for clock_gettime()... "; 571 my $has_clock_gettime; 572 my $has_clock_gettime_emulation; 573 if (exists $Config{d_clock_gettime}) { 574 if ($Config{d_clock_gettime}) { # possibly set for cross-compilation 575 $has_clock_gettime++; 576 $DEFINE .= ' -DTIME_HIRES_CLOCK_GETTIME'; 577 } 578 } elsif (has_clock_xxx('gettime')) { 579 $has_clock_gettime++; 580 $DEFINE .= ' -DTIME_HIRES_CLOCK_GETTIME'; 581 } elsif (defined $SYSCALL_H && has_clock_xxx_syscall('gettime')) { 582 $has_clock_gettime++; 583 $DEFINE .= ' -DTIME_HIRES_CLOCK_GETTIME -DTIME_HIRES_CLOCK_GETTIME_SYSCALL'; 584 } elsif ($^O eq 'darwin') { 585 $has_clock_gettime_emulation++; 586 $has_clock_gettime++; 587 $DEFINE .= ' -DTIME_HIRES_CLOCK_GETTIME -DTIME_HIRES_CLOCK_GETTIME_EMULATION'; 588 } 589 590 if ($has_clock_gettime) { 591 if ($DEFINE =~ /-DTIME_HIRES_CLOCK_GETTIME_SYSCALL/) { 592 print "found (via syscall).\n"; 593 } elsif ($has_clock_gettime_emulation) { 594 print "found (via emulation).\n"; 595 } else { 596 print "found.\n"; 597 } 598 } else { 599 print "NOT found.\n"; 600 } 601 602 print "Looking for clock_getres()... "; 603 my $has_clock_getres; 604 my $has_clock_getres_emulation; 605 if (exists $Config{d_clock_getres}) { 606 if ($Config{d_clock_getres}) { # possibly set for cross-compilation 607 $has_clock_getres++; 608 $DEFINE .= ' -DTIME_HIRES_CLOCK_GETRES'; 609 } 610 } elsif (has_clock_xxx('getres')) { 611 $has_clock_getres++; 612 $DEFINE .= ' -DTIME_HIRES_CLOCK_GETRES'; 613 } elsif (defined $SYSCALL_H && has_clock_xxx_syscall('getres')) { 614 $has_clock_getres++; 615 $DEFINE .= ' -DTIME_HIRES_CLOCK_GETRES -DTIME_HIRES_CLOCK_GETRES_SYSCALL'; 616 } elsif ($^O eq 'darwin') { 617 $has_clock_getres_emulation++; 618 $has_clock_getres++; 619 $DEFINE .= ' -DTIME_HIRES_CLOCK_GETRES -DTIME_HIRES_CLOCK_GETRES_EMULATION'; 620 } 621 622 if ($has_clock_getres) { 623 if ($DEFINE =~ /-DTIME_HIRES_CLOCK_GETRES_SYSCALL/) { 624 print "found (via syscall).\n"; 625 } elsif ($has_clock_getres_emulation) { 626 print "found (via emulation).\n"; 627 } else { 628 print "found.\n"; 629 } 630 } else { 631 print "NOT found.\n"; 632 } 633 634 print "Looking for clock_nanosleep()... "; 635 my $has_clock_nanosleep; 636 my $has_clock_nanosleep_emulation; 637 if (exists $Config{d_clock_nanosleep}) { 638 if ($Config{d_clock_nanosleep}) { # possibly set for cross-compilation 639 $has_clock_nanosleep++; 640 $DEFINE .= ' -DTIME_HIRES_CLOCK_NANOSLEEP'; 641 } 642 } elsif (has_clock_nanosleep()) { 643 $has_clock_nanosleep++; 644 $DEFINE .= ' -DTIME_HIRES_CLOCK_NANOSLEEP'; 645 } elsif ($^O eq 'darwin') { 646 $has_clock_nanosleep++; 647 $has_clock_nanosleep_emulation++; 648 $DEFINE .= ' -DTIME_HIRES_CLOCK_NANOSLEEP -DTIME_HIRES_CLOCK_NANOSLEEP_EMULATION'; 649 } 650 651 if ($has_clock_nanosleep) { 652 if ($has_clock_nanosleep_emulation) { 653 print "found (via emulation).\n"; 654 } else { 655 print "found.\n"; 656 } 657 } else { 658 print "NOT found.\n"; 659 } 660 661 print "Looking for clock()... "; 662 my $has_clock; 663 if (exists $Config{d_clock}) { 664 if ($Config{d_clock}) { # possibly set for cross-compilation 665 $has_clock++; 666 $DEFINE .= ' -DTIME_HIRES_CLOCK'; 667 } 668 } elsif (has_clock()) { 669 $has_clock++; 670 $DEFINE .= ' -DTIME_HIRES_CLOCK'; 671 } 672 673 if ($has_clock) { 674 print "found.\n"; 675 } else { 676 print "NOT found.\n"; 677 } 678 679 print "Looking for working futimens()... "; 680 my $has_futimens; 681 if (has_futimens()) { 682 $has_futimens++; 683 $DEFINE .= ' -DHAS_FUTIMENS'; 684 } 685 686 if ($has_futimens) { 687 print "found.\n"; 688 } else { 689 print "NOT found.\n"; 690 } 691 692 print "Looking for working utimensat()... "; 693 my $has_utimensat; 694 if (has_utimensat()) { 695 $has_utimensat++; 696 $DEFINE .= ' -DHAS_UTIMENSAT'; 697 } 698 699 if ($has_utimensat) { 700 print "found.\n"; 701 } else { 702 print "NOT found.\n"; 703 } 704 705 my $has_hires_utime = ($has_futimens && $has_utimensat); 706 if ($has_hires_utime) { 707 $DEFINE .= ' -DTIME_HIRES_UTIME'; 708 print "You seem to have subsecond timestamp setting.\n"; 709 } else { 710 print "You do NOT seem to have subsecond timestamp setting.\n"; 711 } 712 713 print "Looking for stat() subsecond timestamps...\n"; 714 715 print "Trying struct stat st_atimespec.tv_nsec..."; 716 my $has_stat_st_xtimespec; 717 if (try_compile_and_link(<<EOM)) { 718$TIME_HEADERS 719#include <sys/stat.h> 720int main(int argc, char** argv) { 721 struct stat st; 722 st.st_atimespec.tv_nsec = 0; 723} 724EOM 725 $has_stat_st_xtimespec++; 726 DEFINE('TIME_HIRES_STAT_ST_XTIMESPEC'); # 1 727 } 728 729 if ($has_stat_st_xtimespec) { 730 print "found.\n"; 731 } else { 732 print "NOT found.\n"; 733 } 734 735 print "Trying struct stat st_atimensec..."; 736 my $has_stat_st_xtimensec; 737 if (try_compile_and_link(<<EOM)) { 738$TIME_HEADERS 739#include <sys/stat.h> 740int main(int argc, char** argv) { 741 struct stat st; 742 st.st_atimensec = 0; 743} 744EOM 745 $has_stat_st_xtimensec++; 746 DEFINE('TIME_HIRES_STAT_ST_XTIMENSEC'); # 2 747 } 748 749 if ($has_stat_st_xtimensec) { 750 print "found.\n"; 751 } else { 752 print "NOT found.\n"; 753 } 754 755 print "Trying struct stat st_atime_n..."; 756 my $has_stat_st_xtime_n; 757 if (try_compile_and_link(<<EOM)) { 758$TIME_HEADERS 759#include <sys/stat.h> 760int main(int argc, char** argv) { 761 struct stat st; 762 st.st_atime_n = 0; 763} 764EOM 765 $has_stat_st_xtime_n++; 766 DEFINE('TIME_HIRES_STAT_ST_XTIME_N'); # 3 767 } 768 769 if ($has_stat_st_xtime_n) { 770 print "found.\n"; 771 } else { 772 print "NOT found.\n"; 773 } 774 775 print "Trying struct stat st_atim.tv_nsec..."; 776 my $has_stat_st_xtim; 777 if (try_compile_and_link(<<EOM)) { 778$TIME_HEADERS 779#include <sys/stat.h> 780int main(int argc, char** argv) { 781 struct stat st; 782 st.st_atim.tv_nsec = 0; 783} 784EOM 785 $has_stat_st_xtim++; 786 DEFINE('TIME_HIRES_STAT_XTIM'); # 4 787 } 788 789 if ($has_stat_st_xtim) { 790 print "found.\n"; 791 } else { 792 print "NOT found.\n"; 793 } 794 795 print "Trying struct stat st_uatime..."; 796 my $has_stat_st_uxtime; 797 if (try_compile_and_link(<<EOM)) { 798$TIME_HEADERS 799#include <sys/stat.h> 800int main(int argc, char** argv) { 801 struct stat st; 802 st.st_uatime = 0; 803} 804EOM 805 $has_stat_st_uxtime++; 806 DEFINE('TIME_HIRES_STAT_ST_UXTIME'); # 5 807 } 808 809 if ($has_stat_st_uxtime) { 810 print "found.\n"; 811 } else { 812 print "NOT found.\n"; 813 } 814 815 # See HiRes.xs hrstatns() 816 if ($has_stat_st_xtimespec) { 817 DEFINE('TIME_HIRES_STAT', 1); 818 } elsif ($has_stat_st_xtimensec) { 819 DEFINE('TIME_HIRES_STAT', 2); 820 } elsif ($has_stat_st_xtime_n) { 821 DEFINE('TIME_HIRES_STAT', 3); 822 } elsif ($has_stat_st_xtim) { 823 DEFINE('TIME_HIRES_STAT', 4); 824 } elsif ($has_stat_st_uxtime) { 825 DEFINE('TIME_HIRES_STAT', 5); 826 } 827 828 my $has_hires_stat = ($DEFINE =~ /-DTIME_HIRES_STAT=(\d+)/) ? $1 : 0; 829 if ($has_hires_stat) { 830 print "You seem to have subsecond timestamp reading.\n"; 831 print "(Your struct stat has them, but the filesystems must help.)\n"; 832 unless ($has_hires_utime) { 833 print "However, you do NOT seem to have subsecond timestamp setting.\n"; 834 } 835 } else { 836 print "You do NOT seem to have subsecond timestamp reading.\n"; 837 } 838 839 my $has_w32api_windows_h; 840 841 if ($^O eq 'cygwin') { 842 print "Looking for <w32api/windows.h>... "; 843 if (has_include('w32api/windows.h')) { 844 $has_w32api_windows_h++; 845 DEFINE('HAS_W32API_WINDOWS_H'); 846 } 847 if ($has_w32api_windows_h) { 848 print "found.\n"; 849 } else { 850 print "NOT found.\n"; 851 } 852 } 853 if ($^O eq "darwin") { 854 # the system perl on darwin doesn't seem to include -DPERL_DARWIN 855 # which breaks setting up emulation 856 DEFINE("PERL_DARWIN"); 857 } 858 859 if ($DEFINE) { 860 $DEFINE =~ s/^\s+//; 861 if (open(XDEFINE, '>', 'xdefine')) { 862 print XDEFINE $DEFINE, "\n"; 863 close(XDEFINE); 864 } 865 } 866} 867 868sub doMakefile { 869 my @makefileopts = (); 870 871 push (@makefileopts, 872 'NAME' => 'Time::HiRes', 873 'AUTHOR' => 'Jarkko Hietaniemi <jhi@iki.fi>', 874 'ABSTRACT_FROM' => 'HiRes.pm', 875 'VERSION_FROM' => 'HiRes.pm', # finds $VERSION 876 'LIBS' => $LIBS, # e.g., '-lm' 877 'DEFINE' => $DEFINE, # e.g., '-DHAS_SOMETHING' 878 'XSOPT' => $XSOPT, 879 # Do not even think about 'INC' => '-I/usr/ucbinclude', 880 # Solaris will avenge. 881 'INC' => '', # e.g., '-I/usr/include/other' 882 'INSTALLDIRS' => ($] >= 5.008 && $] < 5.011 ? 'perl' : 'site'), 883 'PREREQ_PM' => { 884 'Carp' => 0, 885 'Config' => 0, 886 'Exporter' => 0, 887 'ExtUtils::MakeMaker' => 0, 888 'Test::More' => 0.84, 889 'XSLoader' => 0, 890 'strict' => 0, 891 'File::Spec' => 0, 892 }, 893 'dist' => { 894 'CI' => 'ci -l', 895 'COMPRESS' => 'gzip -9f', 896 'SUFFIX' => 'gz', 897 }, 898 clean => { FILES => "xdefine" }, 899 realclean => { FILES=> 'const-c.inc const-xs.inc' }, 900 ); 901 902 if ($^O eq "MSWin32" && !(grep { /\ALD[A-Z]*=/ } @ARGV)) { 903 my $libperl = $Config{libperl} || ""; 904 my $gccversion = $Config{gccversion} || ""; 905 if ($gccversion =~ /\A3\.4\.[0-9]+/ and $libperl =~ /\.lib\z/) { 906 # Avoid broken linkage with ActivePerl, by linking directly 907 # against the Perl DLL rather than the import library. 908 (my $llibperl = "-l$libperl") =~ s/\.lib\z//; 909 my $lddlflags = $Config{lddlflags} || ""; 910 my $ldflags = $Config{ldflags} || ""; 911 s/-L(?:".*?"|\S+)//g foreach $lddlflags, $ldflags; 912 my $libdirs = join ' ', 913 map { s/(?<!\\)((?:\\\\)*")/\\$1/g; qq[-L"$_"] } 914 @Config{qw/bin sitebin/}; 915 push @makefileopts, macro => { 916 LDDLFLAGS => "$lddlflags $libdirs $llibperl", 917 LDFLAGS => "$ldflags $libdirs $llibperl", 918 PERL_ARCHIVE => "", 919 }; 920 } 921 } 922 923 if ($ENV{PERL_CORE}) { 924 push @makefileopts, MAN3PODS => {}; 925 } 926 927 if ($ExtUtils::MakeMaker::VERSION >= 6.48) { 928 push @makefileopts, (MIN_PERL_VERSION => '5.006',); 929 } 930 931 if ($ExtUtils::MakeMaker::VERSION >= 6.31) { 932 push @makefileopts, (LICENSE => 'perl_5'); 933 } 934 935 if ($ExtUtils::MakeMaker::VERSION >= 6.46) { 936 push @makefileopts, ( 937 META_MERGE => { 938 resources => { 939 repository => 'https://github.com/Perl/perl5.git', 940 bugtracker => 'https://github.com/Perl/perl5/issues', 941 homepage => "https://github.com/Perl/perl5", 942 }, 943 }, 944 ) 945 } 946 947 WriteMakefile(@makefileopts); 948} 949 950sub doConstants { 951 if (eval {require ExtUtils::Constant; 1}) { 952 # More or less this same list is in HiRes.pm. Should unify. 953 my @names = qw( 954 CLOCKS_PER_SEC 955 CLOCK_BOOTTIME 956 CLOCK_HIGHRES 957 CLOCK_MONOTONIC 958 CLOCK_MONOTONIC_COARSE 959 CLOCK_MONOTONIC_FAST 960 CLOCK_MONOTONIC_PRECISE 961 CLOCK_MONOTONIC_RAW 962 CLOCK_PROF 963 CLOCK_PROCESS_CPUTIME_ID 964 CLOCK_REALTIME 965 CLOCK_REALTIME_COARSE 966 CLOCK_REALTIME_FAST 967 CLOCK_REALTIME_PRECISE 968 CLOCK_REALTIME_RAW 969 CLOCK_SECOND 970 CLOCK_SOFTTIME 971 CLOCK_THREAD_CPUTIME_ID 972 CLOCK_TIMEOFDAY 973 CLOCK_UPTIME 974 CLOCK_UPTIME_COARSE 975 CLOCK_UPTIME_FAST 976 CLOCK_UPTIME_PRECISE 977 CLOCK_UPTIME_RAW 978 CLOCK_VIRTUAL 979 ITIMER_PROF 980 ITIMER_REAL 981 ITIMER_REALPROF 982 ITIMER_VIRTUAL 983 TIMER_ABSTIME 984 ); 985 foreach (qw (d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer 986 d_nanosleep d_clock_gettime d_clock_getres 987 d_clock d_clock_nanosleep d_hires_stat 988 d_futimens d_utimensat d_hires_utime)) { 989 my $macro = $_; 990 if ($macro =~ /^(d_nanosleep|d_clock)$/) { 991 $macro =~ s/^d_(.+)/TIME_HIRES_\U$1/; 992 } elsif ($macro =~ /^(d_hires_stat)$/) { 993 my $d_hires_stat = $1 if ($DEFINE =~ /-DTIME_HIRES_STAT=(\d+)/); 994 if (defined $d_hires_stat) { 995 push @names, {name => $_, macro => "TIME_HIRES_STAT", value => $d_hires_stat, 996 default => ["IV", "0"]}; 997 next; 998 } 999 } elsif ($macro =~ /^(d_hires_utime)$/) { 1000 my $d_hires_utime = 1001 ($DEFINE =~ /-DHAS_FUTIMENS/ || 1002 $DEFINE =~ /-DHAS_UTIMENSAT/); 1003 push @names, {name => $_, macro => "TIME_HIRES_UTIME", value => $d_hires_utime, 1004 default => ["IV", "0"]}; 1005 next; 1006 } elsif ($macro =~ /^(d_clock_gettime|d_clock_getres|d_clock_nanosleep)$/) { 1007 $macro =~ s/^d_(.+)/TIME_HIRES_\U$1/; 1008 my $val = ($DEFINE =~ /-D$macro\b/) ? 1 : 0; 1009 push @names, {name => $_, macro => $macro, value => $val, 1010 default => ["IV", "0"]}; 1011 next; 1012 } else { 1013 $macro =~ s/^d_(.+)/HAS_\U$1/; 1014 } 1015 push @names, {name => $_, macro => $macro, value => 1, 1016 default => ["IV", "0"]}; 1017 } 1018 ExtUtils::Constant::WriteConstants( 1019 NAME => 'Time::HiRes', 1020 NAMES => \@names, 1021 ); 1022 } else { 1023 my $file; 1024 foreach $file ('const-c.inc', 'const-xs.inc') { 1025 my $fallback = File::Spec->catfile('fallback', $file); 1026 local $/; 1027 open IN, '<', $fallback or die "Can't open $fallback: $!"; 1028 open OUT, '>', $file or die "Can't open $file: $!"; 1029 print OUT <IN> or die $!; 1030 close OUT or die "Can't close $file: $!"; 1031 close IN or die "Can't close $fallback: $!"; 1032 } 1033 } 1034} 1035 1036sub main { 1037 if (-f "xdefine" && !(@ARGV && $ARGV[0] =~ /^--(?:configure|force)$/)) { 1038 print qq[$0: The "xdefine" exists, skipping the configure step.\n]; 1039 print qq[Use "$^X $0 --configure"\n]; 1040 print qq[or: "$^X $0 --force\n]; 1041 print qq[to force the configure step.\n]; 1042 } else { 1043 print "Configuring Time::HiRes...\n"; 1044 1 while unlink("define"); 1045 if ($^O =~ /Win32/i) { 1046 DEFINE('SELECT_IS_BROKEN'); 1047 # we provide our own implementations of those functions on win32 1048 DEFINE('TIME_HIRES_CLOCK_GETTIME'); 1049 DEFINE('TIME_HIRES_CLOCK_GETRES'); 1050 $LIBS = []; 1051 print "System is $^O, skipping full configure...\n"; 1052 open(XDEFINE, '>', 'xdefine') or die "$0: Cannot create xdefine: $!\n"; 1053 close(XDEFINE); 1054 } else { 1055 init(); 1056 } 1057 doMakefile; 1058 doConstants; 1059 } 1060 my $make = $Config{'make'} || "make"; 1061 unless (exists $ENV{PERL_CORE} && $ENV{PERL_CORE}) { 1062 print <<EOM; 1063Now you may issue '$make'. Do not forget also '$make test'. 1064EOM 1065 if ($] == 5.008 && 1066 ((exists $ENV{LC_ALL} && $ENV{LC_ALL} =~ /utf-?8/i) || 1067 (exists $ENV{LC_CTYPE} && $ENV{LC_CTYPE} =~ /utf-?8/i) || 1068 (exists $ENV{LANG} && $ENV{LANG} =~ /utf-?8/i))) { 1069 print <<EOM; 1070 1071NOTE: if you get an error like this (the Makefile line number may vary): 1072Makefile:91: *** missing separator 1073then set the environment variable LC_ALL to "C" and retry 1074from scratch (re-run perl "Makefile.PL"). 1075(And consider upgrading your Perl to, say, at least Perl 5.8.8.) 1076(You got this message because you seem to have 1077 an UTF-8 locale active in your shell environment, this used 1078 to cause broken Makefiles to be created from Makefile.PLs) 1079EOM 1080 } 1081 } 1082} 1083 1084&main; 1085 1086# EOF 1087