File Coverage

blib/lib/Module/XSOrPP.pm
Criterion Covered Total %
statement 64 85 75.2
branch 28 60 46.6
condition 3 6 50.0
subroutine 9 9 100.0
pod 3 3 100.0
total 107 163 65.6


line stmt bran cond sub pod time code
1             package Module::XSOrPP;
2              
3             our $DATE = '2015-05-22'; # DATE
4             our $VERSION = '0.09'; # VERSION
5              
6 1     1   676 use 5.010001;
  1         3  
  1         51  
7 1     1   8 use strict;
  1         1  
  1         51  
8 1     1   7 use warnings;
  1         1  
  1         46  
9              
10 1     1   612 use Dist::Util qw(packlist_for);
  1         878  
  1         75  
11 1     1   650 use Module::Path::More qw(module_path);
  1         908  
  1         143  
12              
13             require Exporter;
14             our @ISA = qw(Exporter);
15             our @EXPORT_OK = qw(
16             is_xs
17             is_pp
18             xs_or_pp
19             );
20              
21             our @XS_OR_PP_MODULES = qw(
22             Params::Util
23             List::MoreUtils
24             );
25              
26             our @XS_MODULES = qw(
27             Scalar::Util
28             );
29              
30             our @PP_MODULES = qw(
31             );
32              
33             sub xs_or_pp {
34 1     1   471 use experimental 'smartmatch';
  1         836  
  1         7  
35              
36 13     13 1 21 my ($mod, $opts) = @_;
37 13 50       31 die "Please specify module\n" unless $mod;
38              
39 13 50       42 if ($mod =~ m!/!) {
40 0         0 $mod =~ s!/!::!g;
41 0         0 $mod =~ s/\.pm$//;
42             }
43              
44 13   50     64 $opts //= {};
45 13   50     60 $opts->{warn} //= 0;
46 13         19 my $warn = $opts->{warn};
47 13   50     46 $opts->{debug} //= 0;
48 13         16 my $debug = $opts->{debug};
49              
50 13 100       63 if ($mod ~~ @XS_OR_PP_MODULES) {
51 3 50       7 warn "$mod is xs_or_pp (from list)\n" if $debug;
52 3         13 return "xs_or_pp";
53             }
54              
55 10 100       29 if ($mod ~~ @XS_MODULES) {
56 3 50       7 warn "$mod is xs (from list)\n" if $debug;
57 3         12 return "xs";
58             }
59              
60 7 50       18 if ($mod ~~ @PP_MODULES) {
61 0 0       0 warn "$mod is pp (from list)\n" if $debug;
62 0         0 return "pp";
63             }
64              
65 7         27 my $path = packlist_for($mod);
66             {
67 7 50       1744 last unless $path;
  7         22  
68 0         0 my $fh;
69 0 0       0 unless (open $fh, '<', $path) {
70 0 0       0 warn "Can't open .packlist $path: $!\n" if $warn;
71 0         0 last;
72             }
73 0         0 while (my $line = <$fh>) {
74 0         0 chomp $line;
75 0 0       0 if ($line =~ /\.(bs|so|[Dd][Ll][Ll])\z/) {
76 0 0       0 warn "$mod is XS because the .packlist contains .{bs,so,dll} files\n" if $debug;
77 0         0 return "xs";
78             }
79             }
80 0 0       0 warn "$mod is PP because the .packlist doesn't contain any .{bs,so,dll} files\n" if $debug;
81 0         0 return "pp";
82             }
83              
84 7         28 $path = module_path(module=>$mod);
85             {
86 7 100       2404 last unless $path;
  7         21  
87 6         23 local $/;
88 6         7 my $fh;
89 6 50       275 unless (open $fh, '<', $path) {
90 0 0       0 warn "Can't open module file $path: $!" if $warn;
91 0         0 last;
92             }
93 6         254 while (my $content = <$fh>) {
94 6 100       2491 if ($content =~ m!^\s*(use|require) \s+ (DynaLoader|XSLoader)\b!mx) {
95 3 50       9 warn "$mod is XS because the source contains 'use {DynaLoader,XSLoader}' statement\n" if $debug;
96 3         48 return "xs";
97             }
98             }
99 3 50       16 warn "$mod is PP because the source code doesn't contain any 'use {DynaLoader,XSLoader}' statement\n" if $debug;
100 3         55 return "pp";
101             }
102              
103             {
104 1         2 my $mod = $mod;
  1         3  
105 1 50       5 unless ($mod =~ /\.pm\z/) { $mod =~ s!::!/!g; $mod .= ".pm" }
  1         3  
  1         3  
106              
107 1 50       12 if ($mod =~ m!/XS\.pm\z|/[^/]+_(xs|XS)\.pm\z!) {
    50          
108 0 0       0 warn "$mod is probably XS because its name contains XS" if $debug;
109 0         0 return "xs";
110             } elsif ($mod =~ m!/PP\.pm\z|/[^/]+_(pp|PP)\.pm\z!) {
111 0 0       0 warn "$mod is probably PP because its name contains PP" if $debug;
112 0         0 return "pp";
113             }
114             }
115              
116 1 50       3 warn "Can't determine whether $mod is XS: all methods tried\n" if $warn;
117 1         3 undef;
118             }
119              
120             sub is_xs {
121 5     5 1 18 my ($mod, $opts) = @_;
122 5         14 my $res = xs_or_pp($mod, $opts);
123 5 100       21 return undef unless defined($res);
124 4 100       36 $res eq 'xs' || $res eq 'xs_or_pp';
125             }
126              
127             sub is_pp {
128 4     4 1 10 my ($mod, $opts) = @_;
129 4         11 my $res = xs_or_pp($mod, $opts);
130 4 50       29 return undef unless defined($res);
131 4 100       515 $res eq 'pp' || $res eq 'xs_or_pp';
132             }
133              
134             1;
135             # ABSTRACT: Determine if an installed module is XS or pure-perl
136              
137             __END__