File Coverage

inc/My/Config.pm
Criterion Covered Total %
statement 68 242 28.1
branch 0 80 0.0
condition 2 36 5.5
subroutine 21 28 75.0
pod 0 11 0.0
total 91 397 22.9


line stmt bran cond sub pod time code
1             package My::Config;
2              
3 2     2   14 use strict;
  2         2  
  2         72  
4 2     2   8 use warnings;
  2         6  
  2         115  
5 2     2   11 use Config;
  2         3  
  2         68  
6 2     2   8 use File::Spec;
  2         2  
  2         49  
7 2     2   1152 use FindBin;
  2         2680  
  2         96  
8 2     2   431 use Text::ParseWords qw( shellwords );
  2         1425  
  2         115  
9 2     2   607 use My::BuildConfig;
  2         5  
  2         64  
10 2     2   631 use My::ShareConfig;
  2         5  
  2         45  
11 2     2   582 use My::ConfigH;
  2         5  
  2         64  
12 2     2   12 use My::ShareConfig;
  2         3  
  2         44  
13 2     2   7 use lib 'lib';
  2         3  
  2         13  
14 2     2   1960 use FFI::Probe;
  2         8  
  2         113  
15 2     2   31 use FFI::Probe::Runner;
  2         4  
  2         56  
16 2     2   1123 use FFI::Probe::Runner::Builder;
  2         4  
  2         80  
17 2     2   15 use File::Glob qw( bsd_glob );
  2         3  
  2         265  
18 2     2   16 use File::Basename qw( basename );
  2         3  
  2         115  
19 2     2   1611 use JSON::PP qw( decode_json );
  2         34151  
  2         6515  
