File Coverage

blib/lib/Dist/Zilla/Plugin/DynamicPrereqs.pm
Criterion Covered Total %
statement 109 110 99.0
branch 35 44 79.5
condition 9 14 64.2
subroutine 25 25 100.0
pod 0 8 0.0
total 178 201 88.5


line stmt bran cond sub pod time code
1 21     21   52844537 use strict;
  21         101  
  21         768  
2 21     21   127 use warnings;
  21         53  
  21         1474  
3             package Dist::Zilla::Plugin::DynamicPrereqs; # git description: v0.037-6-gfad5320
4             # vim: set ts=8 sts=2 sw=2 tw=100 et :
5             # ABSTRACT: Specify dynamic (user-side) prerequisites for your distribution
6             # KEYWORDS: plugin distribution metadata MYMETA prerequisites Makefile.PL dynamic
7              
8             our $VERSION = '0.038';
9              
10 21     21   3527 use Moose;
  21         2861119  
  21         187  
11             with
12             'Dist::Zilla::Role::FileGatherer',
13             'Dist::Zilla::Role::ModuleMetadata',
14             'Dist::Zilla::Role::FileMunger',
15             'Dist::Zilla::Role::MetaProvider',
16             'Dist::Zilla::Role::PrereqSource',
17             'Dist::Zilla::Role::AfterBuild',
18             'Dist::Zilla::Role::TextTemplate',
19             ;
20 21     21   154337 use List::Util 1.45 qw(first notall any uniq);
  21         669  
  21         2201  
21 21     21   171 use Module::Runtime 'module_notional_filename';
  21         53  
  21         182  
22 21     21   1171 use Try::Tiny;
  21         55  
  21         1411  
23 21     21   1193 use Path::Tiny;
  21         12019  
  21         1229  
24 21     21   4597 use File::ShareDir;
  21         135573  
  21         1269  
25 21     21   3456 use namespace::autoclean;
  21         50642  
  21         239  
26 21     21   16819 use Term::ANSIColor 3.00 'colored';
  21         173387  
  21         71606  
