File Coverage

blib/lib/Dist/Zilla/Plugin/FFI/CheckLib.pm
Criterion Covered Total %
statement 48 51 94.1
branch 13 20 65.0
condition 1 2 50.0
subroutine 10 10 100.0
pod 0 4 0.0
total 72 87 82.7


line stmt bran cond sub pod time code
1              
2             use strict;
3 1     1   319322 use warnings;
  1         15  
  1         31  
4 1     1   5 use 5.020;
  1         2  
  1         24  
5 1     1   21  
  1         3  
6             # ABSTRACT: FFI::CheckLib alternative to Dist::Zilla::Plugin::CheckLib
7              
8             use Moose;
9 1     1   559 with
  1         452257  
  1         8  
10             'Dist::Zilla::Role::FileMunger',
11             'Dist::Zilla::Role::InstallTool',
12             'Dist::Zilla::Role::PrereqSource',
13             ;
14              
15             use namespace::autoclean;
16 1     1   7513  
  1         3  
  1         11  
17             my @list_options = qw/
18             alien
19             lib
20             libpath
21             symbol
22             systempath
23             verify
24             /;
25              
26 3     3 0 3290095 has $_ => (
27             isa => 'ArrayRef[Str]',
28             lazy => 1,
29             default => sub { [] },
30             traits => ['Array'],
31             handles => { $_ => 'elements' },
32             ) for @list_options;
33              
34             has [ qw/recursive try_linker_script/ ] => (
35             is => 'rw',
36             lazy => 1,
37             default => sub { 0 },
38             );
39              
40             around dump_config => sub {
41             my ($orig, $self) = @_;
42             my $config = $self->$orig;
43              
44             $config->{+__PACKAGE__} = +{
45             (map {; $_ => [ $self->$_ ] } @list_options),
46             recursive => $self->recursive,
47             try_linker_script => $self->try_linker_script,
48             };
49              
50             $config
51             };
52              
53             my ($self) = @_;
54             $self->zilla->register_prereqs( +{
55             phase => 'configure',
56 3     3 0 6571 type => 'requires',
57 3         94 },
58             'FFI::CheckLib' => '0.28',
59             );
60             }
61              
62             my %files;
63             my ($self) = @_;
64              
65             my @mfpl = grep
66             {; $_->name eq 'Makefile.PL' or $_->name eq 'Build.PL' }
67 3     3 0 119641 @{ $self->zilla->files };
68              
69             for my $mfpl (@mfpl) {
70 9 100       685 $self->log_debug('munging ' . $mfpl->name . ' in file gatherer phase');
71 3         10 $files{ $mfpl->name } = $mfpl;
  3         109  
72             $self->_munge_file($mfpl);
73 3         226 }
74 3         13  
75 3         1143 ()
76 3         175 }
77              
78             my ($self) = @_;
79              
80 3         814 my @mfpl = grep
81             {; $_->name eq 'Makefile.PL' or $_->name eq 'Build.PL' }
82             @{ $self->zilla->files };
83 3     3 0 47441  
84             unless (@mfpl) {
85             $self->log_fatal(
86 9 100       637 'No Makefile.PL or Build.PL was found.'
87 3         7 .' [FFI::CheckLib] should appear in dist.ini'
  3         88  
88             .' after [MakeMaker] or variant!'
89 3 50       277 );
90 0         0 }
91              
92             for my $mfpl (@mfpl) {
93             next if exists $files{ $mfpl->name };
94             $self->log_debug('munging ' . $mfpl->name . ' in setup_installer phase');
95             $self->_munge_file($mfpl);
96             }
97 3         9  
98 3 50       12 ()
99 0         0 }
100 0         0  
101             my ($self, $file) = @_;
102              
103             my $orig_content = $file->content;
104 3         139 $self->log_fatal('could not find position in ' . $file->name . ' to modify!')
105             unless $orig_content =~ m/use strict;\nuse warnings;\n\n/g;
106             my $pos = pos($orig_content);
107 3     3   11  
108             my @options = map {;
109 3         16 my @stuff = map {; '\'' . $_ . '\'' } $self->$_;
110 3 50       256 @stuff ?
111             [
112 3         10 $_ => @stuff > 1 ? ('[ ' . join(', ', @stuff) . ' ]') : $stuff[0]
113             ] : ()
114 3 50       107 } grep !/^verify$/, @list_options,
    50          
115 21         823 ( $self->recursive ? 'recursive' : () ),
  30         112  
116 21 100       151 ( $self->try_linker_script ? 'try_linker_script' : () );
    50          
