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