20              
21             my @probe_types = split /\n/, <
22             char
23             signed char
24             unsigned char
25             short
26             signed short
27             unsigned short
28             int
29             signed int
30             unsigned int
31             long
32             signed long
33             unsigned long
34             uint8_t
35             int8_t
36             uint16_t
37             int16_t
38             uint32_t
39             int32_t
40             uint64_t
41             int64_t
42             size_t
43             ssize_t
44             SSIZE_T
45             float
46             double
47             long double
48             float complex
49             double complex
50             long double complex
51             bool
52             _Bool
53             pointer
54             uintptr_t
55             intptr_t
56             enum
57             senum
58             intmax_t
59             uintmax_t
60             EOF
61              
62             my @extra_probe_types = split /\n/, <
63             long long
64             signed long long
65             unsigned long long
66             dev_t
67             ino_t
68             mode_t
69             nlink_t
70             uid_t
71             gid_t
72             off_t
73             blksize_t
74             blkcnt_t
75             time_t
76             ptrdiff_t
77             wchar_t
78             wint_t
79             EOF
80              
81             push @probe_types, @extra_probe_types unless $ENV{FFI_PLATYPUS_NO_EXTRA_TYPES};
82              
83             sub new
84             {
85 2     2 0 6 my($class) = @_;
86 2         7 bless {}, $class;
87             }
88              
89             my $ppport_h = File::Spec->catfile(qw( include ppport.h ));
90              
91             sub generate_dev
92             {
93 0 0 0 0 0 0 if(!-r $ppport_h || -d '.git')
94             {
95 0         0 my $ppport_version = 3.28;
96 0         0 require Devel::PPPort;
97 0 0       0 die "Devel::PPPort $ppport_version or better required for development"
98             unless $Devel::PPPort::VERSION >= $ppport_version;
99              
100 0         0 my $old = '';
101 0 0       0 if(-e $ppport_h)
102             {
103 0         0 open my $fh, '<', $ppport_h;
104 0         0 $old = do { local $/; <$fh> };
  0         0  
  0         0  
105 0         0 close $fh;
106             }
107              
108 0         0 my $content = Devel::PPPort::GetFileContents('include/ppport.h');
109              
110 0 0       0 if($content ne $old)
111             {
112 0         0 print "XX $ppport_h\n";
113 0         0 open my $fh, '>', $ppport_h;
114 0         0 print $fh $content;
115 0         0 close $fh;
116             }
117             }
118             }
119              
120             sub clean
121             {
122 0     0 0 0 unlink $ppport_h;
123             }
124              
125             sub share_config
126             {
127 0     0 0 0 my($self) = @_;
128 0   0     0 $self->{share_config} ||= My::ShareConfig->new;
129             }
130              
131             sub build_config
132             {
133 5     5 0 21 my($self) = @_;
134 5   66     95 $self->{build_config} ||= My::BuildConfig->new;
135             }
136              
137             sub probe
138             {
139 0     0 0 0 my($self) = @_;
140              
141             $self->{probe} ||= FFI::Probe->new(
142             runner => $self->probe_runner,
143             log => "config.log",
144             data_filename => "./blib/lib/auto/share/dist/FFI-Platypus/probe/probe.pl",
145 0   0     0 alien => [$self->build_config->get('alien')->{class}],
146             cflags => ['-Iinclude'],
147             );
148             }
149              
150             sub probe_runner
151             {
152 0     0 0 0 my($self) = @_;
153 0         0 my $builder = FFI::Probe::Runner::Builder->new;
154 0         0 my $exe = $builder->exe;
155 0 0       0 if(-e $exe)
156             {
157 0         0 return FFI::Probe::Runner->new( exe => $exe );
158             }
159             else
160             {
161 0         0 return undef;
162             }
163             }
164              
165             sub probe_runner_build
166             {
167 0     0 0 0 my($self) = @_;
168 0         0 my $probe = $self->probe;
169 0         0 my $builder = FFI::Probe::Runner::Builder->new;
170 0         0 foreach my $key (qw( cc ccflags optimize ld ldflags ))
171 0         0 { @{ $builder->$key } = @{ $self->build_config->get('eumm')->{$key} } }
  0         0  
  0         0  
172 0 0       0 $builder->build unless -e $builder->exe;
173             }
174              
175             sub configure
176             {
177 0     0 0 0 my($self) = @_;
178              
179 0         0 my $probe = $self->probe;
180              
181 0         0 my $config_h = File::Spec->rel2abs( File::Spec->catfile( 'include', 'ffi_platypus_config.h' ) );
182 0 0 0     0 return if -r $config_h && ref($self->share_config->get( 'type_map' )) eq 'HASH';
183              
184 0         0 my $ch = My::ConfigH->new;
185              
186 0         0 $ch->define_var( do {
187 0         0 my $os = uc $^O;
188 0         0 $os =~ s/-/_/;
189 0         0 $os =~ s/[^A-Z0-9_]//g;
190 0         0 "PERL_OS_$os";
191             } => 1 );
192              
193 0 0       0 $ch->define_var( PERL_OS_WINDOWS => 1 ) if $^O =~ /^(MSWin32|cygwin|msys)$/;
194              
195             {
196 0         0 my($major, $minor, $patch) = $] =~ /^(5|[7-9])\.([0-9]{3})([0-9]{3})/;
197 0         0 $ch->define_var( FFI_PL_PERL_VERSION_MAJOR => int $major );
198 0         0 $ch->define_var( FFI_PL_PERL_VERSION_MINOR => int $minor );
199 0         0 $ch->define_var( FFI_PL_PERL_VERSION_PATCH => int $patch );
200             }
201              
202             {
203 0         0 my($major, $minor, $patch) = (@{ $self->build_config->get('version') }, 0);
  0         0  
  0         0  
  0         0  
204 0         0 $ch->define_var( FFI_PL_VERSION_MAJOR => int $major );
205 0         0 $ch->define_var( FFI_PL_VERSION_MINOR => int $minor );
206 0         0 $ch->define_var( FFI_PL_VERSION_PATCH => int $patch );
207             }
208              
209 0         0 foreach my $header (qw( stdlib stdint sys/types sys/stat unistd alloca dlfcn limits stddef wchar signal inttypes windows sys/cygwin string psapi stdio stdbool complex ))
210             {
211 0 0       0 if($probe->check_header("$header.h"))
212             {
213 0         0 my $var = uc $header;
214 0         0 $var =~ s{/}{_}g;
215 0         0 $var = "HAVE_${var}_H";
216 0         0 $ch->define_var( $var => 1 );
217             }
218             }
219              
220 0 0 0     0 if(!$self->build_config->get('config_debug_fake32') && $Config{ivsize} >= 8)
221             {
222 0         0 $ch->define_var( HAVE_IV_IS_64 => 1 );
223             }
224              
225 0         0 my %type_map;
226             my %align;
227              
228 0         0 foreach my $type (@probe_types)
229             {
230 0 0       0 if($type =~ /^(float|double|long double)/)
    0          
    0          
    0          
231             {
232 0 0       0 if(my $basic = $probe->check_type_float($type))
233             {
234 0         0 $type_map{$type} = $basic;
235 0         0 $align{$type} = $probe->data->{type}->{$type}->{align};
236             }
237             }
238             elsif($type eq 'pointer')
239             {
240 0         0 $probe->check_type_pointer;
241 0         0 $align{pointer} = $probe->data->{type}->{pointer}->{align};
242             }
243             elsif($type eq 'enum')
244             {
245 0 0       0 if(my $basic = $probe->check_type_enum)
246             {
247 0         0 $type_map{enum} = $basic;
248 0   0     0 $align{$basic} ||= $probe->data->{type}->{enum}->{align};
249             }
250             }
251             elsif($type eq 'senum')
252             {
253 0 0       0 if(my $basic = $probe->check_type_signed_enum)
254             {
255 0         0 $type_map{senum} = $basic;
256 0   0     0 $align{$basic} ||= $probe->data->{type}->{senum}->{align};
257             }
258             }
259             else
260             {
261 0 0       0 if(my $basic = $probe->check_type_int($type))
    0          
262             {
263 0         0 $type_map{$type} = $basic;
264 0   0     0 $align{$basic} ||= $probe->data->{type}->{$type}->{align};
265             }
266             elsif($type =~ /^(unsigned |signed )?(char|short|int|long)$/)
267             {
268 0         0 print "Unable to perform basic type check for: \"$type\"\n";
269 0         0 print "Please check config.log for detailed diagnostics.\n";
270 0         0 die "unable to configure Platypus";
271             }
272             }
273             }
274              
275             # Visual C++ uses SSIZE_T instead of ssize_t
276 0 0 0     0 if($^O eq 'MSWin32' && $Config{ccname} eq 'cl' && defined $type_map{SSIZE_T})
    0 0        