117              
118             my @verify = map { s/^\|//r } $self->verify;
119              
120             $file->content(
121             substr($orig_content, 0, $pos)
122             . "# inserted by " . blessed($self)
123             . ' ' . ($self->VERSION || '<self>') . "\n"
124 3         129 . "use FFI::CheckLib;\n"
  6         33  
125             . "check_lib_or_exit(\n"
126             . join('', map {; ' 'x2 . $_->[0] . ' => ' . $_->[1] . ",\n" } @options )
127             . (@verify ? join("\n", map { ' 'x2 . $_ } 'verify => sub {', (map { ' 'x2 . $_ } @verify), '},')."\n" : '')
128             . ");\n\n"
129             . substr($orig_content, $pos)
130             );
131             }
132 21         80  
133 3 50 50     56 __PACKAGE__->meta->make_immutable;
  12         59  
  6         19  
134              
135             }
136              
137              
138             =pod
139              
140             =encoding UTF-8
141              
142             =head1 NAME
143              
144             Dist::Zilla::Plugin::FFI::CheckLib - FFI::CheckLib alternative to Dist::Zilla::Plugin::CheckLib
145              
146             =head1 VERSION
147              
148             version 1.07
149              
150             =head1 SYNOPSIS
151              
152             In your F<dist.ini>:
153              
154             [FFI::CheckLib]
155             lib = zmq
156              
157             =head1 DESCRIPTION
158              
159             This is a L<Dist::Zilla> plugin that modifies the F<Makefile.PL> or
160             F<Build.PL> in your distribution to check for a dynamic library L<FFI::Platypus> (or
161             similar) can access; uses L<FFI::CheckLib> to perform the check.
162              
163             If the library is not available, the program exits with a status of zero,
164             which will result in a NA result on a CPAN test reporter.
165              
166             This module is adapted directly from Dist::Zilla::Plugin::CheckLib, copyright (c) 2014 by Karen Etheridge (CPAN: ETHER).
167             Look there for XS modules.
168              
169             =head1 CONFIGURATION OPTIONS
170              
171             All options are as documented in L<FFI::CheckLib>:
172              
173             =head2 C<lib>
174              
175             The name of a single dynamic library (for example, C<zmq>).
176             Can be used more than once.
177              
178             L<FFI::CheckLib> will prepend C<lib> and append an appropriate dynamic library
179             suffix as needed.
180              
181             =head2 C<symbol>
182              
183             A symbol that must be found. Can be used more than once.
184              
185             =head2 C<systempath>
186              
187             The system search path to use (instead of letting L<FFI::CheckLib> determine
188             paths). Can be used more than once.
189              
190             =head2 C<libpath>
191              
192             Additional path to search for libraries. Can be used more than once.
193              
194             =head2 C<alien>
195              
196             The name of an L<Alien> class that provides the L<Alien::Base> interface for
197             dynamic libraries.
198              
199             Can be used more than once.
200              
201             =head2 C<recursive>
202              
203             If set to true, directories specified in C<libpath> will be searched
204             recursively.
205              
206             Defaults to false.
207              
208             =head2 C<try_linker_script>
209              
210             If set to true, uses the linker command to attempt to resolve C<.so> files for
211             platforms where C<.so> files are linker scripts.
212              
213             Defaults to false.
214              
215             =head2 C<verify>
216              
217             The verify function body to use. For each usage, is one line of the function
218             body. You can prefix with the pipe C<|> character to get proper indentation.
219              
220             verify = | my($name, $libpath) = @_;
221             verify = | my $ffi = FFI::Platypus->new;
222             verify = | $ffi->lib($libpath);
223             verify = | my $f = $ffi->function('foo_version', [] => 'int');
224             verify = | if($f) {
225             verify = | return $f->call() >= 500; # we accept version 500 or better
226             verify = | } else {
227             verify = | return;
228             verify = | }
229              
230             If you use any modules, such as L<FFI::Platypus> in this example, be sure that
231             you declare them as configure requires.
232              
233             =head1 SEE ALSO
234              
235             =over 4
236              
237             =item *
238              
239             L<FFI::CheckLib>
240              
241             =item *
242              
243             L<Devel::CheckLib> and L<Dist::Zilla::Plugin::CheckLib>
244              
245             =item *
246              
247             L<Devel::AssertOS> and L<Dist::Zilla::Plugin::AssertOS>
248              
249             =back
250              
251             =head1 AUTHOR
252              
253             Author: Graham Ollis E<lt>plicease@cpan.orgE<gt>
254              
255             Contributors:
256              
257             Zaki Mughal (zmughal)
258              
259             =head1 COPYRIGHT AND LICENSE
260              
261             This software is copyright (c) 2018-2022 by Graham Ollis.
262              
263             This is free software; you can redistribute it and/or modify it under
264             the same terms as the Perl 5 programming language system itself.
265              
266             =cut