File Coverage

blib/lib/Imager/Probe.pm
Criterion Covered Total %
statement 20 351 5.7
branch 0 240 0.0
condition 0 124 0.0
subroutine 7 34 20.5
pod 0 2 0.0
total 27 751 3.6


line stmt bran cond sub pod time code
1             package Imager::Probe;
2 1     1   1370 use 5.006;
  1         5  
3 1     1   6 use strict;
  1         3  
  1         25  
4 1     1   6 use File::Spec;
  1         2  
  1         22  
5 1     1   5 use Config;
  1         2  
  1         62  
6 1     1   6 use Cwd ();
  1         2  
  1         33  
7 1     1   1074 use File::Temp ();
  1         15270  
  1         39  
8 1     1   8 use Carp ();
  1         2  
  1         8047  
9              
10             our $VERSION = "1.011";
11              
12             my @alt_transfer = qw/altname incsuffix libbase/;
13              
14             sub probe {
15 0     0 0   my ($class, $req) = @_;
16              
17 0           _populate_defaults($req);
18              
19 0           my $name = $req->{name};
20 0           my $result;
21 0 0         if ($req->{code}) {
22 0           $result = _probe_code($req);
23             }
24 0 0 0       if (!$result && $req->{pkg}) {
25 0           $result = _probe_pkg($req);
26             }
27 0 0 0       if (!$result && $req->{inccheck} && ($req->{libcheck} || $req->{libbase})) {
      0        
      0        
28 0   0       $req->{altname} ||= "main";
29 0           $result = _probe_check($req);
30             }
31              
32 0 0 0       if ($result && $req->{testcode}) {
33 0           $result = _probe_test($req, $result);
34             }
35              
36 0 0 0       if (!$result && $req->{alternatives}) {
37 0           ALTCHECK:
38             my $index = 1;
39 0           for my $alt (@{$req->{alternatives}}) {
  0            
40 0   0       $req->{altname} = $alt->{altname} || "alt $index";
41             $req->{verbose}
42 0 0         and print "$req->{name}: Trying alternative $index\n";
43 0           my %work = %$req;
44 0           for my $key (@alt_transfer) {
45 0 0         exists $alt->{$key} and $work{$key} = $alt->{$key};
46             }
47 0           $result = _probe_check(\%work);
48              
49 0 0 0       if ($result && $req->{testcode}) {
50 0           $result = _probe_test(\%work, $result);
51             }
52              
53             $result
54 0 0         and last;
55              
56 0           ++$index;
57             }
58             }
59              
60 0 0 0       if (!$result && $req->{testcode}) {
61 0           $result = _probe_fake($req);
62              
63 0 0         $result or return;
64              
65 0           $result = _probe_test($req, $result);
66             }
67              
68 0 0         $result or return;
69              
70 0           return $result;
71             }
72              
73             my @default_argv_names =
74             (
75             qw(ccflags optimize cc ldflags)
76             );
77              
78             sub _populate_defaults {
79 0     0     my ($req) = @_;
80 0   0       $req->{verbose} ||= $ENV{IM_VERBOSE};
81 0           my %names = map {; $_ => 1 } @default_argv_names;
  0            
82 0           @$req{@default_argv_names} = @Config{@default_argv_names};
83 0           for my $arg (@ARGV) {
84 0 0         if ($arg =~ /^\U\Q$arg\E=(.*)$/) {
85 0           $req->{$arg} = $1;
86             }
87             }
88             }
89              
90             sub _probe_code {
91 0     0     my ($req) = @_;
92              
93 0           my $code = $req->{code};
94 0 0         my @probes = ref $code eq "ARRAY" ? @$code : $code;
95              
96 0           my $result;
97 0           for my $probe (@probes) {
98 0 0         $result = $probe->($req)
99             and return $result;
100             }
101              
102 0           return;
103             }
104              
105             sub is_exe {
106 0     0 0   my ($name) = @_;
107              
108 0           my @exe_suffix = $Config{_exe};
109 0 0         if ($^O eq 'MSWin32') {
    0          
110 0           push @exe_suffix, qw/.bat .cmd/;
111             }
112             elsif ($^O eq 'cygwin') {
113 0           push @exe_suffix, "";
114             }
115              
116 0           for my $dir (File::Spec->path) {
117 0           for my $suffix (@exe_suffix) {
118 0 0         -x File::Spec->catfile($dir, "$name$suffix")
119             and return 1;
120             }
121             }
122              
123 0           return;
124             }
125              
126             sub _probe_pkg {
127 0     0     my ($req) = @_;
128              
129             # Setup pkg-config's environment variable to search non-standard paths
130             # which may be provided by --libdirs.
131 0           my @pkgcfg_paths = map { "$_/pkgconfig" } _lib_paths( $req );
  0            
132 0 0         unshift @pkgcfg_paths, $ENV{ 'PKG_CONFIG_PATH' } if $ENV{ 'PKG_CONFIG_PATH' };
133              
134 0           local $ENV{ 'PKG_CONFIG_PATH' } = join $Config{path_sep}, @pkgcfg_paths;
135 0 0         print "PKG_CONFIG_PATH=$ENV{PKG_CONFIG_PATH}\n" if $req->{verbose};
136              
137 0 0         is_exe('pkg-config') or return;
138 0 0         my $redir = $^O eq 'MSWin32' ? '' : '2>/dev/null';
139              
140 0           my @pkgs = @{$req->{pkg}};
  0            
141 0           for my $pkg (@pkgs) {
142 0 0         if (!system("pkg-config $pkg --exists $redir")) {
143             # if we find it, but the following fail, then pkg-config is too
144             # broken to be useful
145 0 0 0       my $cflags = `pkg-config $pkg --cflags`
146             and !$? or return;
147              
148 0 0 0       my $lflags = `pkg-config $pkg --libs`
149             and !$? or return;
150              
151 0           my $defines = '';
152 0           $cflags =~ s/(-D\S+)/$defines .= " $1"; ''/ge;
  0            
  0            
153              
154 0           chomp $cflags;
155 0           chomp $lflags;
156 0           print "$req->{name}: Found via pkg-config $pkg\n";
157 0 0         print <{verbose};
158             cflags: $cflags
159             defines: $defines
160             lflags: $lflags
161             EOS
162             # rt 75869
163             # if Win32 doesn't provide this information, too bad
164 0 0 0       if (!grep(/^-L/, split " ", $lflags)
165             && $^O ne 'MSWin32') {
166             # pkg-config told us about the library, make sure it's
167             # somewhere EU::MM can find it
168 0 0         print "Checking if EU::MM can find $lflags\n" if $req->{verbose};
169             my ($extra, $bs_load, $ld_load, $ld_run_path) =
170 0           ExtUtils::Liblist->ext($lflags, $req->{verbose});
171 0 0         unless ($ld_run_path) {
172             # search our standard places
173 0           $lflags = _resolve_libs($req, $lflags);
174             }
175             }
176              
177             return
178             {
179 0           INC => $cflags,
180             LIBS => $lflags,
181             DEFINE => $defines,
182             };
183             }
184             }
185              
186 0           print "$req->{name}: Not found via pkg-config\n";
187              
188 0           return;
189             }
190              
191             sub _is_msvc {
192 0     0     return $Config{cc} eq "cl";
193             }
194              
195             sub _lib_basename {
196 0     0     my ($base) = @_;
197              
198 0 0         if (_is_msvc()) {
199 0           return $base;
200             }
201             else {
202 0           return "lib$base";
203             }
204             }
205              
206             sub _lib_option {
207 0     0     my ($base) = @_;
208              
209 0 0         if (_is_msvc()) {
210 0           return $base . $Config{_a};
211             }
212             else {
213 0           return "-l$base";
214             }
215             }
216              
217             sub _quotearg {
218 0     0     my ($opt) = @_;
219              
220 0 0         return $opt =~ /\s/ ? qq("$opt") : $opt;
221             }
222              
223             sub _probe_check {
224 0     0     my ($req) = @_;
225              
226 0           my @libcheck;
227             my @libbase;
228 0 0         if ($req->{libcheck}) {
    0          
229 0 0         if (ref $req->{libcheck} eq "ARRAY") {
230 0           push @libcheck, @{$req->{libcheck}};
  0            
231             }
232             else {
233 0           push @libcheck, $req->{libcheck};
234             }
235             }
236             elsif ($req->{libbase}) {
237 0 0         @libbase = ref $req->{libbase} ? @{$req->{libbase}} : $req->{libbase};
  0            
238              
239 0           my $lext=$Config{'so'}; # Get extensions of libraries
240 0           my $aext=$Config{'_a'};
241              
242 0           for my $libbase (@libbase) {
243 0           my $basename = _lib_basename($libbase);
244             push @libcheck, sub {
245 0 0   0     -e File::Spec->catfile($_[0], "$basename$aext")
246             || -e File::Spec->catfile($_[0], "$basename.$lext")
247 0           };
248             }
249             }
250             else {
251             print "$req->{name}: No libcheck or libbase, nothing to search for\n"
252 0 0         if $req->{verbose};
253 0           return;
254             }
255              
256 0           my @found_libpath;
257 0           my @lib_search = _lib_paths($req);
258             print "$req->{name}: Searching directories for libraries:\n"
259 0 0         if $req->{verbose};
260 0           for my $libcheck (@libcheck) {
261 0           for my $path (@lib_search) {
262 0 0         print "$req->{name}: $path\n" if $req->{verbose};
263 0 0         if ($libcheck->($path)) {
264 0 0         print "$req->{name}: Found!\n" if $req->{verbose};
265 0           push @found_libpath, $path;
266 0           last;
267             }
268             }
269             }
270              
271 0           my $found_incpath;
272 0           my $inccheck = $req->{inccheck};
273 0           my @inc_search = _inc_paths($req);
274             print "$req->{name}: Searching directories for headers:\n"
275 0 0         if $req->{verbose};
276 0           for my $path (@inc_search) {
277 0 0         print "$req->{name}: $path\n" if $req->{verbose};
278 0 0         if ($inccheck->($path)) {
279 0 0         print "$req->{name}: Found!\n" if $req->{verbose};
280 0           $found_incpath = $path;
281 0           last;
282             }
283             }
284              
285 0           my $alt = "";
286 0 0         if ($req->{altname}) {
287 0           $alt = " $req->{altname}:";
288             }
289 0 0         print "$req->{name}:$alt includes ", $found_incpath ? "" : "not ",
    0          
290             "found - libraries ", @found_libpath == @libcheck ? "" : "not ", "found\n";
291              
292 0 0 0       @found_libpath == @libcheck && $found_incpath
293             or return;
294              
295 0           my @libs = map "-L$_", @found_libpath;
296 0 0         if ($req->{libopts}) {
    0          
297 0           push @libs, $req->{libopts};
298             }
299             elsif (@libbase) {
300 0           push @libs, map _lib_option($_), @libbase;
301             }
302             else {
303 0           die "$req->{altname}: inccheck but no libbase or libopts";
304             }
305              
306             return
307             {
308 0           INC => _quotearg("-I$found_incpath"),
309             LIBS => join(" ", map _quotearg($_), @libs),
310             DEFINE => "",
311             };
312             }
313              
314             sub _probe_fake {
315 0     0     my ($req) = @_;
316              
317             # the caller provided test code, and the compiler may look in
318             # places we don't, see Imager-Screenshot ticket 56793,
319             # so fake up a result so the test code can
320 0           my $lopts;
321 0 0         if ($req->{libopts}) {
    0          
322 0           $lopts = $req->{libopts};
323             }
324             elsif (defined $req->{libbase}) {
325             # might not need extra libraries, eg. Win32 perl already links
326             # everything
327             my @libs = $req->{libbase}
328 0           ? ( ref $req->{libbase} ? @{$req->{libbase}} : $req->{libbase} )
329 0 0         : ();
    0          
330 0           $lopts = join " ", map _lib_option($_), @libs;
331             }
332 0 0         if (defined $lopts) {
333 0           print "$req->{name}: Checking if the compiler can find them on its own\n";
334             return
335             {
336 0           INC => "",
337             LIBS => $lopts,
338             DEFINE => "",
339             };
340             }
341             else {
342             print "$req->{name}: Can't fake it - no libbase or libopts\n"
343 0 0         if $req->{verbose};
344 0           return;
345             }
346             }
347              
348             sub _probe_test {
349 0     0     my ($req, $result) = @_;
350              
351             # setup LD_RUN_PATH to match link time
352 0 0         print "Asking liblist for LD_RUN_PATH:\n" if $req->{verbose};
353             my ($extra, $bs_load, $ld_load, $ld_run_path) =
354 0           ExtUtils::Liblist->ext($result->{LIBS}, $req->{verbose});
355 0           local $ENV{LD_RUN_PATH};
356              
357 0 0         if ($ld_run_path) {
358             print "Setting LD_RUN_PATH=$ld_run_path for $req->{name} probe\n"
359 0 0         if $req->{verbose};
360 0           $ENV{LD_RUN_PATH} = $ld_run_path;
361 0 0 0       if ($Config{lddlflags} =~ /([^ ]*-(?:rpath|R)[,=]?)([^ ]+)/
362             && -d $2) {
363             # hackety, hackety
364             # LD_RUN_PATH is ignored when there's already an -rpath option
365             # so provide one
366 0           my $prefix = $1;
367             $result->{LDDLFLAGS} = $Config{lddlflags} . " " .
368 0           join " ", map "$prefix$_", split $Config{path_sep}, $ld_run_path;
369             }
370             }
371             my $good = _check_lib(
372             $req,
373             LIBS => $result->{LIBS},
374             INC => $result->{INC},
375             header => $req->{testcodeheaders},
376             function => $req->{testcode},
377             prologue => $req->{testcodeprologue},
378 0           );
379 0 0         unless ($good) {
380 0           print "$req->{name}: Test code failed: $@";
381 0           return;
382             }
383              
384 0           print "$req->{name}: Passed code check\n";
385 0           return $result;
386             }
387              
388             sub _check_lib {
389 0     0     my ($req, %args) = @_;
390              
391 0           my $code = "";
392 0 0         if (my $hdrs = $args{header}) {
393 0 0         ref $hdrs or $hdrs = [ $hdrs ];
394 0           $code .= "#include <$_>\n" for @$hdrs;
395             }
396 0 0         $code .= $args{prologue} if $args{prologue};
397 0 0         $args{function} or Carp::confess "Missing function";
398 0           $code .= "int main(int argc, char **argv) {\n$args{function}\n}\n";
399              
400             return _try_compile_and_link
401             (
402             $code, $req,
403             name => $req->{name},
404             ccflags => $args{INC},
405             run => 1,
406             libs => $args{LIBS},
407 0           );
408             }
409              
410             sub _resolve_libs {
411 0     0     my ($req, $lflags) = @_;
412              
413 0           my @libs = grep /^-l/, split ' ', $lflags;
414 0           my %paths;
415 0           my @paths = _lib_paths($req);
416 0           my $so = $Config{so};
417 0           my $libext = $Config{_a};
418 0           for my $lib (@libs) {
419 0           $lib =~ s/^-l/lib/;
420              
421 0           for my $path (@paths) {
422 0 0 0       if (-e "$path/$lib.$so" || -e "$path/$lib$libext") {
423 0           $paths{$path} = 1;
424             }
425             }
426             }
427              
428 0           return join(" ", ( map "-L$_", keys %paths ), $lflags );
429             }
430              
431             sub _lib_paths {
432 0     0     my ($req) = @_;
433              
434             print "$req->{name} IM_LIBPATH: $ENV{IM_LIBPATH}\n"
435 0 0 0       if $req->{verbose} && defined $ENV{IM_LIBPATH};
436             print "$req->{name} LIB: $ENV{IM_LIBPATH}\n"
437 0 0 0       if $req->{verbose} && defined $ENV{LIB} && $^O eq "MSWin32";
      0        
438 0           my $lp = $req->{libpath};
439             print "$req->{name} libpath: ", ref $lp ? join($Config{path_sep}, @$lp) : $lp, "\n"
440 0 0 0       if $req->{verbose} && defined $lp;
    0          
441              
442             return _paths
443             (
444             $ENV{IM_LIBPATH},
445             $req->{libpath},
446             (
447 0           map { split ' ' }
448             grep $_,
449             @Config{qw/loclibpth libpth libspath/}
450             ),
451 0 0         $^O eq "MSWin32" ? $ENV{LIB} : "",
    0          
452             $^O eq "cygwin" ? "/usr/lib/w32api" : "",
453             "/usr/lib",
454             "/usr/local/lib",
455             _gcc_lib_paths(),
456             _dyn_lib_paths(),
457             );
458             }
459              
460             sub _gcc_lib_paths {
461             $Config{gccversion}
462 0 0   0     or return;
463              
464 0 0         my ($base_version) = $Config{gccversion} =~ /^([0-9]+)/
465             or return;
466              
467 0 0         $base_version >= 4
468             or return;
469              
470 0           local $ENV{LANG} = "C";
471 0           local $ENV{LC_ALL} = "C";
472 0 0         my ($lib_line) = grep /^libraries:/, `$Config{cc} -print-search-dirs`
473             or return;
474 0           $lib_line =~ s/^libraries: =//;
475 0           chomp $lib_line;
476              
477 0   0       return grep !/gcc/ && -d, split /:/, $lib_line;
478             }
479              
480             sub _dyn_lib_paths {
481 0 0         return map { defined() ? split /\Q$Config{path_sep}/ : () }
482 0     0     map $ENV{$_},
483             qw(LD_RUN_PATH LD_LIBRARY_PATH DYLD_LIBRARY_PATH LIBRARY_PATH);
484             }
485              
486             sub _inc_paths {
487 0     0     my ($req) = @_;
488              
489             print "$req->{name} IM_INCPATH: $ENV{IM_INCPATH}\n"
490 0 0 0       if $req->{verbose} && defined $ENV{IM_INCPATH};
491             print "$req->{name} INCLUDE: $ENV{INCLUDE}\n"
492 0 0 0       if $req->{verbose} && defined $ENV{INCLUDE} && $^O eq "MSWin32";
      0        
493 0           my $ip = $req->{incpath};
494             print "$req->{name} incpath: ", ref $ip ? join($Config{path_sep}, @$ip) : $ip, "\n"
495 0 0 0       if $req->{verbose} && defined $req->{incpath};
    0          
496              
497             my @paths = _paths
498             (
499             $ENV{IM_INCPATH},
500             $req->{incpath},
501             $^O eq "MSWin32" ? $ENV{INCLUDE} : "",
502             $^O eq "cygwin" ? "/usr/include/w32api" : "",
503             (
504 0           map { split ' ' }
505             grep $_,
506 0 0         @Config{qw/locincpth incpath/}
    0          
507             ),
508             "/usr/include",
509             "/usr/local/include",
510             _gcc_inc_paths(),
511             _dyn_inc_paths(),
512             );
513              
514 0 0         if ($req->{incsuffix}) {
515 0           @paths = map File::Spec->catdir($_, $req->{incsuffix}), @paths;
516             }
517              
518 0           return @paths;
519             }
520              
521             sub _gcc_inc_paths {
522             $Config{gccversion}
523 0 0   0     or return;
524              
525 0 0         my ($base_version) = $Config{gccversion} =~ /^([0-9]+)/
526             or return;
527              
528 0 0         $base_version >= 4
529             or return;
530              
531 0           local $ENV{LANG} = "C";
532 0           local $ENV{LC_ALL} = "C";
533 0           my $devnull = File::Spec->devnull;
534 0           my @spam = `$Config{cc} -E -v - <$devnull 2>&1`;
535             # output includes lines like:
536             # ...
537             # ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../x86_64-linux-gnu/include"
538             # #include "..." search starts here:
539             # #include <...> search starts here:
540             # /usr/lib/gcc/x86_64-linux-gnu/4.9/include
541             # /usr/local/include
542             # /usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed
543             # /usr/include/x86_64-linux-gnu
544             # /usr/include
545             # End of search list.
546             # # 1 ""
547             # # 1 ""
548             # ...
549              
550 0   0       while (@spam && $spam[0] !~ /^#include /) {
551 0           shift @spam;
552             }
553 0           my @inc;
554 0   0       while (@spam && $spam[0] !~ /^End of search/) {
555 0           my $line = shift @spam;
556 0           chomp $line;
557 0 0         next if $line =~ /^#include /;
558 0 0         next unless $line =~ s/^\s+//;
559 0           push @inc, $line;
560             }
561 0           return @inc;
562             }
563              
564             sub _dyn_inc_paths {
565             return map {
566 0     0     my $tmp = $_;
  0            
567 0 0         $tmp =~ s/\blib$/include/ ? $tmp : ()
568             } _dyn_lib_paths();
569             }
570              
571             sub _paths {
572 0     0     my (@in) = @_;
573              
574 0           my @out;
575              
576             # expand any array refs
577 0 0         @in = map { ref() ? @$_ : $_ } @in;
  0            
578              
579 0           for my $path (@in) {
580 0 0         $path or next;
581 0           $path = _tilde_expand($path);
582              
583 0           push @out, grep -d $_, split /\Q$Config{path_sep}/, $path;
584             }
585              
586 0           @out = map Cwd::realpath($_), @out;
587              
588 0           my %seen;
589 0           @out = grep !$seen{$_}++, @out;
590              
591 0           return @out;
592             }
593              
594             my $home;
595             sub _tilde_expand {
596 0     0     my ($path) = @_;
597              
598 0 0         if ($path =~ m!^~[/\\]!) {
599 0 0         defined $home or $home = $ENV{HOME};
600 0 0 0       if (!defined $home && $^O eq 'MSWin32'
      0        
      0        
601             && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
602 0           $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
603             }
604 0 0         unless (defined $home) {
605 0           $home = eval { (getpwuid($<))[7] };
  0            
606             }
607 0 0         defined $home or die "You supplied $path, but I can't find your home directory\n";
608 0           $path =~ s/^~//;
609 0           $path = File::Spec->catdir($home, $path);
610             }
611              
612 0           return $path;
613             }
614              
615             sub _tcal_state {
616 0     0     my ($req) = @_;
617 0           my %state;
618              
619 0 0         $state{start_dir} = Cwd::getcwd()
620             or die "Cannot save current directory: $!\n";
621 0           $state{keep} = !!$ENV{IMAGER_PROBE_KEEP_FILES};
622             $state{tmpdir} = File::Temp->newdir(CLEANUP => !$state{keep})
623 0 0         or Carp::confess("panic: cannot create temp directory");
624 0           $state{num} = 1;
625              
626 0           \%state;
627             }
628              
629             sub _sort_std {
630 0     0     my @stds = grep defined, @_;
631             # we don't support -std=iso9899:1999 etc
632 0 0   0     my $std_map = sub { my $std = shift; return $std > 80 ? $std-100 : $std };
  0            
  0            
633 0           return sort { $std_map->($b) <=> $std_map->($a) } grep defined, @stds;
  0            
634             }
635              
636             # _try_compile_and_link
637             # adapted from Time::HiRes and then adapted some more.
638             # This is not part of the Imager::Probe API
639             #
640             # $code - code to test
641             #
642             # %args - options to control this test
643             # name - required description of what we're testing, used for verbose
644             # cc - optional C compiler (overrides $req->{cc}
645             # ccflags - optional extra compiler flags
646             # ccflags_only - only use ccflags and don't use $req->{ccflags}
647             # libs - extra libraries to link to
648             # std - C standard, needs stdflag set in $req per by probe_std()
649             # nolink - only test compilation success
650             #
651             # $req contains probing state, used here:
652             # verbose - print messages if true
653             # stdflag - compiler option used to select a C standard, by probe_std
654             # minstd - minimum standard (default: 99)
655             # ccflags - base ccflags
656             # cc - base cc
657             #
658              
659             sub _try_compile_and_link {
660 0     0     my ($code, $req, %args) = @_;
661              
662 0   0       my $verbose = $req->{verbose} || 0;
663 0   0       my $indent = $req->{indent} || "";
664             my $name = $args{name}
665 0 0         or Carp::confess("panic: no name supplied to _try_compile_and_link");
666 0   0       my $state = $req->{tcal_state} ||= _tcal_state($req);
667             chdir $state->{tmpdir}
668 0 0         or die "Cannot chdir to $state->{tmpdir}: $!";
669 0           my $ok = 0;
670 0           my $base = "test$state->{num}";
671 0           ++$state->{num};
672              
673 0   0       my $obj_ext = $Config{obj_ext} || ".o";
674 0           unlink("$base.c", "$base$obj_ext");
675              
676 0 0         if (open(my $tmpc, '>', "$base.c")) {
677 0           print $tmpc $code;
678 0           close($tmpc);
679              
680             # we don't need this for our probes
681             #my $COREincdir = File::Spec->catdir($Config{'archlibexp'}, 'CORE');
682              
683 0           my $cc = $req->{cc};
684 0           my $ccflags = "";
685 0 0         $ccflags = $req->{ccflags} unless $args{ccflags_only};
686 0 0         $ccflags .= " $args{ccflags}" if $args{ccflags};
687 0           $ccflags .= " $req->{'optimize'}";
688             # we want the maximum std
689 0           my ($std) = _sort_std($args{std}, $req->{minstd});
690 0   0       my $stdflag = $args{stdflag} || $req->{stdflag};
691 0 0 0       if ($std && $stdflag) {
692 0           $ccflags .= " $stdflag$std";
693             }
694             # we don't need this (yet)
695             #. ' ' . "-I$COREincdir" . ' -DPERL_NO_INLINE_FUNCTIONS';
696              
697 0 0         my $errornull = $verbose ? '' : "2>" . File::Spec->devnull;
698              
699 0           my $cccmd;
700             my $base_out;
701 0 0         if ($args{nolink}) {
702 0           $base_out = "$base$obj_ext";
703 0           $cccmd = "$cc -c -o $base_out $ccflags $base.c $errornull";
704             }
705             else {
706 0   0       my $libs = $args{libs} || '';
707 0           $base_out = "$base$Config{_exe}";
708 0           $cccmd = "$cc -o $base_out $ccflags $base.c $libs $errornull";
709             }
710              
711 0 0         printf "${indent}cccmd = $cccmd\n" if $verbose;
712 0           my $res = system($cccmd);
713 0   0       $ok = defined($res) && $res == 0 && -s $base_out;
714              
715 0 0 0       if ($ok && !$args{nolink} && !-x $base_out) {
      0        
716 0           $ok = 0;
717             }
718              
719 0 0 0       if ( $ok && $args{run} ) {
720             # some Imager module probes use files shipped with the module
721             # so run from the original directory so they're visible
722             chdir $state->{start_dir}
723 0 0         or die "Cannot return to original current directory $state->{start_dir}: $!\n";
724              
725             my $tmp_exe =
726 0           File::Spec->catfile($state->{tmpdir}, $base_out);
727 0           my @run = $tmp_exe;
728 0 0 0       unshift @run, $Config{run} if $Config{run} && -e $Config{run};
729 0 0         printf "${indent}Running $tmp_exe..." if $verbose;
730 0 0         if (system(@run) == 0) {
731 0           $ok = 1;
732 0 0         print "${indent} success\n" if $verbose;
733             } else {
734 0           $ok = 0;
735 0           my $errno = $? >> 8;
736 0           local $! = $errno;
737 0 0         printf <
738              
739             ${indent}*** The test run of '$tmp_exe' failed: status $?
740             ${indent}*** (the status means: errno = $errno or '$!')
741             EOF
742             }
743             }
744             # now cleaned up with the temp dir
745             # unlink("$tmp.c", $tmp_out);
746             }
747              
748             # redundant but harmless if we ran the test executable
749             chdir $state->{start_dir}
750 0 0         or die "Cannot return to original current directory $state->{start_dir}: $!\n";
751              
752              
753 0           return $ok;
754             }
755              
756             1;
757              
758             __END__