X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/3d036c2b4a16bfabb30adc0a1c9a65f0f7823869..be8a15fc9d0d9428f2fb14cc2ecbc0306b52e030:/ext/Time/HiRes/Makefile.PL diff --git a/ext/Time/HiRes/Makefile.PL b/ext/Time/HiRes/Makefile.PL index 51bf35a..cc725b2 100644 --- a/ext/Time/HiRes/Makefile.PL +++ b/ext/Time/HiRes/Makefile.PL @@ -1,3 +1,10 @@ +#!/usr/bin/perl +# +# In general we trust %Config, but for nanosleep() this trust +# may be misplaced (it may be linkable but not really functional). +# Use $ENV{FORCE_NANOSLEEP_SCAN} to force rescanning whether there +# really is hope. + require 5.002; use Config; @@ -7,7 +14,8 @@ use strict; my $VERBOSE = $ENV{VERBOSE}; my $DEFINE; my $LIBS = []; -my $XSOPT; +my $XSOPT = ''; +my $SYSCALL_H; use vars qw($self); # Used in 'sourcing' the hints. @@ -94,6 +102,16 @@ sub try_compile_and_link { $COREincdir = File::Spec->catdir($Config{'archlibexp'}, 'CORE'); } + if ($ENV{PERL_CORE}) { + unless (-f File::Spec->catfile($COREincdir, "EXTERN.h")) { + die <<__EOD__; +Your environment variable PERL_CORE is '$ENV{PERL_CORE}' but there +is no EXTERN.h in $COREincdir. +Cannot continue, aborting. +__EOD__ + } + } + my $ccflags = $Config{'ccflags'} . ' ' . "-I$COREincdir"; if ($^O eq 'VMS') { @@ -134,38 +152,59 @@ sub try_compile_and_link { my $tmp_exe = "$tmp$ld_exeext"; printf "cccmd = $cccmd\n" if $VERBOSE; my $res = system($cccmd); - $ok = defined($res) && $res==0 && -s $tmp_exe && -x _; + $ok = defined($res) && $res == 0 && -s $tmp_exe && -x _; + + if ( $ok && exists $args{run} && $args{run}) { + my $tmp_exe = + File::Spec->catfile(File::Spec->curdir, $tmp_exe); + printf "Running $tmp_exe..." if $VERBOSE; + if (system($tmp_exe) == 0) { + $ok = 1; + } else { + $ok = 0; + my $errno = $? >> 8; + local $! = $errno; + printf < -DHAS_GETTIMEOFDAY already) - return 0 if $Config{d_gettimeod} eq 'define'; - return 1 if try_compile_and_link(< #endif - #ifdef I_SYS_TIME # include #endif - #ifdef I_SYS_SELECT # include /* struct timeval might be hidden in here */ #endif +EOH + +sub has_gettimeofday { + # confusing but true (if condition true ==> -DHAS_GETTIMEOFDAY already) + return 0 if $Config{d_gettimeod}; + return 1 if try_compile_and_link(< #endif -int main _((int argc, char** argv, char** env)) +int main(int argc, char** argv) { $x; } @@ -202,6 +241,32 @@ EOM return 0; } +sub has_nanosleep { + print "testing... "; + return 1 if + try_compile_and_link(< 1); +#include +#include +#include +#include +#include + +/* int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); */ + +int main(int argc, char** argv) { + struct timespec ts1, ts2; + int ret; + ts1.tv_sec = 0; + ts1.tv_nsec = 750000000; + ts2.tv_sec = 0; + ts2.tv_nsec = 0; + errno = 0; + ret = nanosleep(&ts1, &ts2); /* E.g. in AIX nanosleep() fails and sets errno to ENOSYS. */ + ret == 0 ? exit(0) : exit(errno ? errno : -1); +} +EOM +} + sub has_include { my ($inc) = @_; return 1 if @@ -211,7 +276,7 @@ sub has_include { #include "XSUB.h" #include <$inc> -int main _((int argc, char** argv, char** env)) +int main(int argc, char** argv) { return 0; } @@ -219,6 +284,86 @@ EOM return 0; } +sub has_clock_xxx_syscall { + my $x = shift; + return 0 unless defined $SYSCALL_H; + return 1 if + try_compile_and_link(< 1); +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#include <$SYSCALL_H> +int main(int argc, char** argv) +{ + struct timespec ts; + /* Many Linuxes get ENOSYS even though the syscall exists. */ + /* All implementations are supposed to support CLOCK_REALTIME. */ + int ret = syscall(SYS_clock_$x, CLOCK_REALTIME, &ts); + ret == 0 ? exit(0) : exit(errno ? errno : -1); +} +EOM +} + +sub has_clock_xxx { + my $xxx = shift; + return 1 if + try_compile_and_link(< 1); +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +int main(int argc, char** argv) +{ + struct timespec ts; + int ret = clock_$xxx(CLOCK_REALTIME, &ts); /* Many Linuxes get ENOSYS. */ + /* All implementations are supposed to support CLOCK_REALTIME. */ + ret == 0 ? exit(0) : exit(errno ? errno : -1); +} +EOM +} + +sub has_clock { + return 1 if + try_compile_and_link(< 1); +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +int main(int argc, char** argv) +{ + clock_t tictoc; + clock_t ret = clock(); + ret == (clock_t)-1 ? exit(errno ? errno : -1) : exit(0); +} +EOM +} + +sub has_clock_nanosleep { + return 1 if + try_compile_and_link(< 1); +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#include +int main(int argc, char** argv) +{ + int ret; + struct timespec ts1; + struct timespec ts2; + ts1.tv_sec = 0; + ts1.tv_nsec = 750000000;; + ret = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts1, &ts2); + ret == 0 ? exit(0) : exit(errno ? errno : -1); +} +EOM +} + +sub DEFINE { + my ($def, $val) = @_; + my $define = defined $val ? "$def=$val" : $def ; + unless ($DEFINE =~ /(?:^| )-D\Q$define\E(?: |$)/) { + $DEFINE .= " -D$define"; + } +} + sub init { my $hints = File::Spec->catfile("hints", "$^O.pl"); if (-f $hints) { @@ -233,6 +378,25 @@ sub init { $DEFINE = ''; + if ($Config{d_syscall}) { + print "Have syscall()... looking for syscall.h... "; + if (has_include('syscall.h')) { + $SYSCALL_H = 'syscall.h'; + } elsif (has_include('sys/syscall.h')) { + $SYSCALL_H = 'sys/syscall.h'; + } + } else { + print "No syscall()...\n"; + } + + if ($Config{d_syscall}) { + if (defined $SYSCALL_H) { + print "found <$SYSCALL_H>.\n"; + } else { + print "NOT found.\n"; + } + } + print "Looking for gettimeofday()... "; my $has_gettimeofday; if (exists $Config{d_gettimeod}) { @@ -327,7 +491,7 @@ EOD } else { print "NOT found.\n"; print "Let's see if you have select()... "; - if ($Config{'d_select'} eq 'define') { + if ($Config{'d_select'}) { print "found.\n"; print "We can make a Time::HiRes::usleep().\n"; } else { @@ -338,15 +502,27 @@ EOD print "Looking for nanosleep()... "; my $has_nanosleep; - if (exists $Config{d_nanosleep}) { + if ($ENV{FORCE_NANOSLEEP_SCAN}) { + print "forced scan... "; + if (has_nanosleep()) { + $has_nanosleep++; + $DEFINE .= ' -DTIME_HIRES_NANOSLEEP'; + } + } + elsif (exists $Config{d_nanosleep}) { + print "believing \$Config{d_nanosleep}... "; if ($Config{d_nanosleep}) { $has_nanosleep++; $DEFINE .= ' -DTIME_HIRES_NANOSLEEP'; } - } elsif ($^O ne 'mpeix' && # MPE/iX falsely finds nanosleep. - has_x ("nanosleep (NULL, NULL)")) { - $has_nanosleep++; - $DEFINE .= ' -DTIME_HIRES_NANOSLEEP'; + } elsif ($^O =~ /^(mpeix)$/) { + # MPE/iX falsely finds nanosleep from its libc equivalent. + print "skipping because in $^O... "; + } else { + if (has_nanosleep()) { + $has_nanosleep++; + $DEFINE .= ' -DTIME_HIRES_NANOSLEEP'; + } } if ($has_nanosleep) { @@ -360,12 +536,196 @@ EOD print "(It would not be portable anyway.)\n"; } + print "Looking for clock_gettime()... "; + my $has_clock_gettime; + if (exists $Config{d_clock_gettime}) { + $has_clock_gettime++ if $Config{d_clock_gettime}; # Unlikely... + } elsif (has_clock_xxx('gettime')) { + $has_clock_gettime++; + $DEFINE .= ' -DTIME_HIRES_CLOCK_GETTIME'; + } elsif (defined $SYSCALL_H && has_clock_xxx_syscall('gettime')) { + $has_clock_gettime++; + $DEFINE .= ' -DTIME_HIRES_CLOCK_GETTIME -DTIME_HIRES_CLOCK_GETTIME_SYSCALL'; + } + + if ($has_clock_gettime) { + if ($DEFINE =~ /-DTIME_HIRES_CLOCK_GETTIME_SYSCALL/) { + print "found (via syscall).\n"; + } else { + print "found.\n"; + } + } else { + print "NOT found.\n"; + } + + print "Looking for clock_getres()... "; + my $has_clock_getres; + if (exists $Config{d_clock_getres}) { + $has_clock_getres++ if $Config{d_clock_getres}; # Unlikely... + } elsif (has_clock_xxx('getres')) { + $has_clock_getres++; + $DEFINE .= ' -DTIME_HIRES_CLOCK_GETRES'; + } elsif (defined $SYSCALL_H && has_clock_xxx_syscall('getres')) { + $has_clock_getres++; + $DEFINE .= ' -DTIME_HIRES_CLOCK_GETRES -DTIME_HIRES_CLOCK_GETRES_SYSCALL'; + } + + if ($has_clock_getres) { + if ($DEFINE =~ /-DTIME_HIRES_CLOCK_GETRES_SYSCALL/) { + print "found (via syscall).\n"; + } else { + print "found.\n"; + } + } else { + print "NOT found.\n"; + } + + print "Looking for clock_nanosleep()... "; + my $has_clock_nanosleep; + if (exists $Config{d_clock_nanosleep}) { + $has_clock_nanosleep++ if $Config{d_clock_nanosleep}; # Unlikely... + } elsif (has_clock_nanosleep()) { + $has_clock_nanosleep++; + $DEFINE .= ' -DTIME_HIRES_CLOCK_NANOSLEEP'; + } + + if ($has_clock_nanosleep) { + print "found.\n"; + } else { + print "NOT found.\n"; + } + + print "Looking for clock()... "; + my $has_clock; + if (exists $Config{d_clock}) { + $has_clock++ if $Config{d_clock}; # Unlikely... + } elsif (has_clock()) { + $has_clock++; + $DEFINE .= ' -DTIME_HIRES_CLOCK'; + } + + if ($has_clock) { + print "found.\n"; + } else { + print "NOT found.\n"; + } + + print "Looking for stat() subsecond timestamps...\n"; + + print "Trying struct stat st_atimespec.tv_nsec..."; + my $has_stat_st_xtimespec; + if (try_compile_and_link(< +int main(int argc, char** argv) { + struct stat st; + st.st_atimespec.tv_nsec = 0; +} +EOM + $has_stat_st_xtimespec++; + DEFINE('TIME_HIRES_STAT', 1); + } + + if ($has_stat_st_xtimespec) { + print "found.\n"; + } else { + print "NOT found.\n"; + } + + print "Trying struct stat st_atimensec..."; + my $has_stat_st_xtimensec; + if (try_compile_and_link(< +int main(int argc, char** argv) { + struct stat st; + st.st_atimensec = 0; +} +EOM + $has_stat_st_xtimensec++; + DEFINE('TIME_HIRES_STAT', 2); + } + + if ($has_stat_st_xtimensec) { + print "found.\n"; + } else { + print "NOT found.\n"; + } + + print "Trying struct stat st_atime_n..."; + my $has_stat_st_xtime_n; + if (try_compile_and_link(< +int main(int argc, char** argv) { + struct stat st; + st.st_atime_n = 0; +} +EOM + $has_stat_st_xtime_n++; + DEFINE('TIME_HIRES_STAT', 3); + } + + if ($has_stat_st_xtime_n) { + print "found.\n"; + } else { + print "NOT found.\n"; + } + + print "Trying struct stat st_atim.tv_nsec..."; + my $has_stat_st_xtim; + if (try_compile_and_link(< +int main(int argc, char** argv) { + struct stat st; + st.st_atim.tv_nsec = 0; +} +EOM + $has_stat_st_xtim++; + DEFINE('TIME_HIRES_STAT', 4); + } + + if ($has_stat_st_xtim) { + print "found.\n"; + } else { + print "NOT found.\n"; + } + + print "Trying struct stat st_uatime..."; + my $has_stat_st_uxtime; + if (try_compile_and_link(< +int main(int argc, char** argv) { + struct stat st; + st.st_uatime = 0; +} +EOM + $has_stat_st_uxtime++; + DEFINE('TIME_HIRES_STAT', 5); + } + + if ($has_stat_st_uxtime) { + print "found.\n"; + } else { + print "NOT found.\n"; + } + + if ($DEFINE =~ /-DTIME_HIRES_STAT=\d+/) { + print "You seem to have stat() subsecond timestamps.\n"; + print "(Your struct stat has them, but the filesystems must help.)\n"; + } else { + print "You do not seem to have stat subsecond timestamps.\n"; + } + my $has_w32api_windows_h; + if ($^O eq 'cygwin') { print "Looking for ... "; if (has_include('w32api/windows.h')) { $has_w32api_windows_h++; - $DEFINE .= ' -DHAS_W32API_WINDOWS_H'; + DEFINE('HAS_W32API_WINDOWS_H'); } if ($has_w32api_windows_h) { print "found.\n"; @@ -391,7 +751,7 @@ sub doMakefile { 'AUTHOR' => 'Jarkko Hietaniemi ', 'ABSTRACT_FROM' => 'HiRes.pm', ); - $DEFINE .= " -DATLEASTFIVEOHOHFIVE"; + DEFINE('ATLEASTFIVEOHOHFIVE'); } push (@makefileopts, @@ -400,9 +760,10 @@ sub doMakefile { 'LIBS' => $LIBS, # e.g., '-lm' 'DEFINE' => $DEFINE, # e.g., '-DHAS_SOMETHING' 'XSOPT' => $XSOPT, - # do not even think about 'INC' => '-I/usr/ucbinclude', Solaris will avenge. + # Do not even think about 'INC' => '-I/usr/ucbinclude', + # Solaris will avenge. 'INC' => '', # e.g., '-I/usr/include/other' - 'INSTALLDIRS' => 'perl', + 'INSTALLDIRS' => ($] >= 5.008 ? 'perl' : 'site'), 'dist' => { 'CI' => 'ci -l', 'COMPRESS' => 'gzip -9f', @@ -421,15 +782,30 @@ sub doMakefile { sub doConstants { if (eval {require ExtUtils::Constant; 1}) { - my @names = (qw(ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF - ITIMER_REALPROF)); + my @names = qw(CLOCK_HIGHRES CLOCK_MONOTONIC + CLOCK_PROCESS_CPUTIME_ID + CLOCK_REALTIME + CLOCK_SOFTTIME + CLOCK_THREAD_CPUTIME_ID + CLOCK_TIMEOFDAY + CLOCKS_PER_SEC + ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF + ITIMER_REALPROF + TIMER_ABSTIME); foreach (qw (d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer - d_nanosleep)) { + d_nanosleep d_clock_gettime d_clock_getres + d_clock d_clock_nanosleep d_hires_stat)) { my $macro = $_; - if ($macro eq 'd_nanosleep') { - $macro =~ s/d_(.*)/TIME_HIRES_\U$1/; + if ($macro =~ /^(d_nanosleep|d_clock_gettime|d_clock_getres|d_clock|d_clock_nanosleep)$/) { + $macro =~ s/^d_(.+)/TIME_HIRES_\U$1/; + } elsif ($macro =~ /^(d_hires_stat)$/) { + my $d_hires_stat = 0; + $d_hires_stat = $1 if ($DEFINE =~ /-DTIME_HIRES_STAT=(\d+)/); + push @names, {name => $_, macro => "TIME_HIRES_STAT", value => $d_hires_stat, + default => ["IV", "0"]}; + next; } else { - $macro =~ s/d_(.*)/HAS_\U$1/; + $macro =~ s/^d_(.+)/HAS_\U$1/; } push @names, {name => $_, macro => $macro, value => 1, default => ["IV", "0"]}; @@ -459,8 +835,9 @@ sub main { } if ($^O =~ /Win32/i) { - $DEFINE = '-DSELECT_IS_BROKEN'; + DEFINE('SELECT_IS_BROKEN'); $LIBS = []; + print "System is $^O, skipping full configure...\n"; } else { init(); } @@ -475,10 +852,11 @@ EOM (exists $ENV{LC_CTYPE} && $ENV{LC_CTYPE} =~ /utf-?8/i) || (exists $ENV{LANG} && $ENV{LANG} =~ /utf-?8/i)) { print <