File Coverage

blib/lib/Module/XSOrPP.pm
Criterion Covered Total %
statement 63 84 75.0
branch 28 60 46.6
condition 3 6 50.0
subroutine 9 9 100.0
pod 3 3 100.0
total 106 162 65.4


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