X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/6a20eacca2c8d50cbe7b8dbb810a041242de9c84..be8a15fc9d0d9428f2fb14cc2ecbc0306b52e030:/ext/Time/HiRes/Makefile.PL diff --git a/ext/Time/HiRes/Makefile.PL b/ext/Time/HiRes/Makefile.PL index 5868239..cc725b2 100644 --- a/ext/Time/HiRes/Makefile.PL +++ b/ext/Time/HiRes/Makefile.PL @@ -1,16 +1,32 @@ - -# See lib/ExtUtils/MakeMaker.pm for details of how to influence -# the contents of the Makefile that is written. +#!/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; use ExtUtils::MakeMaker; - -# Perls 5.002 and 5.003 did not have File::Spec, fake what we need. +use strict; my $VERBOSE = $ENV{VERBOSE}; +my $DEFINE; +my $LIBS = []; +my $XSOPT = ''; +my $SYSCALL_H; + +use vars qw($self); # Used in 'sourcing' the hints. + +my $ld_exeext = ($^O eq 'cygwin' || + $^O eq 'os2' && $Config{ldflags} =~ /-Zexe\b/) ? '.exe' : ''; + +unless($ENV{PERL_CORE}) { + $ENV{PERL_CORE} = 1 if grep { $_ eq 'PERL_CORE=1' } @ARGV; +} + +# Perls 5.002 and 5.003 did not have File::Spec, fake what we need. sub my_dirsep { $^O eq 'VMS' ? '.' : @@ -22,7 +38,14 @@ sub my_dirsep { sub my_catdir { shift; my $catdir = join(my_dirsep, @_); - $^O eq 'VMS' ? "[$dirsep]" : $dirsep; + $^O eq 'VMS' ? "[$catdir]" : $catdir; +} + +sub my_catfile { + shift; + return join(my_dirsep, @_) unless $^O eq 'VMS'; + my $file = pop; + return my_catdir (undef, @_) . $file; } sub my_updir { @@ -33,33 +56,30 @@ sub my_updir { BEGIN { eval { require File::Spec }; if ($@) { - *File::Spec::catdir = \&my_catdir; - *File::Spec::updir = \&my_updir; + *File::Spec::catdir = \&my_catdir; + *File::Spec::updir = \&my_updir; + *File::Spec::catfile = \&my_catfile; } } +# Avoid 'used only once' warnings. +my $nop1 = *File::Spec::catdir; +my $nop2 = *File::Spec::updir; +my $nop3 = *File::Spec::catfile; + # if you have 5.004_03 (and some slightly older versions?), xsubpp # tries to generate line numbers in the C code generated from the .xs. # unfortunately, it is a little buggy around #ifdef'd code. -# my choice is leave it in and have people with old perls complain +# my choice is leave it in and have people with old perls complain # about the "Usage" bug, or leave it out and be unable to compile myself -# without changing it, and then I'd always forget to change it before a +# without changing it, and then I'd always forget to change it before a # release. Sorry, Edward :) -sub TMPDIR { - my $TMPDIR = - (grep(defined $_ && -d $_ && -w _, - ((defined $ENV{'TMPDIR'} ? $ENV{'TMPDIR'} : undef), - qw(/var/tmp /usr/tmp /tmp))))[0] - unless defined $TMPDIR; - $TMPDIR || die "Cannot find writable temporary directory.\n"; -} - sub try_compile_and_link { my ($c, %args) = @_; my ($ok) = 0; - my ($tmp) = (($^O eq 'VMS') ? "sys\$scratch:tmp$$" : TMPDIR . '/' . "tmp$$"); + my ($tmp) = "tmp$$"; local(*TMPC); my $obj_ext = $Config{obj_ext} || ".o"; @@ -69,27 +89,40 @@ sub try_compile_and_link { print TMPC $c; close(TMPC); - $cccmd = $args{cccmd}; + my $cccmd = $args{cccmd}; my $errornull; my $COREincdir; + if ($ENV{PERL_CORE}) { my $updir = File::Spec->updir; $COREincdir = File::Spec->catdir(($updir) x 3); } else { $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') { if ($ENV{PERL_CORE}) { - # Fragile if the extensions change hierachy within + # Fragile if the extensions change hierarchy within # the Perl core but this should do for now. $cccmd = "$Config{'cc'} /include=([---]) $tmp.c"; } else { my $perl_core = $Config{'installarchlib'}; $perl_core =~ s/\]$/.CORE]/; - $cccmd = "$Config{'cc'} /include=(perl_root:[000000],$perl_core) $tmp.c"; + $cccmd = "$Config{'cc'} /include=(perl_root:[000000],$perl_core) $tmp.c"; } } @@ -99,56 +132,79 @@ sub try_compile_and_link { $errornull = ''; } - $cccmd = "$Config{'cc'} -o $tmp $ccflags $tmp.c @$LIBS $errornull" + $cccmd = "$Config{'cc'} -o $tmp $ccflags $tmp.c @$LIBS $errornull" unless defined $cccmd; - if ($^O eq 'VMS') { + + if ($^O eq 'VMS') { open( CMDFILE, ">$tmp.com" ); print CMDFILE "\$ SET MESSAGE/NOFACILITY/NOSEVERITY/NOIDENT/NOTEXT\n"; print CMDFILE "\$ $cccmd\n"; - print CMDFILE "\$ IF \$SEVERITY .NE. 1 THEN EXIT 44\n"; # escalate + print CMDFILE "\$ IF \$SEVERITY .NE. 1 THEN EXIT 44\n"; # escalate close CMDFILE; system("\@ $tmp.com"); $ok = $?==0; - for ("$tmp.c", "$tmp$obj_ext", "$tmp.com", "$tmp$Config{exe_ext}") { - 1 while unlink $_; + for ("$tmp.c", "$tmp$obj_ext", "$tmp.com", "$tmp$Config{exe_ext}") { + 1 while unlink $_; } } else { + my $tmp_exe = "$tmp$ld_exeext"; printf "cccmd = $cccmd\n" if $VERBOSE; - system($cccmd); - $ok = -s $tmp && -x _; - unlink("$tmp.c", $tmp); + my $res = system($cccmd); + $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; } @@ -185,55 +241,173 @@ EOM return 0; } -sub unixinit { - $DEFINE = ''; +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 + try_compile_and_link(< +int main(int argc, char** argv) +{ + return 0; +} +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 +} - $LIBS = []; +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 +} - # this might break the link, try it if it can't find some things you - # honestly think should be in there... - # $LIBS = ['-lucb -lbsd']; +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 +} - # ... but ucb is poison for Solaris, and probably Linux. honest. - $LIBS = [] if $Config{'osname'} eq 'solaris'; - $LIBS = [] if $Config{'osname'} eq 'linux'; - $LIBS = ['-lm'] if $Config{'osname'} =~ /sco/i; - $LIBS = ['-lc'] if $Config{'osname'} =~ /dynixptx/i; +sub DEFINE { + my ($def, $val) = @_; + my $define = defined $val ? "$def=$val" : $def ; + unless ($DEFINE =~ /(?:^| )-D\Q$define\E(?: |$)/) { + $DEFINE .= " -D$define"; + } +} - # For nanosleep - push @$LIBS, '-lrt' unless $Config{'osname'} =~ /irix/; - push @$LIBS, '-lposix4' ; +sub init { + my $hints = File::Spec->catfile("hints", "$^O.pl"); + if (-f $hints) { + print "Using hints $hints...\n"; + local $self; + do $hints; + if (exists $self->{LIBS}) { + $LIBS = $self->{LIBS}; + print "Extra libraries: @$LIBS...\n"; + } + } - my @goodlibs; + $DEFINE = ''; - select(STDOUT); $| = 1; + 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"; + } - print "Checking for libraries...\n"; - my $lib; - for $lib (@$LIBS) { - print "Checking for $lib...\n"; - $LIBS = [ $lib ]; - if ($Config{libs} =~ /\b$lib\b/ || has_x("time(0)")) { - push @goodlibs, $lib; + if ($Config{d_syscall}) { + if (defined $SYSCALL_H) { + print "found <$SYSCALL_H>.\n"; + } else { + print "NOT found.\n"; } } - @$LIBS = @goodlibs; - print @$LIBS ? - "You have extra libraries: @$LIBS.\n" : - "You have no applicable extra libraries.\n"; - print "\n"; - print "Looking for gettimeofday()...\n"; + print "Looking for gettimeofday()... "; my $has_gettimeofday; - if ($Config{'d_gettimeod'}) { - $has_gettimeofday++; + if (exists $Config{d_gettimeod}) { + $has_gettimeofday++ if $Config{d_gettimeod}; } elsif (has_gettimeofday()) { $DEFINE .= ' -DHAS_GETTIMEOFDAY'; $has_gettimeofday++; } if ($has_gettimeofday) { - print "You have gettimeofday().\n\n"; + print "found.\n"; } else { die < +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 "Whoops! No nanosleep()! You cannot mix subsecond sleeps with signals.\n"; + 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('HAS_W32API_WINDOWS_H'); + } + if ($has_w32api_windows_h) { + print "found.\n"; + } else { + print "NOT found.\n"; + } } if ($DEFINE) { @@ -349,60 +744,121 @@ EOD } sub doMakefile { - @makefileopts = (); + my @makefileopts = (); if ($] >= 5.005) { push (@makefileopts, 'AUTHOR' => 'Jarkko Hietaniemi ', 'ABSTRACT_FROM' => 'HiRes.pm', ); - $DEFINE .= " -DATLEASTFIVEOHOHFIVE"; + DEFINE('ATLEASTFIVEOHOHFIVE'); } push (@makefileopts, 'NAME' => 'Time::HiRes', 'VERSION_FROM' => 'HiRes.pm', # finds $VERSION - 'LIBS' => $LIBS, # e.g., '-lm' - 'DEFINE' => $DEFINE, # e.g., '-DHAS_SOMETHING' + '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. - 'INC' => '', # e.g., '-I/usr/include/other' - 'INSTALLDIRS' => 'perl', + # Do not even think about 'INC' => '-I/usr/ucbinclude', + # Solaris will avenge. + 'INC' => '', # e.g., '-I/usr/include/other' + 'INSTALLDIRS' => ($] >= 5.008 ? 'perl' : 'site'), 'dist' => { 'CI' => 'ci -l', - 'COMPRESS' => 'gzip -9f', + 'COMPRESS' => 'gzip -9f', 'SUFFIX' => 'gz', }, clean => { FILES => "xdefine" }, + realclean => { FILES=> 'const-c.inc const-xs.inc' }, ); + if ($ENV{PERL_CORE}) { + push @makefileopts, MAN3PODS => {}; + } + WriteMakefile(@makefileopts); } -sub main { - print < $_, macro => "TIME_HIRES_STAT", value => $d_hires_stat, + default => ["IV", "0"]}; + next; + } else { + $macro =~ s/^d_(.+)/HAS_\U$1/; + } + push @names, {name => $_, macro => $macro, value => 1, + default => ["IV", "0"]}; + } + ExtUtils::Constant::WriteConstants( + NAME => 'Time::HiRes', + NAMES => \@names, + ); + } else { + my $file; + foreach $file ('const-c.inc', 'const-xs.inc') { + my $fallback = File::Spec->catfile('fallback', $file); + local $/; + open IN, "<$fallback" or die "Can't open $fallback: $!"; + open OUT, ">$file" or die "Can't open $file: $!"; + print OUT or die $!; + close OUT or die "Can't close $file: $!"; + close IN or die "Can't close $fallback: $!"; + } + } +} -EOM +sub main { + print "Configuring Time::HiRes...\n"; + if ($] == 5.007002) { + die "Cannot Configure Time::HiRes for Perl $], aborting.\n"; + } if ($^O =~ /Win32/i) { - $DEFINE = '-DSELECT_IS_BROKEN'; - $LIBS = ['']; + DEFINE('SELECT_IS_BROKEN'); + $LIBS = []; + print "System is $^O, skipping full configure...\n"; } else { - unixinit(); + init(); } - configure; doMakefile; + doConstants; my $make = $Config{'make'} || "make"; - unless ($ENV{PERL_CORE}) { + unless (exists $ENV{PERL_CORE} && $ENV{PERL_CORE}) { print <