File Coverage

blib/lib/Devel/FindPerl.pm
Criterion Covered Total %
statement 63 80 78.7
branch 8 24 33.3
condition 4 20 20.0
subroutine 15 16 93.7
pod 2 2 100.0
total 92 142 64.7


line stmt bran cond sub pod time code
1             package Devel::FindPerl;
2             $Devel::FindPerl::VERSION = '0.014';
3 2     2   52386 use strict;
  2         5  
  2         92  
4 2     2   9 use warnings;
  2         2  
  2         72  
5              
6 2     2   7 use Exporter 5.57 'import';
  2         62  
  2         131  
7             our @EXPORT_OK = qw/find_perl_interpreter perl_is_same/;
8             our %EXPORT_TAGS = (all => \@EXPORT_OK);
9              
10 2     2   9 use Carp q/carp/;
  2         2  
  2         119  
11 2     2   8 use Config;
  2         3  
  2         70  
12 2     2   8 use Cwd q/realpath/;
  2         2  
  2         87  
13 2     2   10 use File::Basename qw/basename dirname/;
  2         2  
  2         167  
14 2     2   1109 use File::Spec::Functions qw/catfile catdir rel2abs file_name_is_absolute updir curdir path/;
  2         1392  
  2         218  
15 2     2   14 use Scalar::Util 'tainted';
  2         3  
  2         168  
16 2     2   490 use IPC::Open2 qw/open2/;
  2         4206  
  2         1314  
17              
18             my %perl_for;
19             sub find_perl_interpreter {
20 2   50 2 1 3461 my $config = shift || 'Devel::FindPerl::Config';
21 2 50       49 my $key = $config->can('serialize') ? $config->serialize : '';
22 2   33     20 $perl_for{$key} ||= _discover_perl_interpreter($config);
23 2 50       2160 return wantarray ? @{ $perl_for{$key} } : $perl_for{$key}[0];
  0         0  
24             }
25              
26             sub _discover_perl_interpreter {
27 2     2   5 my $config = shift;
28              
29 2 50       11 return VMS::Filespec::vmsify($^X) if $^O eq 'VMS';
30 2         156 my $perl_basename = basename($^X);
31              
32 2         5 my @potential_perls;
33              
34             # Try 1, Check $^X for absolute and relative path
35 2 0       11 push @potential_perls, file_name_is_absolute($^X) ? [ $^X ] : length +(splitpath($^X))[1] ? [ rel2abs($^X) ] : ();
    50          
36              
37             # Try 2, Last ditch effort: These two option use hackery to try to locate
38             # a suitable perl. The hack varies depending on whether we are running
39             # from an installed perl or an uninstalled perl in the perl source dist.
40 2 50       64 if ($ENV{PERL_CORE}) {
41             # Try 3.A, If we are in a perl source tree, running an uninstalled
42             # perl, we can keep moving up the directory tree until we find our
43             # binary. We wouldn't do this under any other circumstances.
44              
45 0         0 my $perl_src = _perl_src();
46 0 0 0     0 if (defined($perl_src) && length($perl_src)) {
47 0         0 my $uninstperl = catfile($perl_src, $perl_basename);
48             # When run from the perl core, @INC will include the directories
49             # where perl is yet to be installed. We need to reference the
50             # absolute path within the source distribution where it can find
51             # it's Config.pm This also prevents us from picking up a Config.pm
52             # from a different configuration that happens to be already
53             # installed in @INC.
54 0         0 push @potential_perls, [ $uninstperl, '-I' . catdir($perl_src, 'lib') ];
55             }
56             }
57             else {
58             # Try 2.B, First look in $Config{perlpath}, then search the user's
59             # PATH. We do not want to do either if we are running from an
60             # uninstalled perl in a perl source tree.
61              
62 2         19 push @potential_perls, [ $config->get('perlpath') ];
63 2         2317 push @potential_perls, map { [ catfile($_, $perl_basename) ] } path();
  14         102  
64             }
65 2         7 @potential_perls = grep { !tainted($_->[0]) } @potential_perls;
  18         41  
66              
67             # Now that we've enumerated the potential perls, it's time to test
68             # them to see if any of them match our configuration, returning the
69             # absolute path of the first successful match.
70 2         9 my $exe = $config->get('exe_ext');
71 2         7 foreach my $thisperl (@potential_perls) {
72 2 50 33     9 $thisperl->[0] .= $exe if length $exe and $thisperl->[0] !~ m/\Q$exe\E$/i;
73 2 50 33     75 return $thisperl if -f $thisperl->[0] && perl_is_same(@{$thisperl});
  2         9  
74             }
75              
76             # We've tried all alternatives, and didn't find a perl that matches
77             # our configuration. Throw an exception, and list alternatives we tried.
78 0         0 my @paths = map { dirname($_->[0]) } @potential_perls;
  0         0  
79 0         0 die "Can't locate the perl binary used to run this script in (@paths)\n";
80             }
81              
82             # if building perl, perl's main source directory
83             sub _perl_src {
84             # N.B. makemaker actually searches regardless of PERL_CORE, but
85             # only squawks at not finding it if PERL_CORE is set
86              
87 0 0   0   0 return unless $ENV{PERL_CORE};
88              
89 0         0 my $updir = updir;
90 0         0 my $dir = curdir;
91              
92             # Try up to 10 levels upwards
93 0         0 for (0..10) {
94 0 0 0     0 if (
      0        
95             -f catfile($dir,"config_h.SH")
96             &&
97             -f catfile($dir,"perl.h")
98             &&
99             -f catfile($dir,"lib","Exporter.pm")
100             ) {
101 0         0 return realpath($dir);
102             }
103              
104 0         0 $dir = catdir($dir, $updir);
105             }
106              
107 0         0 carp "PERL_CORE is set but I can't find your perl source!\n";
108 0         0 return;
109             }
110              
111             sub perl_is_same {
112 3     3 1 3395 my @perl = @_;
113 3         493 return lc _capture_command(@perl, qw(-MConfig=myconfig -e print -e myconfig)) eq lc Config->myconfig;
114             }
115              
116             sub _capture_command {
117 3     3   11 my (@command) = @_;
118              
119 3         36 local @ENV{qw/PATH IFS CDPATH ENV BASH_ENV/};
120 3         19 my $pid = open2(my($in, $out), @command);
121 3 50       7332 binmode $in, ':crlf' if $^O eq 'MSWin32';
122 3         9 my $ret = do { local $/; <$in> };
  3         25  
  3         35328  
123 3         136 waitpid $pid, 0;
124 3         418 return $ret;
125             }
126              
127             sub Devel::FindPerl::Config::get {
128 4     4   7 my ($self, $key) = @_;
129 4         766 return $Config{$key};
130             }
131              
132             1;
133              
134             #ABSTRACT: Find the path to your perl
135              
136             __END__