27              
28             has raw => (
29             isa => 'ArrayRef[Str]',
30             traits => ['Array'],
31             handles => { raw => 'elements' },
32             lazy => 1,
33             default => sub {
34             my $self = shift;
35              
36             my @lines;
37             if (my $filename = $self->raw_from_file)
38             {
39             my $file = first { $_->name eq $filename } @{ $self->zilla->files };
40             $self->log_fatal([ 'no such file in build: %s' ], $filename) if not $file;
41             $self->zilla->prune_file($file);
42             try {
43             @lines = split(/\n/, $file->content);
44             }
45             catch {
46             $self->log_fatal($_);
47             };
48             }
49              
50             $self->log('no content found in -raw/-body!') if not @lines;
51             return \@lines;
52             },
53             );
54              
55             has raw_from_file => (
56             is => 'ro', isa => 'Str',
57             );
58              
59             has $_ => (
60             isa => 'ArrayRef[Str]',
61             traits => ['Array'],
62             handles => { $_ => 'elements' },
63             lazy => 1,
64             default => sub { [] },
65             ) foreach qw(include_subs conditions);
66              
67 25     25 0 10619234 sub mvp_multivalue_args { qw(raw include_subs conditions) }
68              
69             sub mvp_aliases { +{
70 25     25 0 4126 '-raw' => 'raw',
71             '-delimiter' => 'delimiter',
72             '-raw_from_file' => 'raw_from_file',
73             '-include_sub' => 'include_subs',
74             '-condition' => 'conditions',
75             '-body' => 'raw',
76             '-body_from_file' => 'raw_from_file',
77             'body_from_file' => 'raw_from_file',
78             } }
79              
80             around BUILDARGS => sub
81             {
82             my $orig = shift;
83             my $class = shift;
84              
85             my $args = $class->$orig(@_);
86              
87             my $delimiter = delete $args->{delimiter};
88             if (defined $delimiter and length($delimiter))
89             {
90             s/^\Q$delimiter\E// foreach @{$args->{raw}};
91             }
92              
93             return $args;
94             };
95              
96             sub BUILD
97             {
98 25     25 0 90 my ($self, $args) = @_;
99              
100             $self->log_fatal('[MakeMaker::Awesome] must be at least version 0.19 to be used with [DynamicPrereqs]')
101             if $INC{module_notional_filename('Dist::Zilla::Plugin::MakeMaker::Awesome')}
102 25 50 33     157 and not eval { Dist::Zilla::Plugin::MakeMaker::Awesome->VERSION('0.19') };
  0         0  
103              
104 25         905 my %extra_args = %$args;
105 25         199 delete @extra_args{ map $_->name, $self->meta->get_all_attributes };
106 25 100       4513 if (my @keys = keys %extra_args)
107             {
108 1 50       14 $self->log('Warning: unrecognized argument' . (@keys > 1 ? 's' : '')
109             . ' (' . join(', ', @keys) . ') passed. Perhaps you need to upgrade?');
110             }
111             }
112              
113             around dump_config => sub
114             {
115             my ($orig, $self) = @_;
116             my $config = $self->$orig;
117              
118             my $data = {
119             blessed($self) ne __PACKAGE__ ? ( version => $VERSION ) : (),
120             };
121             $config->{+__PACKAGE__} = $data if keys %$data;
122              
123             return $config;
124             };
125              
126 20     20 0 296990 sub metadata { return +{ dynamic_config => 1 } }
127              
128             sub after_build
129             {
130 20     20 0 536711 my $self = shift;
131             $self->log_fatal('Build.PL detected - dynamic prereqs will not be added to it!')
132 20 100   71   159 if first { $_->name eq 'Build.PL' } @{ $self->zilla->files };
  71         3365  
  20         864  
133             }
134              
135             # track which subs have already been included by some other instance
136             my %included_subs;
137              
138             sub munge_files
139             {
140 23     23 0 54017 my $self = shift;
141              
142 23     78   181 my $file = first { $_->name eq 'Makefile.PL' } @{$self->zilla->files};
  78         3599  
  23         829  
143 23 100       1198 $self->log_fatal('No Makefile.PL found! Is [MakeMaker] at least version 5.022?') if not $file;
144              
145 21         152 my $content = $file->content;
146              
147 21         1824 $self->log_debug('Inserting dynamic prereq into Makefile.PL...');
148              
149             # we insert our code just *before* this bit in Makefile.PL
150 21         7531 my $insertion_breadcrumb = "\n\nunless ( eval { ExtUtils::MakeMaker";
151              
152             # insert after declarations for BOTH %WriteMakefileArgs, %FallbackPrereqs.
153             # TODO: if marker cannot be found, fall back to looking for just
154             # %WriteMakefileArgs -- this requires modifying the content too.
155 21 50       531 $self->log_fatal('failed to find position in Makefile.PL to munge!')
156             if $content !~ m/\Q$insertion_breadcrumb/mg;
157              
158 21         99 my $pos = pos($content) - length($insertion_breadcrumb);
159              
160 21         1148 my $code = join("\n", $self->raw);
161 21 100       931 if (my $conditions = join(' && ', $self->conditions))
162             {
163 5         34 $code = "if ($conditions) {\n"
164             . $code . "\n"
165             . '}' . "\n";
166             }
167              
168 21         906 $content = substr($content, 0, $pos)
169             . "\n"
170             . $self->_header . "\n"
171             . $code . "\n"
172             . substr($content, $pos);
173              
174 21         364 $content =~ s/\n+\z/\n/;
175              
176 21         873 $content .= $self->_sub_definitions;
177              
178 20         141 $file->content($content);
179 20         5749 return;
180             }
181              
182             has _header => (
183             is => 'ro', isa => 'Str',
184             lazy => 1,
185             default => sub {
186             my $self = shift;
187             '# inserted by ' . blessed($self) . ' ' . $self->VERSION;
188             },
189             );
190              
191             has _sub_definitions => (
192             is => 'ro', isa => 'Str',
193             lazy => 1, builder => '_build__sub_definitions',
194             );
195              
196             sub _build__sub_definitions
197             {
198 21     21   68 my $self = shift;
199              
200 21         996 my @include_subs = grep +(not exists $included_subs{$_}), $self->_all_required_subs;
201 21 100       426 return '' if not @include_subs;
202              
203 11         30 my $content;
204 11 100       426 $content .= "\n" . $self->_header if not keys %included_subs;
205              
206 11 100       422 if (my @missing_subs = grep !-f path($self->_include_sub_root, $_), @include_subs)
207             {
208 1 50       87 $self->log_fatal(
209             @missing_subs > 1
210             ? [ 'no definitions available for subs %s!', join(', ', map "'".$_."'", @missing_subs) ]
211             : [ 'no definition available for sub \'%s\'!', $missing_subs[0] ]
212             );
213             }
214              
215             # On consultation with ribasushi I agree that we cannot let authors
216             # use some sub definitions without copious danger tape.
217 10         720 $self->_warn_include_subs(@include_subs);
218              
219 10         1974 my @sub_definitions = map path($self->_include_sub_root, $_)->slurp_utf8, @include_subs;
220 10         2629 $content .= "\n"
221             . $self->fill_in_string(
222             join("\n", @sub_definitions),
223             {
224             dist => \($self->zilla),
225             plugin => \$self,
226             },
227             );
228 10         11914 @included_subs{@include_subs} = (() x @include_subs);
229              
230 10         579 return $content;
231             }
232              
233              
234             my %sub_prereqs = (
235             can_cc => {
236             'Config' => '0', # core since perl 5.00307
237             },
238             can_run => {
239             'File::Spec' => '0', # core since perl 5.00405
240             'Config' => '0', # core since perl 5.00307
241             },
242             parse_args => {
243             'Text::ParseWords' => '0', # core since perl 5.000
244             },
245             has_module => {
246             'Module::Metadata' => '0', # core since perl 5.013009
247             'CPAN::Meta::Requirements' => '2.120620', # core since perl 5.015007
248             },
249             is_miniperl => {
250             'DynaLoader' => '0', # core since perl 5.000
251             },
252             );
253              
254             # instead of including these dependencies in configure-requires, we inline
255             # them right into the distribution in inc/.
256             my %sub_inc_dependencies = (
257             can_xs => {
258             'ExtUtils::HasCompiler' => '0.014',
259             },
260             );
261              
262             sub gather_files {
263 25     25 0 1971250 my $self = shift;
264              
265 25         1238 foreach my $required_sub ($self->_all_required_subs)
266             {
267             # FIXME: update %included_subs earlier to account for other coexisting
268             # plugins, or running two instances of the plugin will try to do this twice.
269 32   100     151 my $include_modules = $sub_inc_dependencies{$required_sub} || {};
270 32         142 foreach my $module (keys %$include_modules)
271             {
272 3         14 (my $path = $module) =~ s{::}{/}g;
273 3         12 $path = path('inc', $path . '.pm');
274 3         106 my $cpath = $path->canonpath;
275              
276 3 50   12   23 my $file = first { $_->name eq $path or $_->name eq $cpath } @{ $self->zilla->files };
  12         950  
  3         112  
277 3 50       392 if (not $file)
278             {
279 3         27 $self->log([ 'inlining %s into inc/', $module ]);
280 3 100       1037 my $installed_filename = Module::Metadata->find_module_by_name($module)
281             or $self->log_fatal([ 'Can\'t locate %s', $module ]);
282              
283 2         758 $file = Dist::Zilla::File::OnDisk->new({ name => $installed_filename });
284 2         665 $file->name($path->stringify);
285 2         613 $self->add_file($file);
286             }
287 2 50       1254 $self->log_fatal([ 'failed to find %s in files', $module ]) if not $file;
288              
289 2 50 33     24 if (defined $include_modules->{$module} and $include_modules->{$module} > 0)
290             {
291             # check that the file we got actually satisfies our dependency
292 2         16 my $mmd = $self->module_metadata_for_file($file);
293             $self->log_fatal([ '%s version %s required--only found version %s',
294             $module, $include_modules->{$module},
295             (defined $mmd->version ? $mmd->version->stringify : 'undef') ])
296 2 50 50     7900 if ($mmd->version || 0) < $include_modules->{$module};
    100          
297             }
298             }
299             }
300             }
301              
302             sub register_prereqs
303             {
304 20     20 0 42488 my $self = shift;
305 20         987 foreach my $required_sub ($self->_all_required_subs)
306             {
307 27   100     149 my $configure_prereqs = $sub_prereqs{$required_sub} || {};
308 27 100       302 $self->zilla->register_prereqs(
309             {
310             phase => 'configure',
311             type => 'requires',
312             },
313             %$configure_prereqs,
314             ) if %$configure_prereqs;
315              
316 27   100     1766 my $develop_prereqs = $sub_inc_dependencies{$required_sub} || {};
317 27 100       128 $self->zilla->register_prereqs(
318             {
319             phase => 'develop',
320             type => 'requires',
321             },
322             %$develop_prereqs,
323             ) if %$develop_prereqs;
324             }
325             }
326              
327             has _include_sub_root => (
328             is => 'ro', isa => 'Str',
329             lazy => 1,
330             default => sub {
331             my $self = shift;
332             path(File::ShareDir::module_dir($self->meta->name), 'include_subs')->stringify;
333             },
334             );
335              
336             # indicates subs that require other subs to be included
337             my %sub_dependencies = (
338             can_cc => [ qw(can_run) ],
339             can_run => [ qw(maybe_command) ],
340             requires => [ qw(runtime_requires) ],
341             runtime_requires => [ qw(_add_prereq) ],
342             build_requires => [ qw(_add_prereq) ],
343             test_requires => [ qw(_add_prereq) ],
344             want_pp => [ qw(parse_args) ],
345             );
346              
347             has _all_required_subs => (
348             isa => 'ArrayRef[Str]',
349             traits => ['Array'],
350             handles => { _all_required_subs => 'elements' },
351             lazy => 1,
352             default => sub {
353             my $self = shift;
354             my @code = ($self->conditions, $self->raw);
355             my @subs_in_code = !@code ? () :
356             grep {
357             my $sub_name = $_;
358             any { /\b$sub_name\b\(/ } @code
359             } map $_->basename, path($self->_include_sub_root)->children;
360              
361             [ sort($self->_all_required_subs_for(uniq(
362             $self->include_subs, @subs_in_code,
363             ))) ];
364             },
365             );
366              
367             my %required_subs;
368             sub _all_required_subs_for
369             {
370 36     36   1392 my ($self, @subs) = @_;
371              
372 36         166 @required_subs{@subs} = (() x @subs);
373              
374 36         133 foreach my $sub (@subs)
375             {
376 31 100       63 my @subs = @{ $sub_dependencies{$sub} || [] };
  31         301  
377             $self->_all_required_subs_for(@subs)
378 31 100   16   313 if notall { exists $required_subs{$_} } @subs;
  16         95  
379             }
380              
381 36         1396 return keys %required_subs;
382             }
383              
384             my %warn_include_sub = (
385             can_xs => 1,
386             can_cc => 1,
387             can_run => 1,
388             );
389              
390             sub _warn_include_subs
391             {
392 10     10   64 my ($self, @include_subs) = @_;
393              
394             $self->log(colored('Use ' . $_ . ' with great care! Please consult the documentation!', 'bright_yellow'))
395 10         111 foreach grep exists $warn_include_sub{$_}, @include_subs;
396             }
397              
398             __PACKAGE__->meta->make_immutable;
399              
400             __END__
401              
402             =pod
403              
404             =encoding UTF-8
405              
406             =head1 NAME
407              
408             Dist::Zilla::Plugin::DynamicPrereqs - Specify dynamic (user-side) prerequisites for your distribution
409              
410             =head1 VERSION
411              
412             version 0.038
413              
414             =head1 SYNOPSIS
415              
416             In your F<dist.ini>:
417              
418             [DynamicPrereqs]
419             -condition = has_module('Role::Tiny')
420             -condition = !want_pp()
421             -condition = can_xs()
422             -body = requires('Role::Tiny', '1.003000')
423              
424             or:
425              
426             [DynamicPrereqs]
427             -delimiter = |
428             -raw = |test_requires('Devel::Cover')
429             -raw = | if $ENV{EXTENDED_TESTING} or is_smoker();
430              
431             or:
432              
433             [DynamicPrereqs]
434             -raw_from_file = Makefile.args # code snippet in this file
435              
436             =head1 DESCRIPTION
437              
438             This is a L<Dist::Zilla> plugin that inserts code into your F<Makefile.PL> to
439             indicate dynamic (installer-side) prerequisites.
440              
441             Code is inserted immediately after the declarations for C<%WriteMakefileArgs>
442             and C<%FallbackPrereqs>, before they are conditionally modified (when an older
443             L<ExtUtils::MakeMaker> is installed). This gives you an opportunity to add to
444             the C<WriteMakefile> arguments: C<PREREQ_PM>, C<BUILD_REQUIRES>, and
445             C<TEST_REQUIRES>, and therefore modify the prerequisites in the user's
446             F<MYMETA.yml> and F<MYMETA.json> based on conditions found on the user's system.
447              
448             The C<dynamic_config> field in L<metadata|CPAN::Meta::Spec/dynamic_config> is
449             already set for you.
450              
451             =for stopwords usecase
452              
453             You could potentially use this plugin for performing other modifications in
454             F<Makefile.PL> other than user-side prerequisite modifications, but I can't
455             think of a situation where this makes sense. Contact me if you have any ideas!
456              
457             Only F<Makefile.PL> modification is supported at this time. This author
458             considers the use of L<Module::Build> to be questionable in all circumstances,
459             and L<Module::Build::Tiny> does not (yet?) support dynamic configuration.
460              
461             =head1 BE VIGILANT!
462              
463             You are urged to check the generated F<Makefile.PL> for sanity, and to run it
464             at least once to validate its syntax. Although every effort is made to
465             generate valid and correct code, mistakes can happen, so verification is
466             needed before shipping.
467              
468             Please also see the other warnings later in this document.
469              
470             =head1 CONFIGURATION OPTIONS
471              
472             =head2 C<-raw>
473              
474             =head2 C<-body>
475              
476             The code to be inserted; must be valid and complete perl statements. You can
477             reference and modify the already-declared C<%WriteMakefileArgs> and
478             C<%FallbackPrereqs> variables, as inserted into F<Makefile.PL> by
479             L<Dist::Zilla::Plugin::MakeMaker> and subclasses (e.g.
480             L<Dist::Zilla::Plugin::MakeMaker::Awesome> since L<Dist::Zilla> C<5.001>.
481              
482             This option can be used more than once; lines are added in the order in which they are provided.
483              
484             If you use external libraries in the code you are inserting, you B<must> add
485             these modules to C<configure_requires> prereqs in metadata (e.g. via
486             C<[Prereqs / ConfigureRequires]> in your F<dist.ini>).
487              
488             C<-body> first became available in version 0.018.
489              
490             =for Pod::Coverage mvp_multivalue_args mvp_aliases BUILD metadata after_build munge_files register_prereqs gather_files
491              
492             =head2 C<-delimiter>
493              
494             (Available since version 0.007)
495              
496             A string, usually a single character, which is stripped from the beginning of
497             all C<-raw>/C<-body> lines. This is because the INI file format strips all leading
498             whitespace from option values, so including this character at the front allows
499             you to use leading whitespace in an option string, so you can indent blocks of
500             code properly.
501              
502             =head2 C<-raw_from_file>
503              
504             (Available since version 0.010)
505              
506             =head2 C<-body_from_file>
507              
508             (Available since version 0.018)
509              
510             A filename that contains the code to be inserted; must be valid and complete
511             perl statements, as with C<-raw>/C<-body> above. This file must be part of the build,
512             but it is pruned from the built distribution.
513              
514             =head2 C<-condition>
515              
516             (Available since version 0.014)
517              
518             =for stopwords ANDed
519              
520             A perl expression to be included in the condition statement in the
521             F<Makefile.PL>. Multiple C<-condition>s can be provided, in which case they
522             are ANDed together to form the final condition statement. (You must
523             appropriately parenthesize each of your conditions to ensure correct order of
524             operations.) Any use of recognized subroutines will cause their definitions
525             to be included automatically (see L<AVAILABLE SUBROUTINE DEFINITIONS>, below).
526              
527             When combined with C<-raw>/C<-body> lines, the condition is placed first in a C<if>
528             statement, and the C<-raw>/C<-body> lines are contained as the body of the block. For example:
529              
530             [DynamicPrereqs]
531             -condition = "$]" > '5.020'
532             -body = requires('Role::Tiny', '1.003000')
533              
534             results in the F<Makefile.PL> snippet (note that whitespace is not added, in
535             case this affects the parsing:
536              
537             if ("$]" > '5.020') {
538             requires('Role::Tiny', '1.003000')
539             }
540              
541             =head2 C<-include_sub>
542              
543             (Available since version 0.010; rendered unnecessary in 0.016 (all definitions
544             are now included automatically, when used).
545              
546             =head1 AVAILABLE SUBROUTINE DEFINITIONS
547              
548             A number of helper subroutines are available for use within your code inserted
549             via C<-body>, C<-body_from_file>, C<-raw>, C<-raw_from_file>, or C<-condition> clauses. When used, their
550             definition(s) will be included automatically in F<Makefile.PL> (as well as
551             those of any other subroutines I<they> call); necessary prerequisite modules
552             will be added to C<configure requires> metadata.
553              
554             Unless otherwise noted, these all became available in version 0.010.
555             Available subs are:
556              
557             =over 4
558              
559             =item *
560              
561             C<prompt_default_yes($message)> - takes a string (appending "[Y/n]" to it), returns a boolean; see L<ExtUtils::MakeMaker/prompt>
562              
563             =item *
564              
565             C<prompt_default_no($message)> - takes a string (appending "[y/N]" to it), returns a boolean; see L<ExtUtils::MakeMaker/prompt>
566              
567             =item *
568              
569             C<parse_args()> - returns the hashref of options that were passed as arguments to C<perl Makefile.PL>
570              
571             =item *
572              
573             C<can_xs()> - XS capability testing via L<ExtUtils::HasCompiler> (don't forget to also check C<want_pp>!) Available in this form since 0.029.
574              
575             =item *
576              
577             C<can_cc()> - can we locate a (the) C compiler
578              
579             =item *
580              
581             C<can_run()> - check if we can run some command
582              
583             =item *
584              
585             C<is_miniperl()> - returns true if the current perl is miniperl (this may affect your ability to run XS code) Available since 0.033.
586              
587             =item *
588              
589             C<can_use($module [, $version ])> - checks if a module (optionally, at a specified version) can be loaded. (If you don't want to load the module, you should use C<< has_module >>, see below.)
590              
591             =for stopwords backcompat
592              
593             =item *
594              
595             C<has_module($module [, $version_or_range ])> - checks if a module (optionally, at a specified version or matching a L<version range|CPAN::Meta::Spec/version_ranges>) is available in C<%INC>. Does not load the module, so is safe to use with modules that have side effects when loaded. When passed a second argument, returns true or false; otherwise, returns undef or the module's C<$VERSION>. Note that for extremely simple usecases (module has no side effects when loading, and no explicit version is needed), it can be simpler and more backcompat-friendly to simply do: C<< eval { require Foo::Bar } >>. (Current API available since version 0.015.)
596              
597             =item *
598              
599             C<is_smoker()> - is the installation on a smoker machine?
600              
601             =item *
602              
603             C<is_interactive()> - is the installation in an interactive terminal?
604              
605             =item *
606              
607             C<is_trial()> - is the release a -TRIAL or _XXX-versioned release?
608              
609             =item *
610              
611             C<is_os($os, ...)> - true if the OS is any of those listed
612              
613             =item *
614              
615             C<isnt_os($os, ...)> - true if the OS is none of those listed
616              
617             =item *
618              
619             C<maybe_command> - actually a monkeypatch to C<< MM->maybe_command >> (please keep using the fully-qualified form) to work in Cygwin
620              
621             =item *
622              
623             C<runtime_requires($module [, $version ])> - adds the module to runtime prereqs (as a shorthand for editing the hashes in F<Makefile.PL> directly). Added in 0.016.
624              
625             =item *
626              
627             C<requires($module [, $version ])> - alias for C<runtime_requires>. Added in 0.016.
628              
629             =item *
630              
631             C<build_requires($module [, $version ])> - adds the module to build prereqs (as a shorthand for editing the hashes in F<Makefile.PL> directly). Added in 0.016.
632              
633             =item *
634              
635             C<test_requires($module [, $version ])> - adds the module to test prereqs (as a shorthand for editing the hashes in F<Makefile.PL> directly). Added in 0.016.
636              
637             =item *
638              
639             C<want_pp> - true if the user or CPAN client explicitly specified PUREPERL_ONLY (indicating that no XS-requiring modules or code should be installed)
640              
641             =back
642              
643             =head1 WARNING: INCOMPLETE SUBROUTINE IMPLEMENTATIONS!
644              
645             The implementations for some subroutines (in particular, C<can_xs>, C<can_cc>
646             and C<can_run> are still works in progress, incompatible with some architectures and
647             cannot yet be considered a suitable generic solution. Until we are more
648             confident in their implementations, a warning will be printed (to the distribution author)
649             upon use, and
650             their use B<is not advised> without prior consultation with the author and
651             other members of the Perl Toolchain Gang
652             (see L<C<#toolchain> on C<irc.perl.org>|irc://irc.perl.org/#toolchain>).
653              
654             =head1 WARNING: UNSTABLE API!
655              
656             =for stopwords DarkPAN metacpan
657              
658             This plugin is still undergoing active development, and the interfaces B<will>
659             change and grow as I work through the proper way to do various things. As I
660             make changes, I will be using
661             L<metacpan's reverse dependencies list|https://metacpan.org/requires/distribution/Dist-Zilla-Plugin-DynamicPrereqs>
662             and L<http://grep.cpan.me> to find and fix any
663             upstream users, but I obviously cannot do this for DarkPAN users. Regardless,
664             please contact me (see below) and I will keep you directly advised of
665             interface changes.
666              
667             Future planned features:
668              
669             =for stopwords CPANFile
670              
671             =over 4
672              
673             =item *
674              
675             better compiler detection and conditional XS code inclusion
676              
677             =item *
678              
679             interoperability with the L<[CPANFile]|Dist::Zilla::Plugin::CPANFile> plugin (generation of dynamic prerequisites into a F<cpanfile>)
680              
681             =item *
682              
683             something like C<is_perl_at_least('5.008001')> for testing C<$]>
684              
685             =item *
686              
687             inlining of sub content for some checks, to allow constant folding (e.g. C<$^O> and C<$]> checks)
688              
689             =back
690              
691             =head1 LIMITATIONS
692              
693             It is not possible, given the current features of L<ExtUtils::MakeMaker>, to have dynamic prerequisites using the
694             C<recommends>, C<suggests> or C<conflicts> types. (This is because these get added via the C<META_ADD> or
695             C<META_MERGE> Makefile arguments, and these are ignored for the generation of F<MYMETA.json>.)
696              
697             =head1 SEE ALSO
698              
699             =over 4
700              
701             =item *
702              
703             L<Dist::Zilla::Plugin::MakeMaker>
704              
705             =item *
706              
707             L<ExtUtils::MakeMaker/Using Attributes and Parameters>
708              
709             =item *
710              
711             L<Dist::Zilla::Plugin::OSPrereqs>
712              
713             =item *
714              
715             L<Dist::Zilla::Plugin::PerlVersionPrereqs>
716              
717             =item *
718              
719             L<Module::Install::Can>
720              
721             =back
722              
723             =head1 SUPPORT
724              
725             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Dist-Zilla-Plugin-DynamicPrereqs>
726             (or L<bug-Dist-Zilla-Plugin-DynamicPrereqs@rt.cpan.org|mailto:bug-Dist-Zilla-Plugin-DynamicPrereqs@rt.cpan.org>).
727              
728             There is also a mailing list available for users of this distribution, at
729             L<http://dzil.org/#mailing-list>.
730              
731             There is also an irc channel available for users of this distribution, at
732             L<C<#distzilla> on C<irc.perl.org>|irc://irc.perl.org/#distzilla>.
733              
734             I am also usually active on irc, as 'ether' at C<irc.perl.org> and C<irc.freenode.org>.
735              
736             =head1 AUTHOR
737              
738             Karen Etheridge <ether@cpan.org>
739              
740             =head1 CONTRIBUTOR
741              
742             =for stopwords Graham Ollis
743              
744             Graham Ollis <plicease@cpan.org>
745              
746             =head1 COPYRIGHT AND LICENCE
747              
748             This software is copyright (c) 2014 by Karen Etheridge.
749              
750             This is free software; you can redistribute it and/or modify it under
751             the same terms as the Perl 5 programming language system itself.
752              
753             =cut