File Coverage

blib/lib/Distribution/Guess/BuildSystem.pm
Criterion Covered Total %
statement 142 144 98.6
branch 71 74 95.9
condition 15 15 100.0
subroutine 53 53 100.0
pod 37 37 100.0
total 318 323 98.4


line stmt bran cond sub pod time code
1             package Distribution::Guess::BuildSystem;
2 12     12   15976 use strict;
  12         33  
  12         376  
3              
4 12     12   74 use warnings;
  12         26  
  12         362  
5 12     12   67 no warnings;
  12         25  
  12         514  
6              
7 12     12   6620 use subs qw();
  12         320  
  12         362  
8 12     12   83 use vars qw($VERSION);
  12         30  
  12         704  
9              
10 12     12   107 use Carp qw(carp);
  12         29  
  12         695  
11 12     12   83 use Config qw(%Config);
  12         25  
  12         598  
12 12     12   80 use Cwd qw(cwd);
  12         27  
  12         626  
13 12     12   5937 use File::Spec::Functions qw(catfile);
  12         9839  
  12         826  
14              
15 12     12   6351 use Module::Extract::VERSION;
  12         20304  
  12         26701  
16              
17             $VERSION = '1.002';
18              
19             =encoding utf8
20              
21             =head1 NAME
22              
23             Distribution::Guess::BuildSystem - Guess what this distribution uses to build itself
24              
25             =head1 SYNOPSIS
26              
27             use Distribution::Guess::BuildSystem;
28              
29             chdir $dist_dir;
30              
31             my $guesser = Distribution::Guess::BuildSystem->new(
32             dist_dir => $dir
33             );
34              
35             my $build_files = $guesser->build_files; # Hash ref
36              
37             my $build_pl = $guesser->has_build_pl;
38             my $makefile_pl = $guesser->has_makefile_pl;
39              
40             my $both = $guesser->has_build_and_makefile;
41              
42             my $build_command = $guesser->build_commands; # Hash ref
43              
44             if( $guesser->uses_module_install ) {
45             my $version = $guesser->module_install_version;
46             my $pita = $guesser->uses_auto_install;
47             }
48              
49             if( $guesser->uses_makemaker ) {
50             my $version = $guesser->makemaker_version;
51             my $make = $guesser->make_command;
52             }
53              
54             =head1 DESCRIPTION
55              
56             There are three major build system for Perl distributions:
57              
58             =over 4
59              
60             =item * ExtUtils::MakeMaker
61              
62             Uses F and C.
63              
64             =item * Module::Build
65              
66             Uses F and C, although it might have a F that is
67             a wrapper.
68              
69             =item * Module::Install
70              
71             Uses F and calls to an embedded C. It might
72             use C to call C at build time.
73              
74             =back
75              
76             The trick is to figure out which one you are supposed to use. This module has
77             several methods to look at a distribution and guess what its build system is.
78             The main object is simply some settings. Every time you want to ask a
79             question about the distribution, the object looks at the distribution. That is,
80             it doesn't capture the information when you create the object.
81              
82             =head2 Methods
83              
84             =over 4
85              
86             =item new
87              
88             Creates a new guesser object. You can set:
89              
90             dist_dir - the distribution directory (where the build file is)
91             perl_binary - the path to the perl you want to use
92             prefer_module_build - some methods will return the preferred builder
93             prefer_makemaker - some methods will return the preferred builder
94              
95             If you prefer
96             The defaults are:
97              
98             dist_dir - current working directory
99             perl_binary - $^X (may be relative and no longer in path!)
100             prefer_module_build - true
101             prefer_makemaker - false
102              
103             =cut
104              
105             sub new {
106 17     17 1 70556 my %defaults = (
107             dist_dir => cwd(),
108             prefer_module_build => 1,
109             prefer_makemaker => 0,
110             perl_binary => $^X,
111             );
112              
113 17         525 my( $class, %args ) = @_;
114              
115 17         757 bless { %defaults, %args }, $class;
116             }
117              
118             =item dist_dir( [ DIR ] )
119              
120             Returns or sets the distribution directory.
121              
122             =cut
123              
124             sub dist_dir {
125 581     581 1 1276 my( $self ) = shift;
126 581         1577 $self->_setting( 'dist_dir', @_ );
127             }
128              
129             =item perl_binary( [PERL] )
130              
131             Returns or sets the perl binary path. This is either the one that you set
132             or the value of C<$^X>. There's no check to verify that this is actually
133             a perl binary.
134              
135             =cut
136              
137             sub perl_binary {
138 4     4 1 17 my( $self ) = shift;
139 4         20 $self->_setting( 'perl_binary', @_ );
140             }
141              
142             =item prefer_makemaker( [TRUE|FALSE] )
143              
144             Returns or sets the Module::Build preference. If this is true, some of
145             the methods preferentially return answers for Module::Build over
146             MakeMaker when a distribution can use both systems. If both
147             C and C are true, then
148             MakeMaker wins.
149             =cut
150              
151             sub prefer_makemaker {
152 8     8 1 29 my( $self ) = shift;
153 8         40 $self->_setting( 'prefer_makemaker', @_ );
154             }
155              
156             =item prefer_module_build( [TRUE|FALSE] )
157              
158             Returns or sets the Module::Build preference. If this is true, some of
159             the methods preferentially return answers for Module::Build over
160             MakeMaker when a distribution can use both systems. If both
161             C and C are true, then
162             MakeMaker wins.
163              
164             =cut
165              
166             sub prefer_module_build {
167 17     17 1 50 my( $self ) = shift;
168 17         55 $self->_setting( 'prefer_module_build', @_ );
169             }
170              
171             sub _setting {
172 613     613   1523 my( $self, $key, $value ) = @_;
173              
174 613 100       1700 if( @_ == 3 ) {
175 3         14 $self->{$key} = $value;
176             }
177              
178 613         6545 return $self->{$key};
179             }
180              
181             =back
182              
183             =head2 Questions about the distribution
184              
185             =over 4
186              
187             =item build_files
188              
189             Returns an hash reference of build files found in the distribution. The
190             keys are the filenames of the build files. The values
191              
192             =cut
193              
194             {
195             my @files = (
196             [ qw( has_makefile_pl makefile_pl ) ],
197             [ qw( has_build_pl build_pl ) ],
198              
199             );
200              
201             sub build_files {
202 20     20 1 13673 my %found;
203              
204 20         118 foreach my $pairs ( @files ) {
205 40         219 my( $check, $file ) = @$pairs;
206 40 100       263 $found{ $_[0]->$file() } = $_[0]->$file() if $_[0]->$check()
207             }
208              
209 20         139 return \%found;
210             }
211             }
212              
213             =item preferred_build_file
214              
215             Returns the build file that you should use, even if there is more than
216             one. Right now this is simple:
217              
218             1. In the single build file distributions, return that build file
219              
220             2. If you've specified a preference with C or
221             C, use that.
222              
223             3. If there is no preference (both are false), prefer C.
224              
225             4. If no of those work, return nothing.
226              
227             =cut
228              
229             sub preferred_build_file {
230             # preference doesn't matter in single build system cases
231 32 100   32 1 7703 return $_[0]->makefile_pl if $_[0]->uses_makemaker_only;
232 19 100       120 return $_[0]->build_pl if $_[0]->uses_module_build_only;
233              
234             # preference now matter
235 13 100 100     66 return $_[0]->build_pl if(
236             $_[0]->prefer_module_build and $_[0]->uses_module_build );
237 8 100 100     152861 return $_[0]->makefile_pl if(
238             $_[0]->prefer_makemaker and $_[0]->uses_makemaker );
239              
240             # absence of preference
241 6 100       34 return $_[0]->build_pl if $_[0]->uses_module_build;
242 5 100       7716 return $_[0]->makefile_pl if $_[0]->uses_makemaker;
243              
244             # no build system?
245 2         10 return;
246             }
247              
248             =item preferred_build_command
249              
250             Returns the build command that you should use. This uses the logic of
251             C. It returns the result of either C
252             or C.
253              
254             =cut
255              
256             sub preferred_build_command {
257 17 100   17 1 109 return $_[0]->build_command if $_[0]->preferred_build_file eq $_[0]->build_pl;
258 8 100       44 return $_[0]->make_command if $_[0]->preferred_build_file eq $_[0]->makefile_pl;
259 1         15 return;
260             }
261              
262             =item build_file_paths
263              
264             Returns an anonymous hash to the paths to the build files, based on
265             the dist_dir argument to C and the return value of
266             C. The keys are the file names and the values are
267             the paths.
268              
269             =cut
270              
271             sub build_file_paths {
272 10     10 1 10591 my %paths;
273              
274 10         37 foreach my $file ( keys %{ $_[0]->build_files } ) {
  10         97  
275 12         70 $paths{$file} = File::Spec->catfile( $_[0]->dist_dir, $file );
276             }
277              
278 10         68 return \%paths;
279             }
280              
281             =item makefile_pl_path
282              
283             =cut
284              
285             sub makefile_pl_path {
286 59 100   59 1 41669 return unless $_[0]->has_makefile_pl;
287              
288 58         257 File::Spec->catfile( $_[0]->dist_dir, $_[0]->makefile_pl );
289             }
290              
291             =item build_pl_path
292              
293             =cut
294              
295             sub build_pl_path {
296 37 100   37 1 1383 return unless $_[0]->has_build_pl;
297              
298 34         165 File::Spec->catfile( $_[0]->dist_dir, $_[0]->build_pl );
299             }
300              
301             =item has_build_pl
302              
303             Has the file name returned by C.
304              
305             =cut
306              
307             sub _has_file {
308 473     473   1239 my( $self, $file ) = @_;
309              
310 473         1392 my $path = File::Spec->catfile(
311             $self->dist_dir, $file
312             );
313              
314 473 100       9205 $self->{has}{$file} = $path if -e $path;
315 473         4777 $self->{has}{$file};
316             }
317              
318 217     217 1 6237 sub has_build_pl { $_[0]->_has_file( $_[0]->build_pl ) }
319              
320             =item has_makefile_pl
321              
322             Has the file name returned by C.
323              
324             =cut
325              
326 256     256 1 7339 sub has_makefile_pl { $_[0]->_has_file( $_[0]->makefile_pl ) }
327              
328             =item has_build_and_makefile
329              
330             Has both the files returned by C and C.
331              
332             =cut
333              
334             sub has_build_and_makefile {
335 10 100   10 1 3787 $_[0]->has_build_pl
336             &&
337             $_[0]->has_makefile_pl
338             }
339              
340             =item make_command
341              
342             Looks in %Config to see what perl discovered when someone built it if you
343             can use a C variant to build the distribution.
344              
345             =cut
346              
347 29 100   29 1 2431 sub make_command { $_[0]->has_makefile_pl ? $Config{make} : () }
348              
349             =item build_command
350              
351             Returns C<./Build>, the script that F should have created, if
352             the distribution has a F. Otherwise it returns nothing.
353              
354             =cut
355              
356 18 50   18 1 63 sub build_command { $_[0]->has_build_pl ? './Build' : () }
357              
358             =item perl_command
359              
360             Returns the perl currently running. This is the perl that you would use
361             to run the F or F.
362              
363             =cut
364              
365 7 100   7 1 24 sub perl_command { $_[0]->has_build_pl ? $_[0]->perl_binary : () }
366              
367             =item build_commands
368              
369             Returns a hash reference of the commands you can use to build the
370             distribution. The keys are the commands, such as C or C.
371              
372             =cut
373              
374              
375             sub build_commands {
376 10     10 1 1265 my %commands;
377              
378 10 100       44 $commands{ $_[0]->make_command } = 1
379             if $_[0]->has_makefile_pl;
380              
381 10 100       57 $commands{ $_[0]->perl_command . " " . $_[0]->build_pl } = 1
382             if $_[0]->has_build_pl;
383              
384 10         89 return \%commands;
385             }
386              
387             =item uses_makemaker
388              
389             Returns true if the distro uses C.
390              
391             =cut
392              
393             sub _get_modules {
394 68     68   303 my( $self, $path ) = @_;
395 68         363 my $extractor = $self->module_extractor_class->new;
396 68         1805 $extractor->get_modules( $path );
397             }
398              
399             sub uses_makemaker {
400 30 100   30 1 62437 return unless $_[0]->has_makefile_pl;
401              
402 22         158 scalar grep { $_ eq $_[0]->makemaker_name }
  40         903204  
403             $_[0]->_get_modules( $_[0]->makefile_pl_path )
404             }
405              
406             =item uses_makemaker_only
407              
408             Returns true if MakeMaker is the only build system. Knowing that can cut
409             down on the logic quite a bit since you don't have to choose between
410             possibilities or preferences.
411              
412             =cut
413              
414             sub uses_makemaker_only {
415 36 100   36 1 1082 return unless $_[0]->has_makefile_pl;
416 27 100       112 return if $_[0]->has_build_pl;
417              
418 15         77 return 1;
419             }
420              
421             =item makemaker_version
422              
423             Returns the version of Makemaker installed for the perl running this code.
424              
425             =cut
426              
427             sub makemaker_version {
428 5 100   5 1 870 return unless $_[0]->uses_makemaker;
429              
430 1         4 my $version = $_[0]->_get_version( $_[0]->makemaker_name );
431             }
432              
433             sub _get_version {
434 3     3   61 require Module::Extract::VERSION;
435              
436 3         23 my( $self, $module, @dirs ) = @_;
437              
438 3 100       28 @dirs = @INC unless @dirs;
439              
440 3         44 my $file = catfile( split /::/, $module ) . ".pm";
441              
442 3         12 my $found_module = 0;
443 3         26 foreach my $dir ( @dirs ) {
444 19         111 my $module = catfile( $dir, $file );
445 19 100       388 next unless -e $module;
446              
447 3         18 $found_module = 1;
448 3         47 return Module::Extract::VERSION->parse_version_safely( $module );
449             }
450              
451 0 0       0 return '$module not installed' unless $found_module;
452 0         0 return;
453             }
454              
455             =item uses_module_build
456              
457             Returns true if this distribution uses C. This means that it
458             has a F and that the F actually uses C.
459              
460             =cut
461              
462             sub uses_module_build {
463 37 100   37 1 1298 return unless $_[0]->has_build_pl;
464              
465 25         178 scalar grep { $_ eq $_[0]->module_build_name }
  18         640403  
466             $_[0]->_get_modules( $_[0]->build_pl_path );
467             }
468              
469             =item uses_module_build_only
470              
471             Returns true if C is the only build system. Knowing that can cut
472             down on the logic quite a bit since you don't have to choose between
473             possibilities or preferences.
474              
475             =cut
476              
477             sub uses_module_build_only {
478 25 100   25 1 60128 return unless $_[0]->has_build_pl;
479 22 100       99 return if $_[0]->has_makefile_pl;
480              
481 9         49 return 1;
482             }
483              
484             =item module_build_version
485              
486             Returns the version of C install for perl running this code.
487              
488             =cut
489              
490             sub module_build_version {
491 5 100   5 1 947 return unless $_[0]->uses_module_build;
492              
493 1         8 my $version = $_[0]->_get_version( $_[0]->module_build_name );
494             }
495              
496             =item uses_module_install
497              
498             Returns true if this distribution uses C.
499              
500             =cut
501              
502             sub uses_module_install {
503 24 100   24 1 6222 return unless $_[0]->has_makefile_pl;
504              
505 21         137 scalar grep { $_ eq $_[0]->module_install_name }
  48         983609  
506             $_[0]->_get_modules( $_[0]->makefile_pl_path )
507             }
508              
509             =item uses_auto_install
510              
511             Returns true if this distribution uses C and will
512             use the auto_install feature.
513              
514             This is a very simple test right now. If it finds the string
515             C in the build file, it returns true.
516              
517             =cut
518              
519             sub uses_auto_install {
520 10 100 100 10 1 3443 return unless $_[0]->has_makefile_pl && $_[0]->uses_module_install;
521              
522 2         14 $_[0]->_file_has_string( $_[0]->makefile_pl_path, 'auto_install' );
523             }
524              
525             =item module_install_version
526              
527             Returns the version of C.
528              
529             =cut
530              
531             sub module_install_version {
532 6 100   6 1 1812 return unless $_[0]->uses_module_install;
533              
534 1         7 my $version = $_[0]->_get_version(
535             $_[0]->module_install_name, $_[0]->module_install_dir
536             );
537             }
538              
539             =item uses_module_build_compat
540              
541             Returns true if this distribution uses C and will
542             use the C feature.
543              
544             This is a very simple test right now. If it finds the string
545             C in the build file, it returns true.
546              
547             =cut
548              
549             sub uses_module_build_compat {
550 10 100 100 10 1 4568 return unless $_[0]->has_build_pl && $_[0]->uses_module_build;
551              
552 3         32 $_[0]->_file_has_string( $_[0]->build_pl_path, 'create_makefile_pl' );
553             }
554              
555             =item build_pl_wraps_makefile_pl
556              
557             Returns true if C is a wrapper around C.
558              
559             =cut
560              
561             sub build_pl_wraps_makefile_pl {
562 5 100 100 5 1 691 return unless $_[0]->has_build_pl && $_[0]->has_makefile_pl;
563              
564 1         13 $_[0]->_file_has_string( $_[0]->build_pl_path,
565             "Makefile.PL" );
566             }
567              
568             sub _file_has_string {
569 13     13   5039 my $fh;
570 13 100       581 unless( open $fh, "<", $_[1] ) {
571 1         245 carp "Could not open $_[1]: $!";
572 1         8 return;
573             }
574              
575 12 100       334 while( <$fh> ) { return 1 if /\Q$_[2]/ }
  128         786  
576              
577 6         118 return;
578             }
579              
580             =item just_give_me_a_hash
581              
582             =cut
583              
584             {
585             my @methods = qw(
586             dist_dir
587             build_files
588             build_file_paths
589             makefile_pl_path
590             build_pl_path
591             has_build_pl
592             has_makefile_pl
593             has_build_and_makefile
594             make_command
595             perl_command
596             build_commands
597             uses_makemaker
598             makemaker_version
599             uses_module_build
600             module_build_version
601             uses_module_install
602             uses_auto_install
603             module_install_version
604             uses_module_build_compat
605             build_pl_wraps_makefile_pl
606             );
607              
608             sub just_give_me_a_hash {
609 3     3 1 4350 my %hash = ();
610              
611 3         15 foreach my $method ( @methods ) {
612 60         305 $hash{ $method } = $_[0]->$method();
613             }
614              
615 3         17 return \%hash;
616             }
617             }
618              
619             =back
620              
621             =head2 Methods for strings
622              
623             You may want to override or extend these, so they are methods.
624              
625             =over 4
626              
627             =item makefile_pl
628              
629             Returns the string used for the Makefile.PL filename. Seems stupid
630             until you want to change it in a subclass, which you can do now
631             that it's a method. :)
632              
633             =cut
634              
635 385     385 1 7426 sub makefile_pl { 'Makefile.PL' }
636              
637             =item build_pl
638              
639             Returns the string used for the Build.PL filename. Seems stupid
640             until you want to change it in a subclass, which you can do now
641             that it's a method. :)
642              
643             =cut
644              
645 308     308 1 4361 sub build_pl { 'Build.PL' }
646              
647             =item makemaker_name
648              
649             Returns the module name of Makemaker, which is C.
650              
651             =cut
652              
653 41     41 1 323 sub makemaker_name { 'ExtUtils::MakeMaker' }
654              
655             =item module_build_name
656              
657             Return the string representing the name for Module::Build.
658              
659             =cut
660              
661 19     19 1 304 sub module_build_name { 'Module::Build' }
662              
663             =item module_install_name
664              
665             Return the string representing the name for Module::Install. By default
666             this is C.
667              
668             =cut
669              
670 49     49 1 357 sub module_install_name { 'inc::Module::Install' }
671              
672             =item module_install_dir
673              
674             Returns the directory that contains Module::Install. This is the distribution
675             directory because the module name is actually C.
676              
677             =cut
678              
679 1     1 1 8 sub module_install_dir { $_[0]->dist_dir }
680              
681             =item module_extractor_class
682              
683             The name of the module that can get a list of used modules from a Perl file.
684             By default this is Module::Extract::Use.
685              
686             =cut
687              
688 68     68 1 735 sub module_extractor_class { 'Module::Extract::Use' }
689 12     12   6361 BEGIN { require Module::Extract::Use }
690              
691             =back
692              
693             =head1 TO DO
694              
695              
696             =head1 SEE ALSO
697              
698              
699             =head1 SOURCE AVAILABILITY
700              
701             This source is in Github:
702              
703             git://github.com/briandfoy/distribution-guess-buildsystem.git
704              
705             =head1 AUTHOR
706              
707             brian d foy, C<< >>
708              
709             =head1 COPYRIGHT AND LICENSE
710              
711             Copyright © 2008-2018, brian d foy . All rights reserved.
712              
713             You may redistribute this under the terms of the Artistic License 2.0.
714              
715             =cut
716              
717             1;