277             {
278 0         0 $type_map{ssize_t} = delete $type_map{SSIZE_T};
279             }
280             elsif(defined $type_map{SSIZE_T})
281             {
282 0         0 delete $type_map{SSIZE_T};
283             }
284              
285 0         0 $ch->define_var( SIZEOF_VOIDP => $probe->data->{type}->{pointer}->{size} );
286 0 0       0 if(my $size = $probe->data->{type}->{'float complex'}->{size})
287 0         0 { $ch->define_var( SIZEOF_FLOAT_COMPLEX => $size ) }
288 0 0       0 if(my $size = $probe->data->{type}->{'double complex'}->{size})
289 0         0 { $ch->define_var( SIZEOF_DOUBLE_COMPLEX => $size ) }
290 0 0       0 if(my $size = $probe->data->{type}->{'long double complex'}->{size})
291 0         0 { $ch->define_var( SIZEOF_LONG_DOUBLE_COMPLEX => $size ) }
292              
293             # short aliases
294 0         0 $type_map{uchar} = $type_map{'unsigned char'};
295 0         0 $type_map{ushort} = $type_map{'unsigned short'};
296 0         0 $type_map{uint} = $type_map{'unsigned int'};
297 0         0 $type_map{ulong} = $type_map{'unsigned long'};
298              
299             # on Linux and OS X at least the test for bool fails
300             # but _Bool works (even though code using bool seems
301             # to work for both). May be because bool is a macro
302             # for _Bool or something.
303 0   0     0 $type_map{bool} ||= delete $type_map{_Bool};
304 0         0 delete $type_map{_Bool};
305              
306 0         0 $ch->write_config_h;
307              
308 0         0 my %probe;
309 0 0       0 if(defined $ENV{FFI_PLATYPUS_PROBE_OVERRIDE})
310             {
311 0         0 foreach my $kv (split /:/, $ENV{FFI_PLATYPUS_PROBE_OVERRIDE})
312             {
313 0         0 my($k,$v) = split /=/, $kv, 2;
314 0         0 $probe{$k} = $v;
315             }
316             }
317              
318 0 0       0 if($Config{byteorder} =~ /^(1234|12345678)$/)
319             {
320 0         0 $probe{bigendian} = 0;
321 0         0 $probe{bigendian64} = 0;
322             }
323              
324 0 0       0 if($self->build_config->get('config_no_alloca'))
325             {
326 0         0 $probe{alloca} = 0;
327             }
328              
329 0         0 foreach my $cfile (bsd_glob 'inc/probe/*.c')
330             {
331 0         0 my $name = basename $cfile;
332 0         0 $name =~ s/\.c$//;
333 0 0       0 unless(defined $probe{$name})
334             {
335 0         0 my $code = do {
336 0         0 my $fh;
337 0         0 open $fh, '<', $cfile;
338 0         0 local $/;
339 0         0 <$fh>;
340             };
341 0         0 my $value = $probe->check($name, $code);
342 0 0       0 $probe{$name} = $value if defined $value;
343             }
344 0 0       0 if($probe{$name})
345             {
346 0         0 $ch->define_var( "FFI_PL_PROBE_" . uc($name) => 1 );
347             }
348             }
349              
350 0         0 my %abi;
351              
352 0 0       0 if(my $cpp_output = $probe->check_cpp("#include \n"))
353             {
354 0 0       0 if($cpp_output =~ m/typedef\s+enum\s+ffi_abi\s+{(.*?)}/s)
355             {
356 0         0 my $enum = $1;
357 0         0 my %seen;
358 0         0 while($enum =~ s/FFI_([A-Z_0-9]+)//)
359             {
360 0         0 my $abi = $1;
361 0 0       0 next if $seen{$abi};
362 0         0 $seen{$abi}++;
363 0 0       0 next if $abi =~ /^(FIRST|LAST)_ABI$/;
364 0         0 $probe->check_eval(
365             decl => [
366             "#include \"ffi_platypus.h\"",
367             ],
368             stmt => [
369             "ffi_cif cif;",
370             "ffi_type *args[1];",
371             "ffi_abi abi;",
372             "if(ffi_prep_cif(&cif, FFI_$abi, 0, &ffi_type_void, args) != FFI_OK) { return 2; }",
373             ],
374             eval => {
375 0         0 "abi.@{[ lc $abi ]}" => [ '%d' => "FFI_$abi" ],
376             },
377             );
378             }
379 0 0       0 if(defined $probe->data->{abi})
380             {
381 0 0       0 %abi = %{ $probe->data->{abi} || {} };
  0         0  
382             }
383             else
384             {
385 0         0 $probe->log("[[[ Unable to verify any ffi_abis ]]]");
386 0         0 print "*** Unable to detect ffi_abis ***\n";
387 0         0 print "[[[ Unable to verify any ffi_abis ]]]\n";
388 0         0 print "[[[ will try all known ABIs ]]]\n";
389             }
390             }
391             else
392             {
393 0         0 $probe->log("[[[ ffi_abi enum not found ]]]");
394 0         0 print "*** Unable to detect ffi_abis ***\n";
395 0         0 print "[[[ ffi_abi enum not found ]]]\n";
396 0         0 print "[[[ will try all known ABIs ]]]\n";
397             }
398             }
399             else
400             {
401 0         0 $probe->log("[[[ C pre-processor failed... ]]]");
402 0         0 print "*** Unable to detect ffi_abis ***\n";
403 0         0 print "[[[ C pre-processor failed... ]]]\n";
404 0         0 print "[[[ will try all known ABIs ]]]\n";
405             }
406              
407 0 0       0 unless(%abi)
408             {
409 0 0       0 if($probe->check_eval(
410             decl => [
411             "#include \"ffi_platypus.h\"",
412             ],
413             eval => {
414             "abi.default_abi" => [ '%d' => "FFI_DEFAULT_ABI" ],
415             },
416             ))
417             {
418 0 0       0 open my $fh, '<', 'inc/abi/abis-all.json'
419             or die "unable to read abis-all.json $!";
420 0         0 my @abis = @{ decode_json(do { local $/; <$fh> }) };
  0         0  
  0         0  
  0         0  
421 0         0 close $fh;
422              
423 0         0 foreach my $abi (@abis)
424             {
425 0         0 $probe->check_eval(
426             decl => [
427             "#include \"ffi_platypus.h\"",
428             ],
429             stmt => [
430             "ffi_cif cif;",
431             "ffi_type *args[1];",
432             "ffi_abi abi;",
433             "if(ffi_prep_cif(&cif, FFI_$abi, 0, &ffi_type_void, args) != FFI_OK) { return 2; }",
434             ],
435             eval => {
436 0         0 "abi.@{[ lc $abi ]}" => [ '%d' => "FFI_$abi" ],
437             },
438             );
439             }
440              
441 0 0       0 %abi = %{ $probe->data->{abi} || {} };
  0         0  
442             }
443             else
444             {
445 0         0 $probe->log("[[[ fatal: unable to determine even the default ABI ]]]");
446 0         0 print "Unable to determine even the default ABI\n";
447 0         0 die "unable to configure Platypus";
448             }
449             }
450              
451 0         0 $ch->write_config_h;
452 0         0 $self->share_config->set( type_map => \%type_map );
453 0         0 $self->share_config->set( align => \%align );
454 0         0 $self->share_config->set( probe => \%probe );
455 0         0 $self->share_config->set( abi => \%abi );
456             }
457              
458             sub platform
459             {
460 2     2 0 6 my($self) = @_;
461 2         88308 my %Config = %Config;
462 2         1335 my $eumm = $self->build_config->get('eumm');
463 2         12 foreach my $key (keys %$eumm)
464             {
465 16         35 $Config{$key} = $eumm->{$key};
466             }
467 2         39 require FFI::Build::Platform;
468 2         32 FFI::Build::Platform->new(\%Config);
469             }
470              
471             sub alien
472             {
473 1     1 0 4 my($self) = @_;
474              
475 1         3 my $class = $self->build_config->get('alien')->{class};
476 1         3 my $pm = "$class.pm";
477 1         7 $pm =~ s/::/\//g;
478 1         659 require $pm;
479              
480 1         27496 $self->build_config->get('alien')->{class};
481             }
482              
483             1;