Some headway to testing float types in Simple.t
[perl-ctypes:perl-ctypes.git] / Makefile.PL
1 # Usage:
2 # perl Makefile.PL INCDIR=/usr/src/libffi-3.0.10/include LIBDIR=/usr/src/libffi-3.0.10/lib
3
4 #use 5.010000;
5 use Carp;
6 use ExtUtils::MakeMaker;
7 use Config;
8 use File::Copy;
9 use File::Spec;
10 use feature 'say';
11 use subs qw|create_ctypes_limits_h get_fp_define_values|; 
12 our $libffi_version = "3.0.10rc3";
13
14 # check the installed version of libffi and override default libdir and incdir
15 use lib qw(inc);
16 use Devel::CheckLib;
17 my ($libdir, $incdir);
18 my $args = join(" ", @ARGV);
19 if ($args =~ /INCDIR[ =](\S+)/) {
20   $incdir = $1;
21 }
22 if ($args =~ /LIBDIR[ =](\S+)/) {
23   $libdir = $1;
24 }
25 if ($libdir or $incdir) {
26   eval qq/assert_lib( lib => 'ffi', header => 'ffi.h', libpath => $libdir, incpath => $incdir )/;
27 } else {
28   eval q/assert_lib( lib => 'ffi', header => 'ffi.h' )/;
29 }
30 if ($@) {
31   use File::Spec;
32   if ($^O !~ /MSWin32|msys/) {
33     warn "libffi not installed or failing. Use our own libffi $libffi_version\n";
34     use Cwd;
35     my $tar = $Config{tar} ? $Config{tar} : "tar";
36     system ($tar, "xfz", "libffi.tar.gz");
37     chdir "libffi";
38     my $cwd = getcwd;
39     system ($ENV{SHELL},"./configure --prefix=/");
40     system ("make");
41     system ("make install DESTDIR='$cwd'"); # abspath. install into libffi/lib, bin and include
42     $incdir = "$cwd/include";
43     $libdir = "$cwd/lib";
44     if ($^O eq 'cygwin') { # copy the bin/*.dll
45       mkdir "bin";
46       File::Copy::cp('lib/cygffi-*.dll', 'bin/');
47     }
48     chdir "..";
49   } else { # MSWin32
50     warn "Using the builtin win32 binaries $libffi_version\n";
51     # built with mingw32
52     # install via http://sourceforge.net/projects/mingw/files/Automated%20MinGW%20Installer/mingw-get-inst/
53     my $cwd = getcwd;
54     $libdir = "win32";
55     $incdir = File::Spec->catfile($cwd, $libdir,"include");
56     # be sure to install the dll on site, because we link only to the import lib
57     mkdir "bin";
58     File::Copy::cp(File::Spec->catfile($libdir, "libffi-5.dll"), "bin");
59   }
60 } else {
61   warn "Using system libffi.\n";
62   warn "  If too old (failing _call tests) install our libffi.tar.gz and use INCDIR and LIBDIR.\n";
63   warn "  tar xfz libffi.tar.gz; cd libffi; . configure --prefix=/; make && make install DESTDIR=`pwd`; cd ..\n";
64   warn "  perl Makefile.PL INCDIR=libffi/include LIBDIR=libffi/lib\n";
65 }
66
67 WriteMakefile(
68     NAME              => 'Ctypes',
69     VERSION_FROM      => 'lib/Ctypes.pm',
70     ABSTRACT_FROM     => 'lib/Ctypes.pm',
71     AUTHOR            => 'Ryan Jendoubi <ryan d\x{00f6}t jendoubi at gmail d\x{00f6}t com, Reini Urban',
72     PREREQ_PM         => {},
73     BUILD_REQUIRES    => {"Regexp::Common" => 0},
74     LIBS              => $libdir ? [ "-L$libdir -lffi" ] : [ "-lffi" ],
75     INC               => $incdir ? "-I. -I$incdir" : "-I.",
76     realclean         => {FILES => "Ctypes_float_minima.h"},
77 );
78
79 sub get_fp_define_values {
80   my $self = shift;
81   my $filename = "Ctypes_float_minima_test";
82   my @needed = qw|FLT_MIN DBL_MIN LDBL_MIN|;
83   map { $_ = 'CTYPES_' . $_ } @needed;
84   my @candidate;
85   my $vals;
86   my $cleanup = sub {
87         unlink ("$filename.c", "$filename$self->{EXE_EXT}",
88                 "$filename$self->{OBJ_EXT}");
89   };
90   &$cleanup;
91   unless (open PROG, ">$filename.c") {
92         print ("Can't write $filename.c\n");
93         return undef;
94   }
95   print PROG <<'PROG';
96 #include <stdio.h>
97 #include <limits.h>
98 #include <float.h>
99 int main()
100 {
101     float f_max = FLT_MAX;
102     float f_try = -FLT_MAX + 1;
103     float f_last_try = 0;
104     float f_delta = FLT_EPSILON;
105     float f_min = 0;
106     do {
107       f_last_try = f_min = f_try;
108       f_try = f_try - f_delta;
109       if( f_try == f_last_try )
110         break;
111     } while ( f_try < f_max && f_try < 0 );
112     double d_max = DBL_MAX;
113     double d_try = -DBL_MAX + 1;
114     double d_last_try = 0;
115     double d_delta = DBL_EPSILON;
116     double d_min = 0;
117     do {
118       d_last_try = d_min = d_try;
119       d_try = d_try - d_delta;
120       if( d_try == d_last_try )
121         break;
122     } while ( d_try < d_max && d_try < 0 );
123     long double ld_max = LDBL_MAX;
124     long double ld_try = -LDBL_MAX + 1;
125     long double ld_last_try = 0;
126     long double ld_delta = LDBL_EPSILON;
127     long double ld_min = 0;
128     do {
129       ld_last_try = ld_min = ld_try;
130       ld_try = ld_try - ld_delta;
131       if( ld_try == ld_last_try )
132         break;
133     } while ( ld_try < ld_max && ld_try < 0 );
134     printf("%f\n", f_min);
135     printf("%f\n", d_min);
136     printf("%Lf\n", ld_min);
137     return 0;
138 }
139 PROG
140   close PROG;
141   my $ccflags = $Config{ccflags};
142   @candidate = ();
143   $devnull = $^O eq 'MSWin32' ? "> NUL" : ">/dev/null 2>&1";
144   push @candidate, "$Config{cc} $Config{ccflags} -DNARF $filename.c -o $filename$self->{EXE_EXT} $devnull"
145         unless $Verbose;
146   push @candidate, "$Config{cc} $Config{ccflags} -DNARF $filename.c -o$filename$self->{EXE_EXT} $devnull"
147         unless $Verbose;
148   push @candidate, "$Config{cc} $Config{ccflags} -DNARF $filename.c -o $filename$self->{EXE_EXT}";
149   push @candidate, "$Config{cc} $Config{ccflags} -DNARF $filename.c -o$filename$self->{EXE_EXT}";
150   while ($self->{how_to_compile} = shift (@candidate)) {
151         unlink "$filename$self->{EXE_EXT}";
152         system ($self->{how_to_compile});
153         last if $? == 0 && -x "$filename$self->{EXE_EXT}";
154   }
155   &$cleanup && return undef unless $self->{how_to_compile};
156   @candidate = ();
157   push @candidate, "./$filename$self->{EXE_EXT} $devnull"
158         unless $Verbose;
159   push @candidate, "$filename$self->{EXE_EXT} $devnull"
160         unless $Verbose;
161   push @candidate, "$filename$self->{EXE_EXT}";
162   push @candidate, "./$filename$self->{EXE_EXT}";
163   push @candidate, "run $filename$self->{EXE_EXT}";
164   while ($self->{how_to_run} = shift (@candidate)) {
165     my @output = qx/$self->{how_to_run}/;
166     if( $? == 0 && @output ) {
167       $self->{Ctypes_limits}->{$_} = shift @output
168         for @needed;
169       &$cleanup;
170       return $self->{Ctypes_limits};
171     }
172   }
173   &$cleanup;
174   return undef;
175 }
176
177 sub create_ctypes_limits_h {
178   my $self = shift;
179   croak "Couldn't get limits!"
180     unless my $vals = get_fp_define_values;
181   croak "Can't write Ctypes_float_minima.h"
182    unless (open HEADER, ">Ctypes_float_minima.h");
183   print HEADER <<"HEADER";
184 /*###########################################################################
185 ## Name:        Ctypes_float_minima.h
186 ## Purpose:     Generated by Ctypes.pm Makefile.PL to define minimum
187 ##              (-ve) value alternatives to FLT_MIN, DBL_MIN etc
188 ## Author:      Ryan Jendoubi
189 ## Based on:    C::DynaLib's Makefile.PL
190 ## Created:     2012-06-28
191 ## Copyright:   (c) 2012 Ryan Jendoubi
192 ## Licence:     This program is free software; you can redistribute it and/or
193 ##              modify it under the Artistic License 2.0. For details see
194 ##              http://www.opensource.org/licenses/artistic-license-2.0.php
195 ###########################################################################*/
196 #ifndef _INC_CTYPES_FLOAT_MINIMA_H
197 #define _INC_CTYPES_FLOAT_MINIMA_H
198
199 #define CTYPES_FLT_MIN $vals->{CTYPES_FLT_MIN}
200 #define CTYPES_DBL_MIN $vals->{CTYPES_DBL_MIN}
201 #define CTYPES_LDBL_MIN $vals->{CTYPES_LDBL_MIN}
202
203 #endif
204 HEADER
205   close HEADER;   
206 }
207
208 if  (eval {require ExtUtils::Constant; 1}) {
209   # If you edit these definitions to change the constants used by this module,
210   # you will need to use the generated const-c.inc and const-xs.inc
211   # files to replace their "fallback" counterparts before distributing your
212   # changes.
213   my @names = (qw|FFI_LONG_LONG_MAX FFI_SIZEOF_ARG FFI_SIZEOF_JAVA_RAW
214                  FFI_TYPE_DOUBLE FFI_TYPE_FLOAT FFI_TYPE_INT FFI_TYPE_LAST
215                  FFI_TYPE_LONGDOUBLE FFI_TYPE_POINTER FFI_TYPE_SINT16
216                  FFI_TYPE_SINT32 FFI_TYPE_SINT64 FFI_TYPE_SINT8 FFI_TYPE_STRUCT
217                  FFI_TYPE_UINT16 FFI_TYPE_UINT32 FFI_TYPE_UINT64 FFI_TYPE_UINT8
218                  FFI_TYPE_VOID PERL_SHORT_MIN PERL_SHORT_MAX PERL_USHORT_MIN
219                  PERL_USHORT_MAX PERL_INT_MIN PERL_INT_MAX PERL_UINT_MIN
220                  PERL_UINT_MAX PERL_LONG_MIN PERL_LONG_MAX PERL_ULONG_MIN
221                  PERL_ULONG_MAX PERL_UCHAR_MIN PERL_UCHAR_MAX CHAR_MIN CHAR_MAX
222                  FLT_MAX CTYPES_FLT_MIN FLT_EPSILON
223                  DBL_MAX CTYPES_DBL_MIN DBL_EPSILON
224                  LDBL_MAX CTYPES_LDBL_MIN LDBL_EPSILON|,
225               {name=>"FFI_BAD_ABI", macro=>"1"},
226               {name=>"FFI_BAD_TYPEDEF", macro=>"1"},
227               {name=>"FFI_OK", macro=>"1"});
228   ExtUtils::Constant::WriteConstants(
229                                      NAME         => 'Ctypes',
230                                      NAMES        => \@names,
231                                      C_FILE       => 'const-c.inc',
232                                      XS_FILE      => 'const-xs.inc',
233                                      DEFAULT_TYPE => 'NV',
234                                   );
235
236 }
237 else {
238   foreach my $file ('const-c.inc', 'const-xs.inc') {
239     my $fallback = File::Spec->catfile('win32', $file);
240     File::Copy::cp ($fallback, $file) or die "Can't copy $fallback to $file: $!";
241   }
242 }
243
244 sub MY::depend {
245   my $self = shift;
246   create_ctypes_limits_h;
247     "
248 const-xs.inc: $0 \$(CONFIGDEP)
249
250 const-c.inc: $0 \$(CONFIGDEP)
251
252 Ctypes.c: \$(XSUBPPDEPS) const-xs.inc \$(XS_FILES) util.c obj_util.c
253
254 README : lib/Ctypes.pm
255         pod2text lib/Ctypes.pm > README
256
257 gcov : Ctypes.c.gcov Ctypes.xs.gcov cover_db/Ctypes-xs.html
258
259 Ctypes.c.gcov Ctypes.xs.gcov : Ctypes.xs
260         \$(MAKE) CCFLAGS=\"\$(CCFLAGS) -fprofile-arcs -ftest-coverage\" LDDLFLAGS=\"\$(LDDLFLAGS) -fprofile-arcs -ftest-coverage\"
261         gcov Ctypes.c Ctypes.xs
262
263 cover_db/Ctypes-xs.html : Ctypes.xs.gcov
264         -PERL5OPT=-MDevel::Cover make test
265         -$^X -S gcov2perl Ctypes.c.gcov Ctypes.xs.gcov
266         $^X -S cover
267
268 gprof :
269         \$(MAKE) CCFLAGS=\"\$(CCFLAGS) -pg\" LDDLFLAGS=\"\$(LDDLFLAGS) -pg\"
270 ";
271 }