File Coverage

blib/lib/Dist/Zilla/Plugin/AlienBuild.pm
Criterion Covered Total %
statement 64 80 80.0
branch 15 28 53.5
condition 1 2 50.0
subroutine 10 11 90.9
pod 0 3 0.0
total 90 124 72.5


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::AlienBuild 0.32 {
2              
3 2     2   364253 use 5.014;
  2         17  
4 2     2   1200 use Moose;
  2         1013364  
  2         18  
5 2     2   16074 use List::Util qw( first );
  2         6  
  2         203  
6 2     2   2328 use Path::Tiny qw( path );
  2         24708  
  2         240  
7 2     2   1382 use Capture::Tiny qw( capture );
  2         54602  
  2         163  
8 2     2   1786 use Data::Dumper ();
  2         13281  
  2         2984  
9              
10             # ABSTRACT: Use Alien::Build with Dist::Zilla
11              
12              
13             with 'Dist::Zilla::Role::FileMunger',
14             'Dist::Zilla::Role::MetaProvider',
15             'Dist::Zilla::Role::PrereqSource';
16              
17             has alienfile_meta => (
18             is => 'ro',
19             isa => 'Int',
20             default => 1,
21             );
22              
23             has clean_install => (
24             is => 'ro',
25             isa => 'Int',
26             default => 0,
27             );
28              
29             has _installer => (
30             is => 'ro',
31             lazy => 1,
32             default => sub {
33             my($self) = @_;
34             my $name = first { /^(Build|Makefile)\.PL$/ } map { $_->name } @{ $self->zilla->files };
35             $self->log_fatal('Unable to find Makefile.PL or Build.PL') unless $name;
36             $name;
37             },
38             );
39              
40             has _build => (
41             is => 'ro',
42             lazy => 1,
43             isa => 'Alien::Build',
44             default => sub {
45             my($self) = @_;
46             if(my $file = first { $_->name eq 'alienfile' } @{ $self->zilla->files })
47             {
48             require Alien::Build;
49             my $alienfile = Path::Tiny->tempfile;
50             $alienfile->spew($file->content);
51             my(undef, undef, $build) = capture { Alien::Build->load($alienfile) };
52             return $build;
53             }
54             else
55             {
56             $self->log_fatal('No alienfile!');
57             }
58             },
59             );
60              
61             sub register_prereqs
62             {
63 3     3 0 7543 my($self) = @_;
64              
65 3         90 my $prereqs = $self->zilla->prereqs->as_string_hash;
66              
67 3 100       1046 if($self->clean_install)
68             {
69 1         31 $self->zilla->register_prereqs({
70             phase => 'configure',
71             type => 'requires',
72             }, 'Alien::Build::MM' => '1.74');
73             }
74              
75 3         294 foreach my $phase (keys %$prereqs)
76             {
77 4         10 foreach my $type (keys %{ $prereqs->{$phase} })
  4         16  
78             {
79 4 100       18 if(defined $prereqs->{$phase}->{$type}->{'Alien::Base'})
80             {
81 1         32 $self->zilla->register_prereqs({
82             type => $type,
83             phase => $phase,
84             }, 'Alien::Base' => '0.038' );
85             }
86             }
87             }
88              
89 3         463 my $build = $self->_build;
90              
91 3         9 my $ab_version = '0.32';
92              
93 3         9 foreach my $hook (qw( build_ffi gather_ffi patch_ffi ))
94             {
95 9 50       99 if($build->meta->has_hook($hook))
96             {
97 0         0 $ab_version = '0.40';
98 0         0 last;
99             }
100             }
101              
102 3 50       137 if($self->_installer eq 'Makefile.PL')
103             {
104             $self->zilla->register_prereqs(
105             { phase => $_ },
106             'Alien::Build::MM' => $ab_version,
107             'ExtUtils::MakeMaker' => '6.52',
108 3         93 ) for qw( configure build );
109             }
110             else
111             {
112             $self->zilla->register_prereqs(
113             { phase => $_ },
114             'Alien::Build::MB' => '0.02',
115 0         0 ) for qw( configure build );
116             }
117              
118             # Configure requires...
119             $self->zilla->register_prereqs(
120             { phase => 'configure' },
121             'Alien::Build' => $ab_version,
122 3         2748 %{ $build->requires('configure') },
  3         55  
123             );
124              
125             # Build requires...
126             $self->zilla->register_prereqs(
127             { phase => 'build' },
128             'Alien::Build' => $ab_version,
129 3         1176 %{ $build->requires('any') },
  3         34  
130             );
131             }
132              
133             my $mm_code_postamble = <<'EOF2';
134             { package
135             MY;
136             sub postamble {
137             $abmm->mm_postamble(@_);
138             }
139             sub install {
140             $abmm->can('mm_install')
141             ? $abmm->mm_install(@_)
142             : shift->SUPER::install(@_);
143             }
144             }
145             EOF2
146              
147             my $comment_begin = "# BEGIN code inserted by @{[ __PACKAGE__ ]}\n";
148             my $comment_end = "# END code inserted by @{[ __PACKAGE__ ]}\n";
149              
150             sub munge_files
151             {
152 3     3 0 206099 my($self) = @_;
153              
154 3 50       122 if($self->_installer eq 'Makefile.PL')
    0          
155             {
156              
157 3         7 my $mm_code_prereqs = do {
158              
159 3         7 my %prop;
160 3 100       104 $prop{clean_install} = 1 if $self->clean_install;
161              
162             # this is overkill atm, but may be useful as we add other properties
163 3 100       27 my $prop = %prop
164             ? Data::Dumper->new([{ clean_install => 1 }])->Terse(1)->Indent(0)->Dump =~ s/^\{//r =~ s/\}$//r
165             : '';
166              
167 3         119 <<"EOF1";
168             use Alien::Build::MM;
169 3 100       26 my \$abmm = Alien::Build::MM->new@{[ $prop ? "($prop)" : '' ]};
170             \%WriteMakefileArgs = \$abmm->mm_args(\%WriteMakefileArgs);
171             EOF1
172             };
173              
174 3     9   17 my $file = first { $_->name eq 'Makefile.PL' } @{ $self->zilla->files };
  9         375  
  3         88  
175 3         157 my $content = $file->content;
176              
177 3         271 my $ok = $content =~ s/(unless \( eval \{ ExtUtils::MakeMaker)/"$comment_begin$mm_code_prereqs$comment_end\n\n$1"/e;
  3         26  
178 3 50       14 $self->log_fatal('unable to find the correct location to insert prereqs')
179             unless $ok;
180              
181 3         21 $content .= "\n\n$comment_begin$mm_code_postamble$comment_end\n";
182              
183 3         12 $file->content($content);
184             }
185              
186             elsif($self->_installer eq 'Build.PL')
187             {
188 0     0   0 my $plugin = first { $_->isa('Dist::Zilla::Plugin::ModuleBuild') } @{ $self->zilla->plugins };
  0         0  
  0         0  
189 0 0       0 $self->log_fatal("unable to find [ModuleBuild] plugin") unless $plugin;
190 0 0       0 if($plugin->mb_class eq 'Module::Build')
191             {
192 0         0 $self->log('setting mb_class to Alien::Build::MB');
193 0         0 $plugin->mb_class('Alien::Build::MB');
194             }
195             else
196             {
197 0 0       0 if(eval { $plugin->mb_class->isa('Alien::Build::MB') })
  0         0  
198             {
199 0         0 $self->log('mb_class is already a Alien::Build::MB');
200             }
201             else
202             {
203 0         0 $self->log_fatal("@{[ $plugin->mb_class ]} is not an Alien::Build::MB");
  0         0  
204             }
205             }
206             }
207              
208             else
209             {
210 0         0 $self->log_fatal('unable to find Makefile.PL or Build.PL');
211             }
212             }
213              
214             sub metadata {
215 3     3 0 14387 my($self) = @_;
216 3         16 my %meta = ( dynamic_config => 1 );
217 3 50       128 if($self->alienfile_meta)
218             {
219             $meta{x_alienfile} = {
220 3   50     17 generated_by => "@{[ __PACKAGE__ ]} version @{[ __PACKAGE__->VERSION || 'dev' ]}",
  3         62  
221             requires => {
222             map {
223 3         38 my %reqs = %{ $self->_build->requires($_) };
  6         14  
  6         258  
224 6         270 $reqs{$_} = "$reqs{$_}" for keys %reqs;
225 6         30 $_ => \%reqs;
226             } qw( share system )
227             },
228             }
229             }
230 3         32 \%meta;
231             }
232              
233             __PACKAGE__->meta->make_immutable;
234              
235             }
236              
237             1;
238              
239             __END__
240              
241             =pod
242              
243             =encoding UTF-8
244              
245             =head1 NAME
246              
247             Dist::Zilla::Plugin::AlienBuild - Use Alien::Build with Dist::Zilla
248              
249             =head1 VERSION
250              
251             version 0.32
252              
253             =head1 SYNOPSIS
254              
255             [AlienBuild]
256              
257             =head1 DESCRIPTION
258              
259             This L<Dist::Zilla> plugin is designed to help create L<Alien> modules using
260             the L<alienfile> and L<Alien::Build> recipe system with L<Alien::Base>. The
261             intent is that you will maintain your L<alienfile> as you normally would,
262             and this plugin will ensure the right prereqs are specified in the C<META.json>
263             and other things that are easy to get not quite right.
264              
265             Specifically, this plugin:
266              
267             =over 4
268              
269             =item adds prereqs
270              
271             Adds the C<configure> requirements to your dist C<configure> requires. It
272             adds the C<any> requirements from your L<alienfile> to your dist C<build>
273             requires.
274              
275             =item adjusts Makefile.PL
276              
277             Adjusts your C<Makefile.PL> to use L<Alien::Build::MM>. If you are using
278             L<ExtUtils::MakeMaker>.
279              
280             =item sets the mb_class for Build.PL
281              
282             sets mb_class to L<Alien::Build::MB> on the L<Dist::Zilla::Plugin::ModuleBuild>
283             plugin. If you are using L<Module::Build>.
284              
285             =item turn on dynamic prereqs
286              
287             Which are used by most L<Alien::Build> based L<Alien> distributions.
288              
289             =item sets x_alienfile meta
290              
291             Unless you turn this feature off using C<alienfile_meta> below.
292              
293             =back
294              
295             =head1 PROPERTIES
296              
297             =head2 alienfile_meta
298              
299             As of version 0.23, this plugin adds a special C<x_alienfile> metadata to your
300             C<META.json> or C<META.yml>. This contains the C<share> and C<system> prereqs
301             based on your alienfile. This may be useful for one day searching for Aliens
302             which use another specific Alien during their build. Note that by their nature,
303             C<share> and C<system> prereqs are dynamic, so on some platforms they may
304             actually be different.
305              
306             This is on by default. You can turn this off by setting this property to C<0>.
307              
308             =head2 clean_install
309              
310             Sets the clean_install property on L<Alien::Build::MM>.
311              
312             =head1 SEE ALSO
313              
314             L<Alien::Build>, L<alienfile>, L<Alien::Base>, L<Alien::Build::MM>, L<Alien::Build::MB>,
315             L<Dist::Zilla::Plugin::AlienBase::Doc>
316              
317             =head1 AUTHOR
318              
319             Graham Ollis <plicease@cpan.org>
320              
321             =head1 COPYRIGHT AND LICENSE
322              
323             This software is copyright (c) 2017 by Graham Ollis.
324              
325             This is free software; you can redistribute it and/or modify it under
326             the same terms as the Perl 5 programming language system itself.
327              
328             =cut