File Coverage

blib/lib/Dist/Zilla/Plugin/MakeMaker/Custom.pm
Criterion Covered Total %
statement 37 41 90.2
branch 8 10 80.0
condition 3 6 50.0
subroutine 8 9 88.8
pod 2 5 40.0
total 58 71 81.6


line stmt bran cond sub pod time code
1             #---------------------------------------------------------------------
2             package Dist::Zilla::Plugin::MakeMaker::Custom;
3             #
4             # Copyright 2010 Christopher J. Madsen
5             #
6             # Author: Christopher J. Madsen <perl@cjmweb.net>
7             # Created: 11 Mar 2010
8             #
9             # This program is free software; you can redistribute it and/or modify
10             # it under the same terms as Perl itself.
11             #
12             # This program is distributed in the hope that it will be useful,
13             # but WITHOUT ANY WARRANTY; without even the implied warranty of
14             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the
15             # GNU General Public License or the Artistic License for more details.
16             #
17             # ABSTRACT: Allow a dist to have a custom Makefile.PL
18             #---------------------------------------------------------------------
19              
20             our $VERSION = '4.26';
21             # This file is part of Dist-Zilla-Plugins-CJM 4.27 (August 29, 2015)
22              
23              
24 2     2   688891 use Moose;
  2         3  
  2         15  
25 2     2   13382 use Dist::Zilla::Plugin::MakeMaker 4.300009; # improved subclassing
  2         761525  
  2         127  
26             extends 'Dist::Zilla::Plugin::MakeMaker';
27             with qw(Dist::Zilla::Role::FilePruner
28             Dist::Zilla::Role::HashDumper);
29              
30 2     2   15 use List::Util ();
  2         2  
  2         1182  
31              
32             # We're trying to make the template executable before it's filled in,
33             # so we want delimiters that look like comments:
34             has '+delim' => (
35             default => sub { [ '##{', '##}' ] },
36             );
37              
38             # Need to cache write_makefile_args for the get_default method
39             has _mmc_write_makefile_args => (
40             is => 'ro',
41             isa => 'HashRef',
42             lazy => 1,
43             init_arg => undef,
44             builder => 'write_makefile_args',
45             );
46              
47             # Get rid of any META.yml we may have picked up from MakeMaker:
48             sub prune_files
49             {
50 3     3 0 3152 my ($self) = @_;
51              
52 3         116 my $files = $self->zilla->files;
53 3   33     97 @$files = grep { not($_->name =~ /^META\.(?:yml|json)$/ and
  18         673  
54             $_->isa('Dist::Zilla::File::OnDisk')) } @$files;
55              
56 3         136 return;
57             } # end prune_files
58             #---------------------------------------------------------------------
59              
60              
61             sub get_prereqs
62             {
63 3     3 1 2275 my ($self, $api_version) = @_;
64              
65 3 100       12 if ($api_version) {
66 1 50       6 $self->log_fatal("api_version $api_version is not supported")
67             unless $api_version == 1;
68 1         1 local $@;
69             $self->log(["WARNING: Dist::Zilla %s does not support api_version %d",
70             Dist::Zilla->VERSION, $api_version ])
71 1 50       2 unless eval { Dist::Zilla::Plugin::MakeMaker->VERSION( 4.300032 ) };
  1         32  
72             }
73              
74             # Get the prerequisites as a hashref:
75 3         154 my $prereqs = $self->extract_keys_as_hash(
76             WriteMakefile => $self->_mmc_write_makefile_args,
77             qw(BUILD_REQUIRES CONFIGURE_REQUIRES PREREQ_PM TEST_REQUIRES)
78             );
79              
80             # If we have TEST_REQUIRES, but the template doesn't understand them,
81             # merge them into BUILD_REQUIRES (if any)
82 3 100 66     22 if ($prereqs->{TEST_REQUIRES} and not $api_version) {
83 2 100       7 if ($prereqs->{BUILD_REQUIRES}) {
84             # have both BUILD_REQUIRES & TEST_REQUIRES, so merge them:
85 1         11 require CPAN::Meta::Requirements;
86 1         33 CPAN::Meta::Requirements->VERSION(2.121);
87             my ($buildreq, $testreq) = map {
88 1         5 CPAN::Meta::Requirements->from_string_hash( $prereqs->{$_} )
  2         222  
89             } qw(BUILD_REQUIRES TEST_REQUIRES);
90              
91 1         142 $buildreq->add_requirements( $testreq );
92              
93 1         96 delete $prereqs->{TEST_REQUIRES};
94 1         5 $prereqs->{BUILD_REQUIRES} = $buildreq->as_string_hash;
95             } else {
96             # no BUILD_REQUIRES, so we can just rename TEST_REQUIRES:
97 1         3 $prereqs->{BUILD_REQUIRES} = delete $prereqs->{TEST_REQUIRES};
98             }
99             } # end if TEST_REQUIRES and $api_version is 0
100              
101 3         54 $self->hash_as_string( $prereqs );
102             } # end get_prereqs
103              
104             #---------------------------------------------------------------------
105              
106              
107             sub get_default
108             {
109 1     1 1 83 my $self = shift;
110              
111 1         51 return $self->extract_keys(WriteMakefile => $self->_mmc_write_makefile_args,
112             @_);
113             } # end get_default
114              
115       3 0   sub add_file {} # Don't let parent class add any files
116              
117             #---------------------------------------------------------------------
118             around setup_installer => sub {
119             my $orig = shift;
120             my $self = shift;
121              
122             my $file = List::Util::first { $_->name eq 'Makefile.PL' }
123             @{ $self->zilla->files }
124             or $self->log_fatal("No Makefile.PL found in dist");
125              
126             my $write_makefile_args = $self->_mmc_write_makefile_args;
127             my $perl_prereq = $write_makefile_args->{MIN_PERL_VERSION};
128             my $share_dir_code = $self->share_dir_code;
129              
130             # Process Makefile.PL through Text::Template:
131             my %data = (
132             dist => $self->zilla->name,
133             meta => $self->zilla->distmeta,
134             plugin => \$self,
135             version => $self->zilla->version,
136             zilla => \$self->zilla,
137             default_args => $write_makefile_args,
138             eumm_version => \($self->eumm_version),
139             perl_prereq => \$perl_prereq,
140             share_dir_code => $share_dir_code,
141             # Recreate share_dir_block for backwards compatibility:
142             share_dir_block => [ $share_dir_code->{preamble} || '',
143             $share_dir_code->{postamble} || '' ],
144             );
145              
146             # The STRICT option hasn't been implemented in a released version of
147             # Text::Template, but you can apply Template_strict.patch. Since
148             # Text::Template ignores unknown options, this code will still work
149             # even if you don't apply the patch; you just won't get strict checking.
150             my %parms = (
151             STRICT => 1,
152             BROKEN => sub { $self->template_error(@_) },
153             );
154              
155             $self->log_debug("Processing Makefile.PL as template");
156             $file->content($self->fill_in_string($file->content, \%data, \%parms));
157              
158             return;
159             }; # end setup_installer
160              
161             sub template_error
162             {
163 0     0 0   my ($self, %e) = @_;
164              
165             # Put the filename into the error message:
166 0           my $err = $e{error};
167 0           $err =~ s/ at template line (?=\d)/ at Makefile.PL line /g;
168              
169 0           $self->log_fatal($err);
170             } # end template_error
171              
172             #---------------------------------------------------------------------
173 2     2   9 no Moose;
  2         7  
  2         14  
