1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License, Version 1.0 only
6# (the "License").  You may not use this file except in compliance
7# with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22
23# See lib/ExtUtils/MakeMaker.pm for details of how to influence
24# the contents of the Makefile that is written.
25#
26
27require 5.002;
28
29use Config;
30use ExtUtils::MakeMaker;
31use strict;
32
33my $VERBOSE = $ENV{VERBOSE};
34my $DEFINE;
35my $LIBS = [];
36my $XSOPT;
37
38use vars qw($self); # Used in 'sourcing' the hints.
39
40my $ld_exeext = ($^O eq 'os2' and $Config{ldflags} =~ /-Zexe\b/) ? '.exe' : '';
41
42unless($ENV{PERL_CORE}) {
43    $ENV{PERL_CORE} = 1 if grep { $_ eq 'PERL_CORE=1' } @ARGV;
44}
45
46# Perls 5.002 and 5.003 did not have File::Spec, fake what we need.
47
48sub my_dirsep {
49    $^O eq 'VMS' ? '.' :
50	$^O =~ /mswin32|netware|djgpp/i ? '\\' :
51	    $^O eq 'MacOS' ? ':'
52		: '/';
53}
54
55sub my_catdir {
56    shift;
57    my $catdir = join(my_dirsep, @_);
58    $^O eq 'VMS' ? "[$catdir]" : $catdir;
59}
60
61sub my_catfile {
62    shift;
63    return join(my_dirsep, @_) unless $^O eq 'VMS';
64    my $file = pop;
65    return my_catdir (undef, @_) . $file;
66}
67
68sub my_updir {
69    shift;
70    $^O eq 'VMS' ? "-" : "..";
71}
72
73BEGIN {
74    eval { require File::Spec };
75    if ($@) {
76	*File::Spec::catdir  = \&my_catdir;
77	*File::Spec::updir   = \&my_updir;
78	*File::Spec::catfile = \&my_catfile;
79    }
80}
81
82# Avoid 'used only once' warnings.
83my $nop1 = *File::Spec::catdir;
84my $nop2 = *File::Spec::updir;
85my $nop3 = *File::Spec::catfile;
86
87# if you have 5.004_03 (and some slightly older versions?), xsubpp
88# tries to generate line numbers in the C code generated from the .xs.
89# unfortunately, it is a little buggy around #ifdef'd code.
90# my choice is leave it in and have people with old perls complain
91# about the "Usage" bug, or leave it out and be unable to compile myself
92# without changing it, and then I'd always forget to change it before a
93# release. Sorry, Edward :)
94
95sub try_compile_and_link {
96    my ($c, %args) = @_;
97
98    my ($ok) = 0;
99    my ($tmp) = "tmp$$";
100    local(*TMPC);
101
102    my $obj_ext = $Config{obj_ext} || ".o";
103    unlink("$tmp.c", "$tmp$obj_ext");
104
105    if (open(TMPC, ">$tmp.c")) {
106	print TMPC $c;
107	close(TMPC);
108
109	my $cccmd = $args{cccmd};
110
111	my $errornull;
112
113	my $COREincdir;
114
115	if ($ENV{PERL_CORE}) {
116	    my $updir = File::Spec->updir;
117	    $COREincdir = File::Spec->catdir(($updir) x 3);
118	} else {
119	    $COREincdir = File::Spec->catdir($Config{'archlibexp'}, 'CORE');
120	}
121
122	my $ccflags = $Config{'ccflags'} . ' ' . "-I$COREincdir";
123
124	if ($^O eq 'VMS') {
125	    if ($ENV{PERL_CORE}) {
126		# Fragile if the extensions change hierachy within
127		# the Perl core but this should do for now.
128                $cccmd = "$Config{'cc'} /include=([---]) $tmp.c";
129	    } else {
130		my $perl_core = $Config{'installarchlib'};
131		$perl_core =~ s/\]$/.CORE]/;
132                $cccmd = "$Config{'cc'} /include=(perl_root:[000000],$perl_core) $tmp.c";
133	    }
134        }
135
136        if ($args{silent} || !$VERBOSE) {
137	    $errornull = "2>/dev/null" unless defined $errornull;
138	} else {
139	    $errornull = '';
140	}
141
142        $cccmd = "$Config{'cc'} -o $tmp $ccflags $tmp.c @$LIBS $errornull"
143	    unless defined $cccmd;
144
145       if ($^O eq 'VMS') {
146	    open( CMDFILE, ">$tmp.com" );
147	    print CMDFILE "\$ SET MESSAGE/NOFACILITY/NOSEVERITY/NOIDENT/NOTEXT\n";
148	    print CMDFILE "\$ $cccmd\n";
149	    print CMDFILE "\$ IF \$SEVERITY .NE. 1 THEN EXIT 44\n"; # escalate
150	    close CMDFILE;
151	    system("\@ $tmp.com");
152	    $ok = $?==0;
153	    for ("$tmp.c", "$tmp$obj_ext", "$tmp.com", "$tmp$Config{exe_ext}") {
154		1 while unlink $_;
155	    }
156        }
157        else
158        {
159	    my $tmp_exe = "$tmp$ld_exeext";
160	    printf "cccmd = $cccmd\n" if $VERBOSE;
161	    my $res = system($cccmd);
162	    $ok = defined($res) && $res==0 && -s $tmp_exe && -x _;
163	    unlink("$tmp.c", $tmp_exe);
164        }
165    }
166
167    $ok;
168}
169
170sub has_gettimeofday {
171    # confusing but true (if condition true ==> -DHAS_GETTIMEOFDAY already)
172    return 0 if $Config{d_gettimeod} eq 'define';
173    return 1 if try_compile_and_link(<<EOM);
174#include "EXTERN.h"
175#include "perl.h"
176#include "XSUB.h"
177#ifdef I_SYS_TYPES
178#   include <sys/types.h>
179#endif
180
181#ifdef I_SYS_TIME
182#   include <sys/time.h>
183#endif
184
185#ifdef I_SYS_SELECT
186#   include <sys/select.h>	/* struct timeval might be hidden in here */
187#endif
188static int foo()
189{
190    struct timeval tv;
191    gettimeofday(&tv, 0);
192}
193int main _((int argc, char** argv, char** env))
194{
195    foo();
196}
197EOM
198    return 0;
199}
200
201sub has_x {
202    my ($x, %args) = @_;
203
204    return 1 if
205    try_compile_and_link(<<EOM, %args);
206#include "EXTERN.h"
207#include "perl.h"
208#include "XSUB.h"
209
210#ifdef I_UNISTD
211#   include <unistd.h>
212#endif
213
214#ifdef I_SYS_TYPES
215#   include <sys/types.h>
216#endif
217
218#ifdef I_SYS_TIME
219#   include <sys/time.h>
220#endif
221
222int main _((int argc, char** argv, char** env))
223{
224	$x;
225}
226EOM
227    return 0;
228}
229
230sub init {
231    my $hints = File::Spec->catfile("hints", "$^O.pl");
232    if (-f $hints) {
233	print "Using hints $hints...\n";
234	local $self;
235	do $hints;
236	if (exists $self->{LIBS}) {
237	    $LIBS = $self->{LIBS};
238	    print "Extra libraries: @$LIBS...\n";
239	}
240    }
241
242    $DEFINE = '';
243
244    print "Looking for gettimeofday()... ";
245    my $has_gettimeofday;
246    if (exists $Config{d_gettimeod}) {
247	$has_gettimeofday++ if $Config{d_gettimeod};
248    } elsif (has_gettimeofday()) {
249	$DEFINE .= ' -DHAS_GETTIMEOFDAY';
250	$has_gettimeofday++;
251    }
252
253    if ($has_gettimeofday) {
254	print "found.\n";
255    } else {
256	die <<EOD
257Your operating system does not seem to have the gettimeofday() function.
258(or, at least, I cannot find it)
259
260There is no way Time::HiRes is going to work.
261
262I am awfully sorry but I cannot go further.
263
264Aborting configuration.
265
266EOD
267    }
268
269    print "Looking for setitimer()... ";
270    my $has_setitimer;
271    if (exists $Config{d_setitimer}) {
272        $has_setitimer++ if $Config{d_setitimer};
273    } elsif (has_x("setitimer(ITIMER_REAL, 0, 0)")) {
274        $has_setitimer++;
275        $DEFINE .= ' -DHAS_SETITIMER';
276    }
277
278    if ($has_setitimer) {
279        print "found.\n";
280    } else {
281	print "NOT found.\n";
282    }
283
284    print "Looking for getitimer()... ";
285    my $has_getitimer;
286    if (exists $Config{'d_getitimer'}) {
287        $has_getitimer++ if $Config{'d_getitimer'};
288    } elsif (has_x("getitimer(ITIMER_REAL, 0)")) {
289        $has_getitimer++;
290        $DEFINE .= ' -DHAS_GETITIMER';
291    }
292
293    if ($has_getitimer) {
294        print "found.\n";
295    } else {
296	print "NOT found.\n";
297    }
298
299    if ($has_setitimer && $has_getitimer) {
300	print "You have interval timers (both setitimer and setitimer).\n";
301    } else {
302	print "You do not have interval timers.\n";
303    }
304
305    print "Looking for ualarm()... ";
306    my $has_ualarm;
307    if (exists $Config{d_ualarm}) {
308        $has_ualarm++ if $Config{d_ualarm};
309    } elsif (has_x ("ualarm (0, 0)")) {
310        $has_ualarm++;
311	$DEFINE .= ' -DHAS_UALARM';
312    }
313
314    if ($has_ualarm) {
315        print "found.\n";
316    } else {
317	print "NOT found.\n";
318	if ($has_setitimer) {
319	    print "But you have setitimer().\n";
320	    print "We can make a Time::HiRes::ualarm().\n";
321	}
322    }
323
324    print "Looking for usleep()... ";
325    my $has_usleep;
326    if (exists $Config{d_usleep}) {
327	$has_usleep++ if $Config{d_usleep};
328    } elsif (has_x ("usleep (0)")) {
329	$has_usleep++;
330	$DEFINE .= ' -DHAS_USLEEP';
331    }
332
333    if ($has_usleep) {
334	print "found.\n";
335    } else {
336	print "NOT found.\n";
337        print "Let's see if you have select()... ";
338        if ($Config{'d_select'} eq 'define') {
339	    print "found.\n";
340	    print "We can make a Time::HiRes::usleep().\n";
341	} else {
342	    print "NOT found.\n";
343	    print "You won't have a Time::HiRes::usleep().\n";
344	}
345    }
346
347    print "Looking for nanosleep()... ";
348    my $has_nanosleep;
349    if (exists $Config{d_nanosleep}) {
350	if ($Config{d_nanosleep}) {
351	    $has_nanosleep++;
352	    $DEFINE .= ' -DTIME_HIRES_NANOSLEEP';
353	}
354    } elsif ($^O ne 'mpeix' && # MPE/iX falsely finds nanosleep.
355             has_x ("nanosleep (NULL, NULL)")) {
356	$has_nanosleep++;
357	$DEFINE .= ' -DTIME_HIRES_NANOSLEEP';
358    }
359
360    if ($has_nanosleep) {
361	print "found.\n";
362        print "You can mix subsecond sleeps with signals.\n";
363    } else {
364	print "NOT found.\n";
365	my $nt = ($^O eq 'os2' ? '' : 'not');
366        print "You can$nt mix subsecond sleeps with signals.\n";
367    }
368
369    if ($DEFINE) {
370        $DEFINE =~ s/^\s+//;
371        if (open(XDEFINE, ">xdefine")) {
372	    print XDEFINE $DEFINE, "\n";
373	    close(XDEFINE);
374        }
375    }
376}
377
378sub doMakefile {
379    my @makefileopts = ();
380
381    if ($] >= 5.005) {
382	push (@makefileopts,
383	    'AUTHOR'    => 'Jarkko Hietaniemi <jhi@iki.fi>',
384	    'ABSTRACT_FROM' => 'HiRes.pm',
385	);
386	$DEFINE .= " -DATLEASTFIVEOHOHFIVE";
387    }
388
389    push (@makefileopts,
390	'NAME'	=> 'Time::HiRes',
391	'VERSION_FROM' => 'HiRes.pm', # finds $VERSION
392	'LIBS'	=> $LIBS,   # e.g., '-lm'
393	'DEFINE'	=> $DEFINE,     # e.g., '-DHAS_SOMETHING'
394	'XSOPT'	=> $XSOPT,
395    # do not even think about 'INC' => '-I/usr/ucbinclude', Solaris will avenge.
396	'INC'	=> '',     # e.g., '-I/usr/include/other'
397	'INSTALLDIRS' => 'perl',
398	'dist'      => {
399	    'CI'       => 'ci -l',
400	    'COMPRESS' => 'gzip -9f',
401	    'SUFFIX'   => 'gz',
402	},
403        clean => { FILES => "xdefine" },
404        realclean => { FILES=> 'const-c.inc const-xs.inc' },
405    );
406
407    if ($ENV{PERL_CORE}) {
408	push @makefileopts, MAN3PODS => {};
409    }
410
411    WriteMakefile(@makefileopts);
412}
413
414sub doConstants {
415    if (eval {require ExtUtils::Constant; 1}) {
416	my @names = (qw(ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF
417			ITIMER_REALPROF));
418	foreach (qw (d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
419		     d_nanosleep)) {
420	    my $macro = $_;
421	    if ($macro eq 'd_nanosleep') {
422		$macro =~ s/d_(.*)/TIME_HIRES_\U$1/;
423	    } else {
424		$macro =~ s/d_(.*)/HAS_\U$1/;
425	    }
426	    push @names, {name => $_, macro => $macro, value => 1,
427			  default => ["IV", "0"]};
428	}
429	ExtUtils::Constant::WriteConstants(
430					   NAME => 'Time::HiRes',
431					   NAMES => \@names,
432					  );
433    } else {
434	foreach my $file ('const-c.inc', 'const-xs.inc') {
435	    my $fallback = File::Spec->catfile('fallback', $file);
436	    local $/;
437	    open IN, "<$fallback" or die "Can't open $fallback: $!";
438	    open OUT, ">$file" or die "Can't open $file: $!";
439	    print OUT <IN> or die $!;
440	    close OUT or die "Can't close $file: $!";
441	    close IN or die "Can't close $fallback: $!";
442	}
443    }
444}
445
446sub main {
447    print "Configuring Time::HiRes...\n";
448
449    if ($^O =~ /Win32/i) {
450      $DEFINE = '-DSELECT_IS_BROKEN';
451      $LIBS = [];
452    } else {
453      init();
454    }
455    doMakefile;
456    doConstants;
457    my $make = $Config{'make'} || "make";
458    unless ($ENV{PERL_CORE}) {
459	print  <<EOM;
460Now you may issue '$make'.  Do not forget also '$make test'.
461
462EOM
463       if ($ENV{LC_ALL}   =~ /utf-?8/i ||
464           $ENV{LC_CTYPE} =~ /utf-?8/i ||
465           $ENV{LANG}     =~ /utf-?8/i) {
466            print  <<EOM;
467NOTE: if you get an error like this (the line number may vary):
468Makefile:91: *** missing separator
469then set the environment variable LC_ALL to "C" and retry
470from scratch (re-run perl "Makefile.PL").
471
472EOM
473        }
474    }
475}
476
477&main;
478
479# EOF
480