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