174             __PACKAGE__->meta->make_immutable;
175             1;
176              
177             __END__
178              
179             =head1 NAME
180              
181             Dist::Zilla::Plugin::MakeMaker::Custom - Allow a dist to have a custom Makefile.PL
182              
183             =head1 VERSION
184              
185             This document describes version 4.26 of
186             Dist::Zilla::Plugin::MakeMaker::Custom, released August 29, 2015
187             as part of Dist-Zilla-Plugins-CJM version 4.27.
188              
189             =head1 SYNOPSIS
190              
191             In F<dist.ini>:
192              
193             [MakeMaker::Custom]
194             eumm_version = 0.34 ; the default comes from the MakeMaker plugin
195              
196             In your F<Makefile.PL>:
197              
198             use ExtUtils::MakeMaker;
199              
200             ##{ $share_dir_code{preamble} || '' ##}
201              
202             my %args = (
203             NAME => "My::Module",
204             ##{ $plugin->get_default(qw(ABSTRACT AUTHOR LICENSE VERSION)) ##}
205             ##{ $plugin->get_prereqs(1) ##}
206             );
207              
208             unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
209             my $tr = delete $args{TEST_REQUIRES};
210             my $br = $args{BUILD_REQUIRES};
211             for my $mod ( keys %$tr ) {
212             if ( exists $br->{$mod} ) {
213             $br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod};
214             }
215             else {
216             $br->{$mod} = $tr->{$mod};
217             }
218             }
219             } # end unless ExtUtils::MakeMaker is 6.63_03 or newer
220              
221             unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) {
222             my $br = delete $args{BUILD_REQUIRES};
223             my $pp = $args{PREREQ_PM};
224             for my $mod ( keys %$br ) {
225             if ( exists $pp->{$mod} ) {
226             $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod};
227             }
228             else {
229             $pp->{$mod} = $br->{$mod};
230             }
231             }
232             } # end unless ExtUtils::MakeMaker is 6.56 or newer
233              
234             delete $args{CONFIGURE_REQUIRES}
235             unless eval { ExtUtils::MakeMaker->VERSION(6.52) };
236              
237             delete $args{LICENSE}
238             unless eval { ExtUtils::MakeMaker->VERSION(6.31) };
239              
240             WriteMakefile(%args);
241              
242             ##{ $share_dir_code{postamble} || '' ##}
243              
244             Of course, your F<Makefile.PL> doesn't need to look exactly like this.
245             If you increase the minimum version of ExtUtils::MakeMaker, you can
246             remove any C<unless eval> sections whose version test is less than or
247             equal to C<eumm_version>. If you're not using C<share_dir>,
248             you can remove those lines.
249              
250             And if you're not adding your own code to F<Makefile.PL>,
251             you don't need this plugin.
252              
253             =head1 DESCRIPTION
254              
255             This plugin is for people who need something more complex than the
256             auto-generated F<Makefile.PL> or F<Build.PL> generated by the
257             L<MakeMaker|Dist::Zilla::Plugin::MakeMaker> or
258             L<ModuleBuild|Dist::Zilla::Plugin::ModuleBuild> plugins.
259              
260             It is a subclass of the L<MakeMaker plugin|Dist::Zilla::Plugin::MakeMaker>,
261             but it does not write a F<Makefile.PL> for you. Instead, you write your
262             own F<Makefile.PL>, which may do anything L<ExtUtils::MakeMaker> is capable of.
263              
264             This plugin will process F<Makefile.PL> as a template (using
265             L<Text::Template>), which allows you to add data from Dist::Zilla to
266             the version you distribute (if you want). The template delimiters are
267             C<##{> and C<##}>, because that makes them look like comments.
268             That makes it easier to have a F<Makefile.PL> that works both before and
269             after it is processed as a template.
270              
271             This is particularly useful for XS-based modules, because it can allow
272             you to build and test the module without the overhead of S<C<dzil build>>
273             after every small change.
274              
275             The template may use the following variables:
276              
277             =over
278              
279             =item C<%default_args>
280              
281             The hash of arguments for WriteMakefile generated by the normal
282             MakeMaker plugin.
283              
284             =item C<$dist>
285              
286             The name of the distribution.
287              
288             =item C<$eumm_version>
289              
290             The minimum version of ExtUtils::MakeMaker required
291             (from the C<eumm_version> attribute of this plugin).
292              
293             =item C<%meta>
294              
295             The hash of metadata (in META 2 format) that will be stored in F<META.json>.
296              
297             =item C<$perl_prereq>
298              
299             The minimum version of Perl required (from the prerequisites in the metadata).
300             May be C<undef>. Equivalent to C<$default_args{MIN_PERL_VERSION}>.
301              
302             =item C<$plugin>
303              
304             The MakeMaker::Custom object that is processing the template.
305              
306             =item C<%share_dir_code>
307              
308             A hash of strings containing the code for loading
309             C<File::ShareDir::Install> (if it's used by this dist). Put
310             S<C<##{ $share_dir_code{preamble} || '' ##}>> after the
311             S<C<use ExtUtils::MakeMaker>> line, and put
312             S<C<##{ $share_dir_code{postamble} || '' ##}>> after the C<WriteMakefile>
313             call. (You can omit the S<C<|| ''>> if you're sure the dist is using
314             File::ShareDir.
315              
316             For backwards compatibility, this code is also available in the array
317             C<@share_dir_block>, but you should update your templates to use
318             C<%share_dir_code> instead.
319              
320             =item C<$version>
321              
322             The distribution's version number.
323              
324             =item C<$zilla>
325              
326             The Dist::Zilla object that is creating the distribution.
327              
328             =back
329              
330             =head2 Using MakeMaker::Custom with AutoPrereqs
331              
332             If you are using the L<AutoPrereqs|Dist::Zilla::Plugin::AutoPrereqs>
333             plugin, then you will probably want to set its C<configure_finder> to
334             a FileFinder that includes F<Makefile.PL>. You may also want to set
335             this plugin's C<eumm_version> parameter to 0 and allow AutoPrereqs to
336             get the version from your S<C<use ExtUtils::MakeMaker>> line.
337              
338             Example F<dist.ini> configuration:
339              
340             [MakeMaker::Custom]
341             eumm_version = 0 ; AutoPrereqs gets actual version from Makefile.PL
342              
343             [FileFinder::ByName / :MakefilePL]
344             file = Makefile.PL
345              
346             [AutoPrereqs]
347             :version = 4.300005 ; need configure_finder
348             configure_finder = :MakefilePL
349             ; Add next line if your Makefile.PL uses modules you ship in inc/
350             configure_finder = :IncModules
351              
352             Then in your F<Makefile.PL> you'd say:
353              
354             use ExtUtils::MakeMaker 6.32; # or whatever version you need
355              
356             =head1 METHODS
357              
358             =head2 get_default
359              
360             $plugin->get_default(qw(key1 key2 ...))
361              
362             A template can call this method to extract the specified key(s) from
363             the default WriteMakefile arguments created by the normal MakeMaker
364             plugin and have them formatted into a comma-separated list suitable
365             for a hash constructor or a function's parameter list.
366              
367             If any key has no value (or its value is an empty hash or array ref)
368             it will be omitted from the list. If all keys are omitted, the empty
369             string is returned. Otherwise, the result always ends with a comma.
370              
371              
372             =head2 get_prereqs
373              
374             $plugin->get_prereqs($api_version);
375              
376             This is mostly equivalent to
377              
378             $plugin->get_default(qw(BUILD_REQUIRES CONFIGURE_REQUIRES PREREQ_PM
379             TEST_REQUIRES))
380              
381             In other words, it returns all the keys that describe the
382             distribution's prerequisites. The C<$api_version> indicates what keys
383             the template can handle. The currently defined values are:
384              
385             =over 8
386              
387             =item C<0> (or undef)
388             - Fold TEST_REQUIRES into BUILD_REQUIRES. This provides backwards
389             compatibility with older versions of this plugin and Dist::Zilla.
390              
391             =item C<1>
392             - Return TEST_REQUIRES (introduced in ExtUtils::MakeMaker 6.63_03) as
393             a separate key (assuming it's not empty), which requires Dist::Zilla
394             4.300032 or later. Your F<Makefile.PL> should either require
395             ExtUtils::MakeMaker 6.63_03, or fold TEST_REQUIRES into BUILD_REQUIRES
396             if an older version is used (as shown in the SYNOPSIS).
397              
398             =back
399              
400             =head1 SEE ALSO
401              
402             The L<ModuleBuild::Custom|Dist::Zilla::Plugin::ModuleBuild::Custom>
403             plugin does basically the same thing as this plugin, but for
404             F<Build.PL> (if you prefer L<Module::Build>).
405              
406             The L<MakeMaker::Awesome|Dist::Zilla::Plugin::MakeMaker::Awesome>
407             plugin allows you to do similar things to your F<Makefile.PL>, but it
408             works in a very different way. With MakeMaker::Awesome, you subclass
409             the plugin and override the methods that generate F<Makefile.PL>. In
410             my opinion, MakeMaker::Awesome has two disadvantages: it's
411             unnecessarily complex, and it doesn't allow you to build your module
412             without doing C<dzil build>. The only advantage of MakeMaker::Awesome
413             that I can see is that if you had several dists with very similar
414             F<Makefile.PL>s, you could write one subclass of MakeMaker::Awesome
415             and use it in each dist.
416              
417              
418             =for Pod::Coverage
419             add_file
420             prune_files
421             setup_installer
422             template_error
423              
424             =head1 DEPENDENCIES
425              
426             MakeMaker::Custom requires L<Dist::Zilla> (4.300009 or later) and
427             L<Text::Template>. I also recommend applying F<Template_strict.patch>
428             to Text::Template. This will add support for the STRICT option, which
429             will help catch errors in your templates.
430              
431             =head1 INCOMPATIBILITIES
432              
433             You must not use this in conjunction with the
434             L<MakeMaker|Dist::Zilla::Plugin::MakeMaker> or
435             L<MakeMaker::Awesome|Dist::Zilla::Plugin::MakeMaker::Awesome> plugins.
436              
437             =head1 BUGS AND LIMITATIONS
438              
439             No bugs have been reported.
440              
441             =head1 AUTHOR
442              
443             Christopher J. Madsen S<C<< <perl AT cjmweb.net> >>>
444              
445             Please report any bugs or feature requests
446             to S<C<< <bug-Dist-Zilla-Plugins-CJM AT rt.cpan.org> >>>
447             or through the web interface at
448             L<< http://rt.cpan.org/Public/Bug/Report.html?Queue=Dist-Zilla-Plugins-CJM >>.
449              
450             You can follow or contribute to Dist-Zilla-Plugins-CJM's development at
451             L<< https://github.com/madsen/dist-zilla-plugins-cjm >>.
452              
453             =head1 COPYRIGHT AND LICENSE
454              
455             This software is copyright (c) 2015 by Christopher J. Madsen.
456              
457             This is free software; you can redistribute it and/or modify it under
458             the same terms as the Perl 5 programming language system itself.
459              
460             =head1 DISCLAIMER OF WARRANTY
461              
462             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
463             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
464             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
465             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
466             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
467             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
468             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
469             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
470             NECESSARY SERVICING, REPAIR, OR CORRECTION.
471              
472             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
473             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
474             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE
475             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
476             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
477             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
478             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
479             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
480             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
481             SUCH DAMAGES.
482              
483             =cut